public inbox for rda@sourceware.org
 help / color / mirror / Atom feed
* [RFC] Revise interfaces for *_bytes_{from,to}_reg()
@ 2002-11-27 10:33 Kevin Buettner
  2002-11-27 10:49 ` Kevin Buettner
  0 siblings, 1 reply; 3+ messages in thread
From: Kevin Buettner @ 2002-11-27 10:33 UTC (permalink / raw)
  To: rda

I recently discovered that rda (on Linux/MIPS) didn't work correctly when
the space allocated to hold a register for the remote protocol is larger
than that required by the ptrace interface.  (In a GDB configured for a
mips64 target, I was seeing the (32-bit) register contents in the most
significant 32-bits.)

The patch below revises the gdbserv_{be,le,host}_bytes_{to,from}_reg()
interfaces so that the correct padding/truncation occurs when the source
and destination sizes differ.  (I've thought about the problem of sign
extension on MIPS, but I'm punting on it for now.)

I'm not sure what the checkin policies are for RDA.  I assume I need
approval for gdbserv-utils.[hc].

In ChangeLog:
	* include/gdbserv-utils.h, lib/gdbserv-utils.c
	(gdbserv_be_bytes_to_reg, gdbserv_le_bytes_to_reg)
	(gdbserv_be_bytes_from_reg, gdbserv_le_bytes_from_reg)
	(gdbserv_host_bytes_to_reg, gdbserv_host_bytes_from_reg):
	Revise interfaces.

In unix/ChangeLog:

	* linux-target.c (linux_get_reg, linux_set_reg, reg_from_regset)
	(reg_to_regset, get_regset, put_regset reg_from_gregset)
	(reg_to_gregset, reg_from_fpregset, reg_to_fpregset)
	(reg_from_xregset, reg_to_xregset): Adjust all calls to
	gdbserv_host_bytes_to_reg() and gdbserv_host_bytes_from_reg()
	to account for change in interface.  Remove code which is
	no longer needed due to improvements in the aforementioned
	functions.

Index: include/gdbserv-utils.h
===================================================================
RCS file: /cvs/src/src/rda/include/gdbserv-utils.h,v
retrieving revision 1.1
diff -u -p -r1.1 gdbserv-utils.h
--- include/gdbserv-utils.h	28 Aug 2002 01:22:27 -0000	1.1
+++ include/gdbserv-utils.h	27 Nov 2002 17:57:17 -0000
@@ -60,42 +60,58 @@ extern void gdbserv_ulonglong_to_reg (st
 				      unsigned long long val,
 				      struct gdbserv_reg *reg);
 
-/* Convert between a REG and a buffer representing a numeric type.
-   Handle big endian and little endian cases explicitly.  */
+/* Convert between a REG and a buffer representing an unsigned numeric
+   type.  Handle big endian and little endian cases explicitly.  When
+   the source buffer is bigger than the destination buffer, the least
+   significant bytes (as appropriate for the endianess) are transferred.
+   When the source buffer is smaller than the destination, the most
+   significant bytes of the destination are padded with zeros.
+   
+   Note that gdbserv_be_bytes_from_reg() and gdbserv_le_bytes_from_reg()
+   have a buffer length parameter, but not a register length
+   parameter.  This is because the register length was obtained from a
+   register packet sent by the debug client.  On the other hand,
+   gdbserv_be_bytes_to_reg() and gdbserv_le_bytes_to_reg() take both a
+   buffer length and the register length.  This is because we're
+   constructing a register (which will likely be sent to the client)
+   of a particular size.  */
 
 extern void gdbserv_be_bytes_to_reg (struct gdbserv *gdbserv,
 		                     const void *buf,
-		                     int len,
-		                     struct gdbserv_reg *reg);
+		                     int buflen,
+		                     struct gdbserv_reg *reg,
+				     int reglen);
 
 extern void gdbserv_le_bytes_to_reg (struct gdbserv *gdbserv,
 		                     const void *buf,
 		                     int len,
-		                     struct gdbserv_reg *reg);
+		                     struct gdbserv_reg *reg,
+				     int reglen);
 
 extern void gdbserv_be_bytes_from_reg (struct gdbserv *gdbserv,
 		                       void *buf,
-		                       int *lenp,
+		                       int buflen,
                                        const struct gdbserv_reg *reg);
 
 extern void gdbserv_le_bytes_from_reg (struct gdbserv *gdbserv,
 		                       void *buf,
-		                       int *lenp,
+		                       int buflen,
                                        const struct gdbserv_reg *reg);
 
-/* Convert between a REG and a buffer representing a native numeric
-   type.  These are just wrappers for the routines above, but are
-   useful nonetheless since they free the caller from having to
+/* Convert between a REG and a buffer representing a native unsigned
+   numeric type.  These are just wrappers for the routines above, but
+   are useful nonetheless since they free the caller from having to
    worry about byte order issues.  */
 
 extern void gdbserv_host_bytes_to_reg (struct gdbserv *gdbserv,
 		                       const void *buf,
-		                       int len,
-		                       struct gdbserv_reg *reg);
+		                       int buflen,
+		                       struct gdbserv_reg *reg,
+				       int reglen);
 
 extern void gdbserv_host_bytes_from_reg (struct gdbserv *gdbserv,
 		                         void *buf,
-		                         int *lenp,
+		                         int buflen,
                                          const struct gdbserv_reg *reg);
 
 #ifdef __cplusplus
Index: lib/gdbserv-utils.c
===================================================================
RCS file: /cvs/src/src/rda/lib/gdbserv-utils.c,v
retrieving revision 1.1
diff -u -p -r1.1 gdbserv-utils.c
--- lib/gdbserv-utils.c	28 Aug 2002 01:22:28 -0000	1.1
+++ lib/gdbserv-utils.c	27 Nov 2002 17:57:17 -0000
@@ -227,67 +227,129 @@ reverse_copy_bytes (void *dest, const vo
 void
 gdbserv_be_bytes_to_reg (struct gdbserv *gdbserv,
 		         const void *buf,
-		         int len,
-		         struct gdbserv_reg *reg)
-{
+		         int buflen,
+		         struct gdbserv_reg *reg,
+			 int reglen)
+{
+  int bufoffset = 0;
+  int regoffset = 0;
+  int len = buflen;
+
   reg->negative_p = 0;
-  reg->len = len;
-  memcpy (reg->buf, buf, len);
+  reg->len = reglen;
+
+  if (reglen > buflen)
+    {
+      memset (reg->buf, 0, reglen - buflen);
+      regoffset = reglen - buflen;
+    }
+
+  if (buflen > reglen)
+    {
+      bufoffset = buflen - reglen;
+      len = reglen;
+    }
+
+  memcpy (reg->buf + regoffset, (char *)buf + bufoffset, len);
 }
 
 void
 gdbserv_be_bytes_from_reg (struct gdbserv *gdbserv,
 		           void *buf,
-		           int *lenp,
+		           int buflen,
                            const struct gdbserv_reg *reg)
 {
-  *lenp = reg->len;
-  memcpy (buf, reg->buf, reg->len);
+  int bufoffset = 0;
+  int regoffset = 0;
+  int len = reg->len;
+
+  if (reg->len > buflen)
+    {
+      regoffset = reg->len - buflen;
+      len = buflen;
+    }
+
+  if (buflen > reg->len)
+    {
+      memset (buf, 0, buflen - reg->len);
+      bufoffset = buflen - reg->len;
+    }
+
+  memcpy ((char *)buf + bufoffset, reg->buf + regoffset, len);
 }
 
 void
 gdbserv_le_bytes_to_reg (struct gdbserv *gdbserv,
 		         const void *buf,
-		         int len,
-		         struct gdbserv_reg *reg)
+		         int buflen,
+		         struct gdbserv_reg *reg,
+			 int reglen)
 {
+  int regoffset = 0;
+  int len = buflen;
+
   reg->negative_p = 0;
-  reg->len = len;
-  reverse_copy_bytes (reg->buf, buf, len);
+  reg->len = reglen;
+
+  if (reglen > buflen)
+    {
+      memset (reg->buf, 0, reglen - buflen);
+      regoffset = reglen - buflen;
+    }
+
+  if (buflen > reglen)
+      len = reglen;
+
+  reverse_copy_bytes (reg->buf + regoffset, buf, len);
 }
 
 void
 gdbserv_le_bytes_from_reg (struct gdbserv *gdbserv,
 		           void *buf,
-		           int *lenp,
+		           int buflen,
                            const struct gdbserv_reg *reg)
 {
-  *lenp = reg->len;
-  reverse_copy_bytes (buf, reg->buf, reg->len);
+  int bufoffset = 0;
+  int regoffset = 0;
+  int len = reg->len;
+
+  if (reg->len > buflen)
+    {
+      regoffset = reg->len - buflen;
+      len = buflen;
+    }
+
+  if (buflen > reg->len)
+    {
+      memset ((char *)buf + reg->len, 0, buflen - reg->len);
+    }
+
+  reverse_copy_bytes (buf, reg->buf + regoffset, reg->len);
 }
 
 void
 gdbserv_host_bytes_to_reg (struct gdbserv *gdbserv,
 		           const void *buf,
-		           int len,
-		           struct gdbserv_reg *reg)
+		           int buflen,
+		           struct gdbserv_reg *reg,
+			   int reglen)
 {
 #ifdef WORDS_BIGENDIAN
-  gdbserv_be_bytes_to_reg (gdbserv, buf, len, reg);
+  gdbserv_be_bytes_to_reg (gdbserv, buf, buflen, reg, reglen);
 #else
-  gdbserv_le_bytes_to_reg (gdbserv, buf, len, reg);
+  gdbserv_le_bytes_to_reg (gdbserv, buf, buflen, reg, reglen);
 #endif
 }
 
 void
 gdbserv_host_bytes_from_reg (struct gdbserv *gdbserv,
 		             void *buf,
-		             int *lenp,
+		             int buflen,
                              const struct gdbserv_reg *reg)
 {
 #ifdef WORDS_BIGENDIAN
-  gdbserv_be_bytes_from_reg (gdbserv, buf, lenp, reg);
+  gdbserv_be_bytes_from_reg (gdbserv, buf, buflen, reg);
 #else
-  gdbserv_le_bytes_from_reg (gdbserv, buf, lenp, reg);
+  gdbserv_le_bytes_from_reg (gdbserv, buf, buflen, reg);
 #endif
 }
Index: unix/linux-target.c
===================================================================
RCS file: /cvs/src/src/rda/unix/linux-target.c,v
retrieving revision 1.1
diff -u -p -r1.1 linux-target.c
--- unix/linux-target.c	28 Aug 2002 01:22:28 -0000	1.1
+++ unix/linux-target.c	27 Nov 2002 17:57:19 -0000
@@ -922,8 +1065,6 @@ linux_get_reg (struct gdbserv *serv, int
       return -1;
     }
 
-  memset (tmp_buf, 0, reginfo[regno].proto_size);
-
   if (reginfo[regno].whichregs != NOREGS)
     {
       /* Get the register value. */
@@ -931,9 +1072,12 @@ linux_get_reg (struct gdbserv *serv, int
       if (status < 0)
 	return -1;	/* fail */
     }
+  else
+    memset (tmp_buf, 0, reginfo[regno].ptrace_size);
 
   /* Copy the bytes to the gdbserv_reg struct.  */
-  gdbserv_host_bytes_to_reg (serv, tmp_buf, reginfo[regno].proto_size, reg);
+  gdbserv_host_bytes_to_reg (serv, tmp_buf, reginfo[regno].ptrace_size,
+                             reg, reginfo[regno].proto_size);
 
   return 0;	/* success */
   
@@ -958,17 +1102,10 @@ linux_set_reg (struct gdbserv *serv, int
       struct child_process *process = gdbserv_target_data (serv);
       char tmp_buf[MAX_REG_SIZE];
       int status;
-      int len;
-
-      /* Clear out a temporary buffer into which to fetch the bytes that
-	 we'll be setting.  We do this in case ptrace_size != proto_size.  */
-      memset (tmp_buf, 0, reginfo[regno].ptrace_size);
 
       /* Copy the bytes from the gdbserv_reg struct to our temporary buffer.  */
-      gdbserv_host_bytes_from_reg (serv, tmp_buf, &len, reg);
-
-      if (len != reginfo[regno].proto_size)
-	return -1;
+      gdbserv_host_bytes_from_reg (serv, tmp_buf, reginfo[regno].ptrace_size,
+                                   reg);
 
       /* Write the child's register. */
       status = write_reg_bytes (process->pid, regno, tmp_buf);
@@ -990,7 +1127,6 @@ reg_from_regset (struct gdbserv *serv, 
 		 const void *regset,
 		 enum regset whichregs)
 {
-  char tmp_buf[MAX_REG_SIZE];
   char *regbytes;
 
   if (regno < 0 || regno >= NUM_REGS 
@@ -1001,10 +1137,8 @@ reg_from_regset (struct gdbserv *serv, 
 
   regbytes = ((char *) regset) + reginfo[regno].regset_field_offset;
 
-  memset (tmp_buf, 0, reginfo[regno].proto_size);
-  memcpy (tmp_buf, regbytes, reginfo[regno].regset_field_size);
-
-  gdbserv_host_bytes_to_reg (serv, tmp_buf, reginfo[regno].proto_size, reg);
+  gdbserv_host_bytes_to_reg (serv, regbytes, reginfo[regno].regset_field_size,
+                             reg, reginfo[regno].proto_size);
 
   return 0;
 }
@@ -1020,9 +1154,7 @@ reg_to_regset (struct gdbserv *serv, 
 	       void *regset,
 	       enum regset whichregs)
 {
-  char tmp_buf[MAX_REG_SIZE];
   char *regbytes;
-  int len;
 
   if (regno < 0 || regno >= NUM_REGS 
       || reginfo[regno].whichregs != whichregs)
@@ -1030,15 +1162,10 @@ reg_to_regset (struct gdbserv *serv, 
       return -1;
     }
 
-  memset (tmp_buf, 0, reginfo[regno].regset_field_size);
-  gdbserv_host_bytes_from_reg (serv, tmp_buf, &len, reg);
-
-  if (len != reginfo[regno].proto_size)
-    return -1;
-
   regbytes = ((char *) regset) + reginfo[regno].regset_field_offset;
 
-  memcpy (regbytes, tmp_buf, reginfo[regno].regset_field_size);
+  gdbserv_host_bytes_from_reg (serv, regbytes, reginfo[regno].regset_field_size,
+    reg);
 
   return 0;
 }
@@ -1137,16 +1264,14 @@ get_regset (struct gdbserv *serv, int pi
 	  struct gdbserv_reg reg;
 	  int status;
 
-	  memset (tmp_buf, 0, reginfo[regno].proto_size);
-
 	  /* Get the register value. */
 	  status = read_reg_bytes (pid, regno, tmp_buf);
 	  if (status < 0)
 	    return -1;	/* fail */
 
 	  /* Copy the bytes to the gdbserv_reg struct.  */
-	  gdbserv_host_bytes_to_reg (serv, tmp_buf,
-	                             reginfo[regno].proto_size, &reg);
+	  gdbserv_host_bytes_to_reg (serv, tmp_buf, reginfo[regno].ptrace_size,
+	                             &reg, reginfo[regno].proto_size);
 
 	  /* Now insert them into the regset.  */
 	  reg_to_regset (serv, &reg, regno, regset, whichregs);
@@ -1173,20 +1298,14 @@ put_regset (struct gdbserv *serv,
 	{
 	  char tmp_buf[MAX_REG_SIZE];
 	  struct gdbserv_reg reg;
-	  int len;
 	  int status;
 
 	  /* Fetch the reg from the regset.  */
 	  reg_from_regset (serv, &reg, regno, regset, whichregs);
 
-	  /* Clear out a temporary buffer into which to put the bytes that
-	     we'll be setting.  We do this in case ptrace_size != proto_size.  */
-	  memset (tmp_buf, 0, reginfo[regno].ptrace_size);
-
 	  /* Copy the bytes from the gdbserv_reg struct to our temporary buffer.  */
-	  gdbserv_host_bytes_from_reg (serv, tmp_buf, &len, &reg);
-	  if (len != reginfo[regno].proto_size)
-	    return -1;
+	  gdbserv_host_bytes_from_reg (serv, tmp_buf,
+	                               reginfo[regno].ptrace_size, &reg);
 
 	  /* Write the child's register. */
 	  status = write_reg_bytes (pid, regno, tmp_buf);
@@ -1343,7 +1462,6 @@ linux_get_reg (struct gdbserv *serv, int
   elf_fpregset_t fpregs;
   void *fpxregs;
   char *buf;
-  char tmp_buf[MAX_REG_SIZE];
 
   if (regno < 0 || regno >= NUM_REGS)
     {
@@ -1394,14 +1512,9 @@ linux_get_reg (struct gdbserv *serv, int
   /* Adjust buf to point at the starting byte of the register.  */
   buf += reginfo[regno].offset;
 
-  /* We go through these memset / memcpy shenanigans in case
-     proto_size != ptrace_size.  */
-  memset (tmp_buf, 0, reginfo[regno].proto_size);
-  if (reginfo[regno].ptrace_size > 0)
-    memcpy (tmp_buf, buf, reginfo[regno].ptrace_size);
-
   /* Copy the bytes to the gdbserv_reg struct.  */
-  gdbserv_host_bytes_to_reg (serv, tmp_buf, reginfo[regno].proto_size, reg);
+  gdbserv_host_bytes_to_reg (serv, buf, reginfo[regno].ptrace_size,
+                             reg, reginfo[regno].proto_size);
 
   return 0;
 }
@@ -1419,7 +1532,6 @@ linux_set_reg (struct gdbserv *serv, int
   void *fpxregs = NULL;
   char *buf;
   char tmp_buf[MAX_REG_SIZE];
-  int len;
 
   if (regno < 0 || regno >= NUM_REGS)
     {
@@ -1468,18 +1580,8 @@ linux_set_reg (struct gdbserv *serv, int
   /* Adjust buf to point at the starting byte of the register.  */
   buf += reginfo[regno].offset;
 
-  /* Clear out a temporary buffer into which to fetch the bytes that
-     we'll be setting.  We do this in case ptrace_size != proto_size.  */
-  memset (tmp_buf, 0, reginfo[regno].ptrace_size);
-
   /* Copy the bytes from the gdbserv_reg struct to our temporary buffer.  */
-  gdbserv_host_bytes_from_reg (serv, tmp_buf, &len, reg);
-
-  if (len != reginfo[regno].proto_size)
-    return -1;
-
-  /* Copy the bytes to the appropriate position in the ptrace struct.  */
-  memcpy (buf, tmp_buf, reginfo[regno].ptrace_size);
+  gdbserv_host_bytes_from_reg (serv, buf, reginfo[regno].ptrace_size, reg);
 
   /* Write the register set to the process.  */
   if (reginfo[regno].whichregs == GREGS)
@@ -1521,7 +1623,6 @@ reg_from_gregset (struct gdbserv *serv, 
 		  int regno, 
 		  const GREGSET_T gregset)
 {
-  char tmp_buf[MAX_REG_SIZE];
   char *regbytes;
 
   if (regno < 0 || regno >= NUM_REGS 
@@ -1532,10 +1633,8 @@ reg_from_gregset (struct gdbserv *serv, 
 
   regbytes = ((char *) gregset) + reginfo[regno].offset;
 
-  memset (tmp_buf, 0, reginfo[regno].proto_size);
-  memcpy (tmp_buf, regbytes, reginfo[regno].ptrace_size);
-
-  gdbserv_host_bytes_to_reg (serv, tmp_buf, reginfo[regno].proto_size, reg);
+  gdbserv_host_bytes_to_reg (serv, regbytes, reginfo[regno].ptrace_size,
+                             reg, reginfo[regno].proto_size);
 
   return 0;
 }
@@ -1550,9 +1649,7 @@ reg_to_gregset (struct gdbserv *serv, 
 		int regno, 
 		GREGSET_T gregset)
 {
-  char tmp_buf[MAX_REG_SIZE];
   char *regbytes;
-  int len;
 
   if (regno < 0 || regno >= NUM_REGS 
       || reginfo[regno].whichregs != GREGS)
@@ -1562,13 +1659,7 @@ reg_to_gregset (struct gdbserv *serv, 
 
   regbytes = ((char *) gregset) + reginfo[regno].offset;
 
-  memset (tmp_buf, 0, reginfo[regno].ptrace_size);
-  gdbserv_host_bytes_from_reg (serv, tmp_buf, &len, reg);
-
-  if (len != reginfo[regno].proto_size)
-    return -1;
-
-  memcpy (regbytes, tmp_buf, reginfo[regno].ptrace_size);
+  gdbserv_host_bytes_from_reg (serv, regbytes, reginfo[regno].ptrace_size, reg);
 
   return 0;
 }
@@ -1583,7 +1674,6 @@ reg_from_fpregset (struct gdbserv *serv,
 		   int regno, 
 		   const FPREGSET_T *fpregset)
 {
-  char tmp_buf[MAX_REG_SIZE];
   char *regbytes;
 
   if (regno < 0 || regno >= NUM_REGS 
@@ -1594,10 +1684,8 @@ reg_from_fpregset (struct gdbserv *serv,
 
   regbytes = ((char *) fpregset) + reginfo[regno].offset;
 
-  memset (tmp_buf, 0, reginfo[regno].proto_size);
-  memcpy (tmp_buf, regbytes, reginfo[regno].ptrace_size);
-
-  gdbserv_host_bytes_to_reg (serv, tmp_buf, reginfo[regno].proto_size, reg);
+  gdbserv_host_bytes_to_reg (serv, regbytes, reginfo[regno].ptrace_size,
+                             reg, reginfo[regno].proto_size);
 
   return 0;
 }
@@ -1612,9 +1700,7 @@ reg_to_fpregset (struct gdbserv *serv, 
 		 int regno, 
 		 FPREGSET_T *fpregset)
 {
-  char tmp_buf[MAX_REG_SIZE];
   char *regbytes;
-  int len;
 
   if (regno < 0 || regno >= NUM_REGS 
       || reginfo[regno].whichregs != FPREGS)
@@ -1624,13 +1710,7 @@ reg_to_fpregset (struct gdbserv *serv, 
 
   regbytes = ((char *) fpregset) + reginfo[regno].offset;
 
-  memset (tmp_buf, 0, reginfo[regno].ptrace_size);
-  gdbserv_host_bytes_from_reg (serv, tmp_buf, &len, reg);
-
-  if (len != reginfo[regno].proto_size)
-    return -1;
-
-  memcpy (regbytes, tmp_buf, reginfo[regno].ptrace_size);
+  gdbserv_host_bytes_from_reg (serv, regbytes, reginfo[regno].ptrace_size, reg);
 
   return 0;
 }
@@ -1645,7 +1725,6 @@ reg_from_xregset (struct gdbserv *serv, 
 		  int regno, 
 		  const void *xregset)
 {
-  char tmp_buf[MAX_REG_SIZE];
   char *regbytes;
 
   if (regno < 0 || regno >= NUM_REGS 
@@ -1656,10 +1735,8 @@ reg_from_xregset (struct gdbserv *serv, 
 
   regbytes = ((char *) xregset) + reginfo[regno].offset;
 
-  memset (tmp_buf, 0, reginfo[regno].proto_size);
-  memcpy (tmp_buf, regbytes, reginfo[regno].ptrace_size);
-
-  gdbserv_host_bytes_to_reg (serv, tmp_buf, reginfo[regno].proto_size, reg);
+  gdbserv_host_bytes_to_reg (serv, tmp_buf, reginfo[regno].ptrace_size,
+                             reg, reginfo[regno].proto_size);
 
   return 0;
 }
@@ -1674,9 +1751,7 @@ reg_to_xregset (struct gdbserv *serv, 
 		int regno, 
 		void *xregset)
 {
-  char tmp_buf[MAX_REG_SIZE];
   char *regbytes;
-  int len;
 
   if (regno < 0 || regno >= NUM_REGS 
       || reginfo[regno].whichregs != FPXREGS)
@@ -1686,13 +1761,7 @@ reg_to_xregset (struct gdbserv *serv, 
 
   regbytes = ((char *) xregset) + reginfo[regno].offset;
 
-  memset (tmp_buf, 0, reginfo[regno].ptrace_size);
-  gdbserv_host_bytes_from_reg (serv, tmp_buf, &len, reg);
-
-  if (len != reginfo[regno].proto_size)
-    return -1;
-
-  memcpy (regbytes, tmp_buf, reginfo[regno].ptrace_size);
+  gdbserv_host_bytes_from_reg (serv, regbytes, reginfo[regno].ptrace_size, reg);
 
   return 0;
 }

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2002-11-27 22:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-11-27 10:33 [RFC] Revise interfaces for *_bytes_{from,to}_reg() Kevin Buettner
2002-11-27 10:49 ` Kevin Buettner
2002-11-27 14:02   ` Kevin Buettner

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).