public inbox for frysk-cvs@sourceware.org
help / color / mirror / Atom feed
From: cagney@sourceware.org
To: frysk-cvs@sourceware.org
Subject: [SCM]  master: Replace JNIEnv* with C++ jnixx::env& wrapper.
Date: Mon, 05 May 2008 15:07:00 -0000	[thread overview]
Message-ID: <20080505150736.11810.qmail@sourceware.org> (raw)

The branch, master has been updated
       via  0affa135c67c130681293a5b5f28ef4fcd8d4d34 (commit)
      from  f34e0e28d1e06376968f23cefcdce18ce037b27c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 0affa135c67c130681293a5b5f28ef4fcd8d4d34
Author: Andrew Cagney <cagney@redhat.com>
Date:   Mon May 5 11:05:38 2008 -0400

    Replace JNIEnv* with C++ jnixx::env& wrapper.
    
    frysk-sys/frysk/jnixx/ChangeLog
    2008-05-05  Andrew Cagney  <cagney@redhat.com>
    
    	* jnixx.hxx: New.
    	* Printer.java: Generate jnixx::env& instead of JNIEnv*, and
    	jnixx::exception instead of jnixx_exception.
    	* PrintDefinitions.java: Ditto.
    	* PrintDeclarations.java: Ditto.
    	* Main.java: Generate #include jnixx.hxx instead of xx.hxx.
    	* print.hxx: Use jnixx.hxx; replace JNIEnv* with jnixx::env&.
    	* print.cxx: Ditto.
    	* exceptions.hxx: Ditto.
    
    frysk-sys/frysk/rsl/ChangeLog
    2008-05-05  Andrew Cagney  <cagney@redhat.com>
    
    	* jni/Log.hxx: Replace JNIEnv* with jnixx::&.
    	* jni/Log.cxx: Ditto.
    
    frysk-sys/frysk/sys/ChangeLog
    2008-05-05  Andrew Cagney  <cagney@redhat.com>
    
    	* jni/Pid.cxx: Update; use jnixx::env&.
    	* jni/Tid.cxx: Ditto.
    	* jni/Signal.cxx-sh: Ditto.
    	* jni/PseudoTerminal.cxx: Ditto.
    
    frysk-sys/lib/stdcpp/ChangeLog
    2008-05-05  Andrew Cagney  <cagney@redhat.com>
    
    	* jni/Demangler.cxx: Replace JNIEnv* with jnixx::env&.

-----------------------------------------------------------------------

Summary of changes:
 frysk-sys/frysk/jnixx/ChangeLog              |   12 +
 frysk-sys/frysk/jnixx/Main.java              |    2 +-
 frysk-sys/frysk/jnixx/PrintDeclarations.java |    4 +-
 frysk-sys/frysk/jnixx/PrintDefinitions.java  |   59 ++--
 frysk-sys/frysk/jnixx/Printer.java           |    6 +-
 frysk-sys/frysk/jnixx/exceptions.cxx         |   40 +-
 frysk-sys/frysk/jnixx/exceptions.hxx         |    6 +-
 frysk-sys/frysk/jnixx/jnixx.hxx              |  558 ++++++++++++++++++++++++++
 frysk-sys/frysk/jnixx/print.cxx              |   11 +-
 frysk-sys/frysk/jnixx/print.hxx              |    4 +-
 frysk-sys/frysk/rsl/ChangeLog                |    5 +
 frysk-sys/frysk/rsl/jni/Log.cxx              |   13 +-
 frysk-sys/frysk/rsl/jni/Log.hxx              |   12 +-
 frysk-sys/frysk/sys/ChangeLog                |    7 +
 frysk-sys/frysk/sys/jni/Pid.cxx              |    4 +-
 frysk-sys/frysk/sys/jni/PseudoTerminal.cxx   |    6 +-
 frysk-sys/frysk/sys/jni/Signal.cxx-sh        |   22 +-
 frysk-sys/frysk/sys/jni/Tid.cxx              |    2 +-
 frysk-sys/lib/stdcpp/ChangeLog               |    4 +
 frysk-sys/lib/stdcpp/jni/Demangler.cxx       |   12 +-
 20 files changed, 686 insertions(+), 103 deletions(-)
 create mode 100644 frysk-sys/frysk/jnixx/jnixx.hxx

First 500 lines of diff:
diff --git a/frysk-sys/frysk/jnixx/ChangeLog b/frysk-sys/frysk/jnixx/ChangeLog
index dc7e4d6..1308064 100644
--- a/frysk-sys/frysk/jnixx/ChangeLog
+++ b/frysk-sys/frysk/jnixx/ChangeLog
@@ -1,3 +1,15 @@
+2008-05-05  Andrew Cagney  <cagney@redhat.com>
+
+	* jnixx.hxx: New.
+	* Printer.java: Generate jnixx::env& instead of JNIEnv*, and
+	jnixx::exception instead of jnixx_exception.
+	* PrintDefinitions.java: Ditto.
+	* PrintDeclarations.java: Ditto.
+	* Main.java: Generate #include jnixx.hxx instead of xx.hxx. 
+	* print.hxx: Use jnixx.hxx; replace JNIEnv* with jnixx::env&.
+	* print.cxx: Ditto.
+	* exceptions.hxx: Ditto.
+	
 2008-05-02  Andrew Cagney  <cagney@redhat.com>
 
 	* jnixx.java: Refactor into ...
diff --git a/frysk-sys/frysk/jnixx/Main.java b/frysk-sys/frysk/jnixx/Main.java
index c030532..52372a1 100644
--- a/frysk-sys/frysk/jnixx/Main.java
+++ b/frysk-sys/frysk/jnixx/Main.java
@@ -46,7 +46,7 @@ class Main {
 	p.println("#ifndef " + header);
 	p.println("#define " + header);
 	p.println();
-	p.println("#include \"frysk/jnixx/xx.hxx\"");
+	p.println("#include \"frysk/jnixx/jnixx.hxx\"");
 	WalkClass.visit(klass, new PrintNamespaces(p));
 	p.println();
 	Class parent = klass.getSuperclass();
diff --git a/frysk-sys/frysk/jnixx/PrintDeclarations.java b/frysk-sys/frysk/jnixx/PrintDeclarations.java
index 30f14d9..a077417 100644
--- a/frysk-sys/frysk/jnixx/PrintDeclarations.java
+++ b/frysk-sys/frysk/jnixx/PrintDeclarations.java
@@ -54,7 +54,7 @@ class PrintDeclarations implements ClassWalker {
     public boolean acceptClass(Class klass) {
 	// Static get-class method - a class knows its own class.
 	p.println();
-	p.print("  public: static jclass Class(JNIEnv* env);");
+	p.print("  public: static jclass Class(jnixx::env& env);");
 	return true;
     }
 
@@ -81,7 +81,7 @@ class PrintDeclarations implements ClassWalker {
 	String name = field.getName();
 	p.print(Character.toUpperCase(name.charAt(0)));
 	p.print(name.substring(1));
-	p.print("(JNIEnv*");
+	p.print("(jnixx::env&");
 	if (!Modifier.isStatic(field.getModifiers())) {
 	    p.print(", ");
 	    p.printCxxType(field.getDeclaringClass());
diff --git a/frysk-sys/frysk/jnixx/PrintDefinitions.java b/frysk-sys/frysk/jnixx/PrintDefinitions.java
index 42f6de6..24234fa 100644
--- a/frysk-sys/frysk/jnixx/PrintDefinitions.java
+++ b/frysk-sys/frysk/jnixx/PrintDefinitions.java
@@ -58,9 +58,9 @@ class PrintDefinitions implements ClassWalker {
 	p.println();
 	p.println("jclass");
 	p.printQualifiedCxxName(klass);
-	p.println("::Class(JNIEnv* env) {");
+	p.println("::Class(jnixx::env& env) {");
 	p.println("  if (_Class == NULL) {");
-	p.println("    _Class = findClass(env, \""
+	p.println("    _Class = env.findClass(\""
 		+ klass.getName().replace("\\.", "/") + "\");");
 	p.println("  }");
 	p.println("  return _Class;");
@@ -78,23 +78,24 @@ class PrintDefinitions implements ClassWalker {
 	p.println(") {");
 	p.println("  static jmethodID id;");
 	p.println("  if (id == NULL)");
-	p.print("    id = getMethodID(env, Class(env), \"<init>\", \"(");
+	p.print("    id = env.getMethodID(Class(env), \"<init>\", \"(");
 	p.printJniSignature(constructor.getParameterTypes());
 	p.println(")V\");");
 	p.print("  ");
 	p.printCxxType(constructor.getDeclaringClass());
 	p.print(" object = (");
 	p.printCxxType(constructor.getDeclaringClass());
-	p.print(") env->NewObject(");
+	p.print(") env.newObject(");
 	p.printActualJniParameters(constructor);
 	p.println(");");
 	p.println("  if (object == NULL)");
-	p.println("    throw jnixx_exception();");
+	p.println("    throw jnixx::exception();");
 	p.println("  return object;");
 	p.println("}");
     }
 
     private void printCxxFieldAccessorDefinition(Field field, boolean get) {
+	boolean isStatic = Modifier.isStatic(field.getModifiers());
 	p.println();
 	if (get) {
 	    p.printCxxType(field.getType());
@@ -112,8 +113,8 @@ class PrintDefinitions implements ClassWalker {
 	String name = field.getName();
 	p.print(Character.toUpperCase(name.charAt(0)));
 	p.print(name.substring(1));
-	p.print("(JNIEnv* env");
-	if (!Modifier.isStatic(field.getModifiers())) {
+	p.print("(jnixx::env& env");
+	if (!isStatic) {
 	    p.print(", ");
 	    p.printCxxType(field.getDeclaringClass());
 	    p.print(" object");
@@ -125,14 +126,13 @@ class PrintDefinitions implements ClassWalker {
 	}
 	p.println(") {");
 	p.println("  if (" + name + "ID == NULL) {");
-	p.print("    " + name + "ID = getFieldID(env, ");
-	if (Modifier.isStatic(field.getModifiers())) {
-	    p.print("Class(env)");
-	} else {
-	    p.print("object");
+	p.print("    " + name + "ID = env.get");
+	if (isStatic) {
+	    p.print("Static");
 	}
-	p.print(", \"" + name + "\"");
-	p.print(", \"");
+	p.print("FieldID(Class(env), \"");
+	p.print(name);
+	p.print("\", \"");
 	p.printJniSignature(field.getType());
 	p.print("\"");
 	p.println(");");
@@ -144,16 +144,16 @@ class PrintDefinitions implements ClassWalker {
 		p.printCxxType(field.getType());
 		p.print(")");
 	    }
-	    p.print(" env->Get");
+	    p.print(" env.get");
 	} else {
-	    p.print("  env->Set");
+	    p.print("  env.set");
 	}
-	if (Modifier.isStatic(field.getModifiers())) {
+	if (isStatic) {
 	    p.print("Static");
 	}
 	p.printJniReturnTypeName(field.getType());
 	p.print("Field(");
-	if (Modifier.isStatic(field.getModifiers())) {
+	if (isStatic) {
 	    p.print("_Class");
 	} else {
 	    p.print("object");
@@ -182,6 +182,7 @@ class PrintDefinitions implements ClassWalker {
     }
 
     private void printCxxMethodDefinition(Method method) {
+	boolean isStatic = Modifier.isStatic(method.getModifiers());
 	Class returnType = method.getReturnType();
 	p.println();
 	p.printCxxType(returnType);
@@ -191,17 +192,15 @@ class PrintDefinitions implements ClassWalker {
 	p.print(method.getName());
 	p.print("(");
 	p.printFormalCxxParameters(method, true);
-	p.print(") {");
+	p.println(") {");
 	p.println();
 	p.println("  static jmethodID id;");
 	p.println("  if (id == NULL)");
-	p.print("    id = getMethodID(env");
-	if (Modifier.isStatic(method.getModifiers())) {
-	    p.print(", Class(env)");
-	} else {
-	    p.print(", object");
+	p.print("    id = env.get");
+	if (isStatic) {
+	    p.print("Static");
 	}
-	p.print(", \"");
+	p.print("MethodID(Class(env), \"");
 	p.print(method.getName());
 	p.print("\", \"");
 	p.printJniSignature(method);
@@ -216,15 +215,14 @@ class PrintDefinitions implements ClassWalker {
 		p.print(") ");
 	    }
 	}
-	p.print("env->Call");
-	if (Modifier.isStatic(method.getModifiers()))
+	p.print("env.call");
+	if (isStatic) {
 	    p.print("Static");
+	}
 	p.printJniReturnTypeName(returnType);
 	p.print("Method(");
 	p.printActualJniParameters(method);
 	p.println(");");
-	p.println("  if (env->ExceptionCheck())");
-	p.println("    throw jnixx_exception();");
 	if (returnType != Void.TYPE) {
 	    p.println("  return ret;");
 	}
@@ -250,6 +248,7 @@ class PrintDefinitions implements ClassWalker {
 	p.printFormalJniParameters(method, true);
 	p.println(") {");
 	p.println("  try {");
+	p.println("    jnixx::env jnixxEnv = jnixx::env(jniEnv);");
 	p.print("    ");
 	if (method.getReturnType() != Void.TYPE) {
 	    p.print("return ");
@@ -258,7 +257,7 @@ class PrintDefinitions implements ClassWalker {
 	p.print("(");
 	p.printActualCxxParameters(method);
 	p.println(");");
-	p.println("  } catch (jnixx_exception) {");
+	p.println("  } catch (jnixx::exception) {");
 	if (method.getReturnType() != Void.TYPE) {
 	    p.println("    return 0;");
 	}
diff --git a/frysk-sys/frysk/jnixx/Printer.java b/frysk-sys/frysk/jnixx/Printer.java
index 7b54fca..ef3aaa6 100644
--- a/frysk-sys/frysk/jnixx/Printer.java
+++ b/frysk-sys/frysk/jnixx/Printer.java
@@ -302,7 +302,7 @@ class Printer {
     private Printer printFormalCxxParameters(Class klass, Class[] params,
 					     boolean isStatic,
 					     boolean printArgs) {
-	print("JNIEnv*");
+	print("jnixx::env&");
 	if (printArgs)
 	    print(" env");
 	if (!isStatic) {
@@ -344,7 +344,7 @@ class Printer {
      */
     private Printer printActualCxxParameters(Member func,
 					     Class[] params) {
-	print("env");
+	print("jnixxEnv");
 	if (!Modifier.isStatic(func.getModifiers())) {
 	    print(", object");
 	}
@@ -373,7 +373,7 @@ class Printer {
     Printer printFormalJniParameters(Method method, boolean printArgs) {
 	print("JNIEnv*");
 	if (printArgs)
-	    print(" env");
+	    print(" jniEnv");
 	if (Modifier.isStatic(method.getModifiers())) {
 	    print(", jclass");
 	    if (printArgs)
diff --git a/frysk-sys/frysk/jnixx/exceptions.cxx b/frysk-sys/frysk/jnixx/exceptions.cxx
index ef52e98..6e2b340 100644
--- a/frysk-sys/frysk/jnixx/exceptions.cxx
+++ b/frysk-sys/frysk/jnixx/exceptions.cxx
@@ -43,20 +43,18 @@
 #include <errno.h>
 #include <stdlib.h>
 
-#include <jni.h>
-
-#include "frysk/jnixx/xx.hxx"
+#include "frysk/jnixx/jnixx.hxx"
 #include "frysk/jnixx/exceptions.hxx"
 
 void
-errnoException(JNIEnv *env, int error, const char *prefix) {
+errnoException(jnixx::env& env, int error, const char *prefix) {
   // Hack; for moment just throw something.
   runtimeException(env, "not implemented: %s#%d#%s",
 		   __FILE__, __LINE__, __func__);
 }
 
 void
-errnoException(JNIEnv *env, int error, const char *prefix,
+errnoException(jnixx::env& env, int error, const char *prefix,
 	       const char *fmt, ...) {
   // Hack; for moment just throw something.
   runtimeException(env, "not implemented: %s#%d#%s",
@@ -64,20 +62,24 @@ errnoException(JNIEnv *env, int error, const char *prefix,
 }
 
 void
-runtimeException(JNIEnv *env, const char *fmt, ...) {
-  jclass cls = env->FindClass("java/lang/RuntimeException");
-  if (cls != NULL) {
-    va_list ap;
-    va_start(ap, fmt);
-    char *msg = NULL;
-    if (::vasprintf(&msg, fmt, ap) < 0) {
-      fprintf(stderr, "runtimeException: vasprintf failed: %s",
-	      ::strerror(errno));
-      env->ThrowNew(cls, "runtimeException: vasprintf failed");
-    }
-    env->ThrowNew(cls, msg);
+runtimeException(jnixx::env& env, const char *fmt, ...) {
+  jclass cls = env.findClass("java/lang/RuntimeException");
+  va_list ap;
+  va_start(ap, fmt);
+  char *msg = NULL;
+  int status = ::vasprintf(&msg, fmt, ap);
+  va_end(ap);
+  if (status < 0) {
+    fprintf(stderr, "runtimeException: vasprintf failed: %s",
+	    ::strerror(errno));
+    env.throwNew(cls, "runtimeException: vasprintf failed");
+  }
+  try {
+    env.throwNew(cls, msg);
+  } catch (jnixx::exception e) {
+    // XXX: Work around lack of finally by catchching, then
+    // re-throwing, the exception
     ::free(msg);
-    va_end(ap);
+    throw e;
   }
-  throw jnixx_exception();
 }
diff --git a/frysk-sys/frysk/jnixx/exceptions.hxx b/frysk-sys/frysk/jnixx/exceptions.hxx
index 0deb3a4..8173b02 100644
--- a/frysk-sys/frysk/jnixx/exceptions.hxx
+++ b/frysk-sys/frysk/jnixx/exceptions.hxx
@@ -42,13 +42,13 @@
  * code return.
  */
 
-extern void errnoException(JNIEnv *env, int error, const char *prefix)
+extern void errnoException(jnixx::env& env, int error, const char *prefix)
   __attribute__((noreturn));
-extern void errnoException(JNIEnv *env, int error, const char *prefix,
+extern void errnoException(jnixx::env& env, int error, const char *prefix,
 			   const char *fmt, ...)
   __attribute__((noreturn))
   __attribute__((format (printf, 4, 5)));
 
-extern void runtimeException(JNIEnv *env, const char *fmt, ...)
+extern void runtimeException(jnixx::env& env, const char *fmt, ...)
   __attribute__((noreturn))
   __attribute__((format (printf, 2, 3)));
diff --git a/frysk-sys/frysk/jnixx/jnixx.hxx b/frysk-sys/frysk/jnixx/jnixx.hxx
new file mode 100644
index 0000000..6859940
--- /dev/null
+++ b/frysk-sys/frysk/jnixx/jnixx.hxx
@@ -0,0 +1,558 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2008, Red Hat Inc.
+//
+// FRYSK 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; version 2 of the License.
+//
+// FRYSK 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 FRYSK; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+// 
+// In addition, as a special exception, Red Hat, Inc. gives You the
+// additional right to link the code of FRYSK with code not covered
+// under the GNU General Public License ("Non-GPL Code") and to
+// distribute linked combinations including the two, subject to the
+// limitations in this paragraph. Non-GPL Code permitted under this
+// exception must only link to the code of FRYSK through those well
+// defined interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved Interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved Interfaces without causing the
+// resulting work to be covered by the GNU General Public
+// License. Only Red Hat, Inc. may make changes or additions to the
+// list of Approved Interfaces. You must obey the GNU General Public
+// License in all respects for all of the FRYSK code and other code
+// used in conjunction with FRYSK except the Non-GPL Code covered by
+// this exception. If you modify this file, you may extend this
+// exception to your version of the file, but you are not obligated to
+// do so. If you do not wish to provide this exception without
+// modification, you must delete this exception statement from your
+// version and license this file solely under the GPL without
+// exception.
+
+#ifndef frysk_jnixx_hxx
+#define frysk_jnixx_hxx
+
+#include <jni.h>
+#include <stdarg.h>
+
+struct __jstringArray : public __jobjectArray {
+};
+typedef __jstringArray* jstringArray;
+
+namespace jnixx {
+  class exception;
+  class env;
+}
+
+class jnixx::exception {
+};
+
+class jnixx::env {
+
+private:
+  JNIEnv* jniEnv;
+
+public:
+  env(JNIEnv* jniEnv) {
+    this->jniEnv = jniEnv;
+  }
+
+  jclass findClass(const char signature[]) {
+    jclass klass = jniEnv->FindClass(signature);
+    if (klass == NULL) {
+      fprintf(stderr,
+	      "frysk: JNIEnv.FindClass(\"%s\") failed\n",
+	      signature);
+      throw jnixx::exception();
+    }
+    return klass;
+  }
+
+  jstring newStringUTF(const char string[]) {
+    jstring utf = jniEnv->NewStringUTF(string);
+    if (utf == NULL) {
+      fprintf(stderr,
+	      "frysk: JNIEnv.NewStringUTF(\"%s\") failed\n",
+	      string);
+      throw jnixx::exception();
+    }
+    return utf;
+  }
+
+  const char* getStringUTFChars(jstring string, jboolean* isCopy) {
+    const char* chars = jniEnv->GetStringUTFChars(string, isCopy);
+    if (chars == NULL) {
+      fprintf(stderr,
+	      "frysk: JNIEnv.GetStringUTFChars(%p,%s) failed\n",
+	      string,
+	      isCopy == NULL ? "<null>" : (*isCopy ? "<true>" : "<false>"));
+      throw jnixx::exception();
+    }
+    return chars;
+  }
+
+  void releaseStringUTFChars(jstring string, const char* chars) {
+    jniEnv->ReleaseStringUTFChars(string, chars);
+    if (jniEnv->ExceptionCheck()) {
+      fprintf(stderr,
+	      "frysk: JNIEnv.ReleaseStringUTFChars(%p,%s) failed\n",
+	      string, chars);
+      throw jnixx::exception();
+    }
+  }
+
+  jmethodID getMethodID(jclass klass, const char name[],
+			const char signature[]) {
+    jmethodID methodID = jniEnv->GetMethodID(klass, name, signature);
+    if (methodID == NULL) {
+      fprintf(stderr,
+	      "frysk: JNIEnv.GetMethodID(%p,\"%s\",\"%s\") failed\n",
+	      klass, name, signature);
+      throw jnixx::exception();
+    }
+    return methodID;
+  }
+  jmethodID getStaticMethodID(jclass klass, const char name[],
+			      const char signature[]) {
+    jmethodID methodID = jniEnv->GetStaticMethodID(klass, name, signature);
+    if (methodID == NULL) {
+      fprintf(stderr,
+	      "frysk: JNIEnv.GetStaticMethodID(%p,\"%s\",\"%s\") failed\n",
+	      klass, name, signature);
+      throw jnixx::exception();
+    }
+    return methodID;
+  }
+
+  jfieldID getFieldID(jclass klass, const char name[],
+		      const char signature[]) {
+    jfieldID fieldID = jniEnv->GetFieldID(klass, name, signature);
+    if (fieldID == NULL) {
+      fprintf(stderr,
+	      "frysk: JNIEnv.GetFieldID(%p,\"%s\",\"%s\") failed\n",
+	      klass, name, signature);
+      throw jnixx::exception();
+    }
+    return fieldID;
+  }
+  jfieldID getStaticFieldID(jclass klass, const char name[],
+			    const char signature[]) {
+    jfieldID fieldID = jniEnv->GetStaticFieldID(klass, name, signature);
+    if (fieldID == NULL) {
+      fprintf(stderr,
+	      "frysk: JNIEnv.GetStaticFieldID(%p,\"%s\",\"%s\") failed\n",
+	      klass, name, signature);
+      throw jnixx::exception();
+    }
+    return fieldID;
+  }


hooks/post-receive
--
frysk system monitor/debugger


                 reply	other threads:[~2008-05-05 15:07 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080505150736.11810.qmail@sourceware.org \
    --to=cagney@sourceware.org \
    --cc=frysk-cvs@sourceware.org \
    --cc=frysk@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).