--- ./sv.c-pre	Mon Nov  3 00:04:30 2003
+++ ./sv.c	Tue Dec  9 20:38:58 2003
@@ -8348,6 +8348,11 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 	unsigned base = 0;
 	IV iv = 0;
 	UV uv = 0;
+#if defined(SPRINTF_QUAD) && !defined(HAS_QUAD)
+	Uquad_t quv;
+#else
+#  define	quv	uv
+#endif
 	/* we need a long double target in case HAS_LONG_DOUBLE but
 	   not USE_LONG_DOUBLE
 	*/
@@ -8540,10 +8545,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 	    q++;
 	    break;
 #endif
-#if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE)
+#if defined(SPRINTF_QUAD) || defined(HAS_LONG_DOUBLE)
 	case 'L':			/* Ld */
 	    /* FALL THROUGH */
-#ifdef HAS_QUAD
+#ifdef SPRINTF_QUAD
 	case 'q':			/* qd */
 #endif
 	    intsize = 'q';
@@ -8551,7 +8556,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 	    break;
 #endif
 	case 'l':
-#if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE)
+#if defined(SPRINTF_QUAD) || defined(HAS_LONG_DOUBLE)
 	    if (*(q + 1) == 'l') {	/* lld, llf */
 		intsize = 'q';
 		q += 2;
@@ -8691,8 +8696,23 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 		default:	iv = va_arg(*args, int); break;
 		case 'l':	iv = va_arg(*args, long); break;
 		case 'V':	iv = va_arg(*args, IV); break;
-#ifdef HAS_QUAD
-		case 'q':	iv = va_arg(*args, Quad_t); break;
+#ifdef SPRINTF_QUAD
+		case 'q':	{
+				    Quad_t qiv = va_arg(*args, Quad_t);
+#  ifdef IV_IS_QUAD
+				    iv = (IV)qiv;
+#  else
+				    if (qiv < 0) {
+					quv = -qiv;
+					esignbuf[esignlen++] = '-';
+				    }
+				    else
+					quv = qiv;
+				    base = 10;
+				    goto quad_integer;
+#  endif
+				}
+				break;
 #endif
 		}
 	    }
@@ -8703,8 +8723,23 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 		default:	break;
 		case 'l':	iv = (long)iv; break;
 		case 'V':	break;
-#ifdef HAS_QUAD
-		case 'q':	iv = (Quad_t)iv; break;
+#ifdef SPRINTF_QUAD
+		case 'q':	{
+				    Quad_t qiv = (Quad_t)iv;
+#  ifdef IV_IS_QUAD
+				    iv = (IV)qiv;
+#  else
+				    if (qiv < 0) {
+					quv = -qiv;
+					esignbuf[esignlen++] = '-';
+				    }
+				    else
+					quv = qiv;
+				    base = 10;
+				    goto quad_integer;
+#  endif
+				}
+				break;
 #endif
 		}
 	    }
@@ -8775,8 +8810,12 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 		default:   uv = va_arg(*args, unsigned); break;
 		case 'l':  uv = va_arg(*args, unsigned long); break;
 		case 'V':  uv = va_arg(*args, UV); break;
-#ifdef HAS_QUAD
-		case 'q':  uv = va_arg(*args, Quad_t); break;
+#ifdef SPRINTF_QUAD
+		case 'q':  quv = va_arg(*args, Quad_t);
+#  ifndef USE_QUAD
+			   goto quad_integer;
+#  endif
+			   break;
 #endif
 		}
 	    }
@@ -8787,8 +8826,12 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 		default:	break;
 		case 'l':	uv = (unsigned long)uv; break;
 		case 'V':	break;
-#ifdef HAS_QUAD
-		case 'q':	uv = (Quad_t)uv; break;
+#ifdef SPRINTF_QUAD
+		case 'q':	quv = (Quad_t)uv;
+#  ifndef USE_QUAD
+				goto quad_integer;
+#  endif
+				break;
 #endif
 		}
 	    }
@@ -8858,6 +8901,72 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 	    }
 	    break;
 
+#if defined(SPRINTF_QUAD) && !defined(USE_QUAD)
+	quad_integer:
+	    eptr = ebuf + sizeof ebuf;
+	    switch (base) {
+		unsigned dig;
+	    case 16:
+		if (!quv)
+		    alt = FALSE;
+		p = (char*)((c == 'X')
+			    ? "0123456789ABCDEF" : "0123456789abcdef");
+		do {
+		    dig = quv & 15;
+		    *--eptr = p[dig];
+		} while (quv >>= 4);
+		if (alt) {
+		    esignbuf[esignlen++] = '0';
+		    esignbuf[esignlen++] = c;  /* 'x' or 'X' */
+		}
+		break;
+	    case 8:
+		do {
+		    dig = quv & 7;
+		    *--eptr = '0' + dig;
+		} while (quv >>= 3);
+		if (alt && *eptr != '0')
+		    *--eptr = '0';
+		break;
+	    case 2:
+		do {
+		    dig = quv & 1;
+		    *--eptr = '0' + dig;
+		} while (quv >>= 1);
+		if (alt) {
+		    esignbuf[esignlen++] = '0';
+		    esignbuf[esignlen++] = 'b';
+		}
+		break;
+	    default:		/* it had better be ten or less */
+#if defined(PERL_Y2KWARN)
+		if (ckWARN(WARN_Y2K)) {
+		    STRLEN n;
+		    char *s = SvPV(sv,n);
+		    if (n >= 2 && s[n-2] == '1' && s[n-1] == '9'
+			&& (n == 2 || !isDIGIT(s[n-3])))
+		    {
+			Perl_warner(aTHX_ packWARN(WARN_Y2K),
+				    "Possible Y2K bug: %%%c %s",
+				    c, "format string following '19'");
+		    }
+		}
+#endif
+		do {
+		    dig = quv % base;
+		    *--eptr = '0' + dig;
+		} while (quv /= base);
+		break;
+	    }
+	    elen = (ebuf + sizeof ebuf) - eptr;
+	    if (has_precis) {
+		if (precis > elen)
+		    zeros = precis - elen;
+		else if (precis == 0 && elen == 1 && *eptr == '0')
+		    elen = 0;
+	    }
+	    break;
+#endif
 	    /* FLOATING POINT */
 
 	case 'F':
@@ -9057,7 +9166,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 		default:	*(va_arg(*args, int*)) = i; break;
 		case 'l':	*(va_arg(*args, long*)) = i; break;
 		case 'V':	*(va_arg(*args, IV*)) = i; break;
-#ifdef HAS_QUAD
+#ifdef SPRINTF_QUAD
 		case 'q':	*(va_arg(*args, Quad_t*)) = i; break;
 #endif
 		}
@@ -9178,6 +9287,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const cha
 	    goto vector;
 	}
     }
+#undef	quv
 }
 
 /* =========================================================================
--- ./pp_pack.c-pre	Sat Oct 18 11:45:42 2003
+++ ./pp_pack.c	Tue Dec  9 20:01:20 2003
@@ -291,7 +291,7 @@ S_measure_struct(pTHX_ register tempsym_
 	case 'p':
 	    size = sizeof(char*);
 	    break;
-#ifdef HAS_QUAD
+#ifdef PACK_QUAD
 	case 'q':
 	    size = sizeof(Quad_t);
 	    break;
@@ -547,15 +547,13 @@ S_unpack_rec(pTHX_ register tempsym_t* s
     short ashort;
     int aint;
     long along;
-#ifdef HAS_QUAD
+#ifdef PACK_QUAD
     Quad_t aquad;
+    Uquad_t auquad;
 #endif
     U16 aushort;
     unsigned int auint;
     U32 aulong;
-#ifdef HAS_QUAD
-    Uquad_t auquad;
-#endif
     char *aptr;
     float afloat;
     double adouble;
@@ -1411,7 +1409,7 @@ S_unpack_rec(pTHX_ register tempsym_t* s
 		sv_setpvn(sv, aptr, len);
 	    PUSHs(sv_2mortal(sv));
 	    break;
-#ifdef HAS_QUAD
+#ifdef PACK_QUAD
 	case 'q':
 	    along = (strend - s) / sizeof(Quad_t);
 	    if (len > along)
@@ -1441,8 +1439,11 @@ S_unpack_rec(pTHX_ register tempsym_t* s
                     sv = NEWSV(42, 0);
                     if (aquad >= IV_MIN && aquad <= IV_MAX)
 		        sv_setiv(sv, (IV)aquad);
-                    else
+                    else {
+			sv_setpvf(sv, "%Qd", aquad);
                         sv_setnv(sv, (NV)aquad);
+			SvPOK_on(sv);			# make double-edged
+		    }
                     PUSHs(sv_2mortal(sv));
                 }
             }
@@ -1476,8 +1477,11 @@ S_unpack_rec(pTHX_ register tempsym_t* s
                     sv = NEWSV(43, 0);
                     if (auquad <= UV_MAX)
                         sv_setuv(sv, (UV)auquad);
-                    else
-		    sv_setnv(sv, (NV)auquad);
+                    else {
+			sv_setpvf(sv, "%Qu", auquad);
+                        sv_setnv(sv, (NV)auquad);
+			SvPOK_on(sv);			# make double-edged
+		    }
                     PUSHs(sv_2mortal(sv));
                 }
             }
@@ -1908,7 +1912,7 @@ S_pack_rec(pTHX_ SV *cat, register temps
 #if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
     long double aldouble;
 #endif
-#ifdef HAS_QUAD
+#ifdef PACK_QUAD
     Quad_t aquad;
     Uquad_t auquad;
 #endif
@@ -2545,18 +2549,26 @@ S_pack_rec(pTHX_ SV *cat, register temps
 		CAT32(cat, &along);
 	    }
 	    break;
-#ifdef HAS_QUAD
+#ifdef PACK_QUAD
 	case 'Q':
 	    while (len-- > 0) {
 		fromstr = NEXTFROM;
+#ifdef UV_IS_QUAD
 		auquad = (Uquad_t)SvUV(fromstr);
+#else
+		auquad = (Uquad_t)SvNV(fromstr);
+#endif
 		sv_catpvn(cat, (char*)&auquad, sizeof(Uquad_t));
 	    }
 	    break;
 	case 'q':
 	    while (len-- > 0) {
 		fromstr = NEXTFROM;
+#ifdef IV_IS_QUAD
 		aquad = (Quad_t)SvIV(fromstr);
+#else
+		aquad = (Quad_t)SvNV(fromstr);
+#endif
 		sv_catpvn(cat, (char*)&aquad, sizeof(Quad_t));
 	    }
 	    break;
--- ./perl.h-pre	Sat Nov  1 04:24:06 2003
+++ ./perl.h	Tue Dec  9 19:50:16 2003
@@ -1078,6 +1078,10 @@ int sockatmark(int);
 typedef IVTYPE IV;
 typedef UVTYPE UV;
 
+#ifdef HAS_QUAD			/* XXX Silly equilibristic... */
+#  define CAN_USE_QUAD
+#endif
+
 #if defined(USE_64_BIT_INT) && defined(HAS_QUAD)
 #  if QUADKIND == QUAD_IS_INT64_T && defined(INT64_MAX)
 #    define IV_MAX INT64_MAX
@@ -1119,12 +1123,18 @@ typedef UVTYPE UV;
 #    define UV_IS_QUAD
 #    ifndef HAS_QUAD
 #      define HAS_QUAD
+#      define CAN_USE_QUAD
 #    endif
 #  else
 #    undef IV_IS_QUAD
 #    undef UV_IS_QUAD
 #    undef HAS_QUAD
 #  endif
+#endif
+
+#ifdef HAS_QUAD
+#  define PACK_QUAD
+#  define SPRINTF_QUAD
 #endif
 
 #if defined(uts) || defined(UTS)
--- ./handy.h-pre	Tue Sep 30 09:10:34 2003
+++ ./handy.h	Tue Dec  9 19:48:08 2003
@@ -136,13 +136,13 @@ typedef U16TYPE U16;
 typedef I32TYPE I32;
 typedef U32TYPE U32;
 #ifdef PERL_CORE
-#   ifdef HAS_QUAD
+#   ifdef CAN_USE_QUAD
 typedef I64TYPE I64;
 typedef U64TYPE U64;
 #   endif
 #endif /* PERL_CORE */
 
-#if defined(HAS_QUAD) && defined(USE_64_BIT_INT)
+#if defined(CAN_USE_QUAD) && defined(USE_64_BIT_INT)
 #   ifndef UINT64_C /* usually from <inttypes.h> */
 #       if defined(HAS_LONG_LONG) && QUADKIND == QUAD_IS_LONG_LONG
 #           define INT64_C(c)	CAT2(c,LL)
