diff options
Diffstat (limited to 'libjava/classpath/native')
185 files changed, 47088 insertions, 0 deletions
diff --git a/libjava/classpath/native/.cvsignore b/libjava/classpath/native/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/Makefile.am b/libjava/classpath/native/Makefile.am new file mode 100644 index 00000000000..6cc309010c0 --- /dev/null +++ b/libjava/classpath/native/Makefile.am @@ -0,0 +1,9 @@ +## Input file for automake to generate the Makefile.in used by configure + +if CREATE_JNI_LIBRARIES + JNIDIR = jni +endif + +SUBDIRS = fdlibm $(JNIDIR) target +DIST_SUBDIRS = fdlibm jni target + diff --git a/libjava/classpath/native/fdlibm/.cvsignore b/libjava/classpath/native/fdlibm/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/fdlibm/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/fdlibm/Makefile.am b/libjava/classpath/native/fdlibm/Makefile.am new file mode 100644 index 00000000000..e3e3eecd2b7 --- /dev/null +++ b/libjava/classpath/native/fdlibm/Makefile.am @@ -0,0 +1,53 @@ +noinst_LTLIBRARIES = libfdlibm.la + +libfdlibm_la_SOURCES = \ + dtoa.c \ + e_acos.c \ + e_asin.c \ + e_atan2.c \ + e_exp.c \ + e_fmod.c \ + e_log.c \ + e_pow.c \ + e_remainder.c \ + e_rem_pio2.c \ + e_scalb.c \ + e_sqrt.c \ + fdlibm.h \ + ieeefp.h \ + java-assert.h \ + k_cos.c \ + k_rem_pio2.c \ + k_sin.c \ + k_tan.c \ + mprec.c \ + mprec.h \ + s_atan.c \ + s_ceil.c \ + s_copysign.c \ + s_cos.c \ + s_fabs.c \ + sf_fabs.c \ + s_finite.c \ + s_floor.c \ + sf_rint.c \ + s_rint.c \ + s_scalbn.c \ + s_sin.c \ + s_tan.c \ + strtod.c \ + w_acos.c \ + w_asin.c \ + w_atan2.c \ + w_exp.c \ + w_fmod.c \ + w_log.c \ + w_pow.c \ + w_remainder.c \ + w_sqrt.c + +AM_LDFLAGS = @CLASSPATH_MODULE@ + +# We just want the standard flags for fdlibm since it is an upstream lib +# and our normal -pedantic -Wall -Werror breaks this lib. So no AM_CFLAGS. +# We also don't need extra includes, so no AM_CPPFLAGS either. diff --git a/libjava/classpath/native/fdlibm/dtoa.c b/libjava/classpath/native/fdlibm/dtoa.c new file mode 100644 index 00000000000..6d5ad3b422e --- /dev/null +++ b/libjava/classpath/native/fdlibm/dtoa.c @@ -0,0 +1,906 @@ +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991 by AT&T. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +#include "mprec.h" +#include <string.h> + +static int +_DEFUN (quorem, + (b, S), + _Jv_Bigint * b _AND _Jv_Bigint * S) +{ + int n; + long borrow, y; + unsigned long carry, q, ys; + unsigned long *bx, *bxe, *sx, *sxe; +#ifdef Pack_32 + long z; + unsigned long si, zs; +#endif + + n = S->_wds; +#ifdef DEBUG + /*debug*/ if (b->_wds > n) + /*debug*/ Bug ("oversize b in quorem"); +#endif + if (b->_wds < n) + return 0; + sx = S->_x; + sxe = sx + --n; + bx = b->_x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef DEBUG + /*debug*/ if (q > 9) + /*debug*/ Bug ("oversized quotient in quorem"); +#endif + if (q) + { + borrow = 0; + carry = 0; + do + { +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend (borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend (borrow, z); + Storeinc (bx, z, y); +#else + ys = *sx++ * q + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend (borrow, y); + *bx++ = y & 0xffff; +#endif + } + while (sx <= sxe); + if (!*bxe) + { + bx = b->_x; + while (--bxe > bx && !*bxe) + --n; + b->_wds = n; + } + } + if (cmp (b, S) >= 0) + { + q++; + borrow = 0; + carry = 0; + bx = b->_x; + sx = S->_x; + do + { +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend (borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend (borrow, z); + Storeinc (bx, z, y); +#else + ys = *sx++ + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend (borrow, y); + *bx++ = y & 0xffff; +#endif + } + while (sx <= sxe); + bx = b->_x; + bxe = bx + n; + if (!*bxe) + { + while (--bxe > bx && !*bxe) + --n; + b->_wds = n; + } + } + return q; +} + +#ifdef DEBUG +#include <stdio.h> + +void +print (_Jv_Bigint * b) +{ + int i, wds; + unsigned long *x, y; + wds = b->_wds; + x = b->_x+wds; + i = 0; + do + { + x--; + fprintf (stderr, "%08x", *x); + } + while (++i < wds); + fprintf (stderr, "\n"); +} +#endif + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the long + * calculation. + */ + + +char * +_DEFUN (_dtoa_r, + (ptr, _d, mode, ndigits, decpt, sign, rve, float_type), + struct _Jv_reent *ptr _AND + double _d _AND + int mode _AND + int ndigits _AND + int *decpt _AND + int *sign _AND + char **rve _AND + int float_type) +{ + /* + float_type == 0 for double precision, 1 for float. + + Arguments ndigits, decpt, sign are similar to those + of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4-9 should give the same return values as 2-3, i.e., + 4 <= mode <= 9 ==> same return as mode + 2 + (mode & 1). These modes are mainly for + debugging; often they run slower but sometimes + faster than modes 2-3. + 4,5,8,9 ==> left-to-right digit generation. + 6-9 ==> don't try fast floating-point estimate + (if applicable). + + > 16 ==> Floating-point arg is treated as single precision. + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be, dig, i, ieps, ilim0, j, j1, k, k0, + k_check, leftright, m2, m5, s2, s5, try_quick; + int ilim = 0, ilim1 = 0, spec_case = 0; + union double_union d, d2, eps; + long L; +#ifndef Sudden_Underflow + int denorm; + unsigned long x; +#endif + _Jv_Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S; + double ds; + char *s, *s0; + + d.d = _d; + + if (ptr->_result) + { + ptr->_result->_k = ptr->_result_k; + ptr->_result->_maxwds = 1 << ptr->_result_k; + Bfree (ptr, ptr->_result); + ptr->_result = 0; + } + + if (word0 (d) & Sign_bit) + { + /* set sign for everything, including 0's and NaNs */ + *sign = 1; + word0 (d) &= ~Sign_bit; /* clear sign bit */ + } + else + *sign = 0; + +#if defined(IEEE_Arith) + defined(VAX) +#ifdef IEEE_Arith + if ((word0 (d) & Exp_mask) == Exp_mask) +#else + if (word0 (d) == 0x8000) +#endif + { + /* Infinity or NaN */ + *decpt = 9999; + s = +#ifdef IEEE_Arith + !word1 (d) && !(word0 (d) & 0xfffff) ? "Infinity" : +#endif + "NaN"; + if (rve) + *rve = +#ifdef IEEE_Arith + s[3] ? s + 8 : +#endif + s + 3; + return s; + } +#endif +#ifdef IBM + d.d += 0; /* normalize */ +#endif + if (!d.d) + { + *decpt = 1; + s = "0"; + if (rve) + *rve = s + 1; + return s; + } + + b = d2b (ptr, d.d, &be, &bbits); +#ifdef Sudden_Underflow + i = (int) (word0 (d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)); +#else + if ((i = (int) (word0 (d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) + { +#endif + d2.d = d.d; + word0 (d2) &= Frac_mask1; + word0 (d2) |= Exp_11; +#ifdef IBM + if (j = 11 - hi0bits (word0 (d2) & Frac_mask)) + d2.d /= 1 << j; +#endif + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) + * + * This suggests computing an approximation k to log10(d) by + * + * k = (i - Bias)*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ + + i -= Bias; +#ifdef IBM + i <<= 2; + i += j; +#endif +#ifndef Sudden_Underflow + denorm = 0; + } + else + { + /* d is denormalized */ + + i = bbits + be + (Bias + (P - 1) - 1); + x = i > 32 ? word0 (d) << (64 - i) | word1 (d) >> (i - 32) + : word1 (d) << (32 - i); + d2.d = x; + word0 (d2) -= 31 * Exp_msk1; /* adjust exponent */ + i -= (Bias + (P - 1) - 1) + 1; + denorm = 1; + } +#endif + ds = (d2.d - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981; + k = (int) ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + if (k >= 0 && k <= Ten_pmax) + { + if (d.d < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) + { + b2 = 0; + s2 = j; + } + else + { + b2 = -j; + s2 = 0; + } + if (k >= 0) + { + b5 = 0; + s5 = k; + s2 += k; + } + else + { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + try_quick = 1; + if (mode > 5) + { + mode -= 4; + try_quick = 0; + } + leftright = 1; + switch (mode) + { + case 0: + case 1: + ilim = ilim1 = -1; + i = 18; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + j = sizeof (unsigned long); + for (ptr->_result_k = 0; (int) (sizeof (_Jv_Bigint) - sizeof (unsigned long)) + j <= i; + j <<= 1) + ptr->_result_k++; + ptr->_result = Balloc (ptr, ptr->_result_k); + s = s0 = (char *) ptr->_result; + + if (ilim >= 0 && ilim <= Quick_max && try_quick) + { + /* Try to get by with floating-point arithmetic. */ + + i = 0; + d2.d = d.d; + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) + { + ds = tens[k & 0xf]; + j = k >> 4; + if (j & Bletch) + { + /* prevent overflows */ + j &= Bletch - 1; + d.d /= bigtens[n_bigtens - 1]; + ieps++; + } + for (; j; j >>= 1, i++) + if (j & 1) + { + ieps++; + ds *= bigtens[i]; + } + d.d /= ds; + } + else if ((j1 = -k)) + { + d.d *= tens[j1 & 0xf]; + for (j = j1 >> 4; j; j >>= 1, i++) + if (j & 1) + { + ieps++; + d.d *= bigtens[i]; + } + } + if (k_check && d.d < 1. && ilim > 0) + { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + d.d *= 10.; + ieps++; + } + eps.d = ieps * d.d + 7.; + word0 (eps) -= (P - 1) * Exp_msk1; + if (ilim == 0) + { + S = mhi = 0; + d.d -= 5.; + if (d.d > eps.d) + goto one_digit; + if (d.d < -eps.d) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) + { + /* Use Steele & White method of only + * generating digits needed. + */ + eps.d = 0.5 / tens[ilim - 1] - eps.d; + for (i = 0;;) + { + L = d.d; + d.d -= L; + *s++ = '0' + (int) L; + if (d.d < eps.d) + goto ret1; + if (1. - d.d < eps.d) + goto bump_up; + if (++i >= ilim) + break; + eps.d *= 10.; + d.d *= 10.; + } + } + else + { +#endif + /* Generate ilim digits, then fix them up. */ + eps.d *= tens[ilim - 1]; + for (i = 1;; i++, d.d *= 10.) + { + L = d.d; + d.d -= L; + *s++ = '0' + (int) L; + if (i == ilim) + { + if (d.d > 0.5 + eps.d) + goto bump_up; + else if (d.d < 0.5 - eps.d) + { + while (*--s == '0'); + s++; + goto ret1; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + d.d = d2.d; + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) + { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) + { + S = mhi = 0; + if (ilim < 0 || d.d <= 5 * ds) + goto no_digits; + goto one_digit; + } + for (i = 1;; i++) + { + L = d.d / ds; + d.d -= L * ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (d.d < 0) + { + L--; + d.d += ds; + } +#endif + *s++ = '0' + (int) L; + if (i == ilim) + { + d.d += d.d; + if (d.d > ds || (d.d == ds && L & 1)) + { + bump_up: + while (*--s == '9') + if (s == s0) + { + k++; + *s = '0'; + break; + } + ++*s++; + } + break; + } + if (!(d.d *= 10.)) + break; + } + goto ret1; + } + + m2 = b2; + m5 = b5; + mhi = mlo = 0; + if (leftright) + { + if (mode < 2) + { + i = +#ifndef Sudden_Underflow + denorm ? be + (Bias + (P - 1) - 1 + 1) : +#endif +#ifdef IBM + 1 + 4 * P - 3 - bbits + ((bbits + be - 1) & 3); +#else + 1 + P - bbits; +#endif + } + else + { + j = ilim - 1; + if (m5 >= j) + m5 -= j; + else + { + s5 += j -= m5; + b5 += j; + m5 = 0; + } + if ((i = ilim) < 0) + { + m2 -= i; + i = 0; + } + } + b2 += i; + s2 += i; + mhi = i2b (ptr, 1); + } + if (m2 > 0 && s2 > 0) + { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) + { + if (leftright) + { + if (m5 > 0) + { + mhi = pow5mult (ptr, mhi, m5); + b1 = mult (ptr, mhi, b); + Bfree (ptr, b); + b = b1; + } + if ((j = b5 - m5)) + b = pow5mult (ptr, b, j); + } + else + b = pow5mult (ptr, b, b5); + } + S = i2b (ptr, 1); + if (s5 > 0) + S = pow5mult (ptr, S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + if (mode < 2) + { + if (!word1 (d) && !(word0 (d) & Bndry_mask) +#ifndef Sudden_Underflow + && word0(d) & Exp_mask +#endif + ) + { + /* The special case */ + b2 += Log2P; + s2 += Log2P; + spec_case = 1; + } + else + spec_case = 0; + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ + +#ifdef Pack_32 + if ((i = ((s5 ? 32 - hi0bits (S->_x[S->_wds - 1]) : 1) + s2) & 0x1f)) + i = 32 - i; +#else + if ((i = ((s5 ? 32 - hi0bits (S->_x[S->_wds - 1]) : 1) + s2) & 0xf)) + i = 16 - i; +#endif + if (i > 4) + { + i -= 4; + b2 += i; + m2 += i; + s2 += i; + } + else if (i < 4) + { + i += 28; + b2 += i; + m2 += i; + s2 += i; + } + if (b2 > 0) + b = lshift (ptr, b, b2); + if (s2 > 0) + S = lshift (ptr, S, s2); + if (k_check) + { + if (cmp (b, S) < 0) + { + k--; + b = multadd (ptr, b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd (ptr, mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && mode > 2) + { + if (ilim < 0 || cmp (b, S = multadd (ptr, S, 5, 0)) <= 0) + { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + goto ret; + } + one_digit: + *s++ = '1'; + k++; + goto ret; + } + if (leftright) + { + if (m2 > 0) + mhi = lshift (ptr, mhi, m2); + + /* Single precision case, */ + if (float_type) + mhi = lshift (ptr, mhi, 29); + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + mlo = mhi; + if (spec_case) + { + mhi = Balloc (ptr, mhi->_k); + Bcopy (mhi, mlo); + mhi = lshift (ptr, mhi, Log2P); + } + + for (i = 1;; i++) + { + dig = quorem (b, S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp (b, mlo); + delta = diff (ptr, S, mhi); + j1 = delta->_sign ? 1 : cmp (b, delta); + Bfree (ptr, delta); +#ifndef ROUND_BIASED + if (j1 == 0 && !mode && !(word1 (d) & 1)) + { + if (dig == '9') + goto round_9_up; + if (j > 0) + dig++; + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || (j == 0 && !mode +#ifndef ROUND_BIASED + && !(word1 (d) & 1) +#endif + )) + { + if (j1 > 0) + { + b = lshift (ptr, b, 1); + j1 = cmp (b, S); + if ((j1 > 0 || (j1 == 0 && dig & 1)) + && dig++ == '9') + goto round_9_up; + } + *s++ = dig; + goto ret; + } + if (j1 > 0) + { + if (dig == '9') + { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + goto roundoff; + } + *s++ = dig + 1; + goto ret; + } + *s++ = dig; + if (i == ilim) + break; + b = multadd (ptr, b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd (ptr, mhi, 10, 0); + else + { + mlo = multadd (ptr, mlo, 10, 0); + mhi = multadd (ptr, mhi, 10, 0); + } + } + } + else + for (i = 1;; i++) + { + *s++ = dig = quorem (b, S) + '0'; + if (i >= ilim) + break; + b = multadd (ptr, b, 10, 0); + } + + /* Round off last digit */ + + b = lshift (ptr, b, 1); + j = cmp (b, S); + if (j > 0 || (j == 0 && dig & 1)) + { + roundoff: + while (*--s == '9') + if (s == s0) + { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else + { + while (*--s == '0'); + s++; + } +ret: + Bfree (ptr, S); + if (mhi) + { + if (mlo && mlo != mhi) + Bfree (ptr, mlo); + Bfree (ptr, mhi); + } +ret1: + Bfree (ptr, b); + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + return s0; +} + + +_VOID +_DEFUN (_dtoa, + (_d, mode, ndigits, decpt, sign, rve, buf, float_type), + double _d _AND + int mode _AND + int ndigits _AND + int *decpt _AND + int *sign _AND + char **rve _AND + char *buf _AND + int float_type) +{ + struct _Jv_reent reent; + char *p; + memset (&reent, 0, sizeof reent); + + p = _dtoa_r (&reent, _d, mode, ndigits, decpt, sign, rve, float_type); + strcpy (buf, p); + + return; +} diff --git a/libjava/classpath/native/fdlibm/e_acos.c b/libjava/classpath/native/fdlibm/e_acos.c new file mode 100644 index 00000000000..ee6b168a1c5 --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_acos.c @@ -0,0 +1,111 @@ + +/* @(#)e_acos.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_acos(x) + * Method : + * acos(x) = pi/2 - asin(x) + * acos(-x) = pi/2 + asin(x) + * For |x|<=0.5 + * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) + * For x>0.5 + * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) + * = 2asin(sqrt((1-x)/2)) + * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) + * = 2f + (2c + 2s*z*R(z)) + * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term + * for f so that f+c ~ sqrt(z). + * For x<-0.5 + * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) + * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN with invalid signal. + * + * Function needed: sqrt + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ +pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ +pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ +pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ +pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ +pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ +pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ +pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ +pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ +qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ +qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ +qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ +qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ + +#ifdef __STDC__ + double __ieee754_acos(double x) +#else + double __ieee754_acos(x) + double x; +#endif +{ + double z,p,q,r,w,s,c,df; + int32_t hx,ix; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x3ff00000) { /* |x| >= 1 */ + uint32_t lx; + GET_LOW_WORD(lx,x); + if(((ix-0x3ff00000)|lx)==0) { /* |x|==1 */ + if(hx>0) return 0.0; /* acos(1) = 0 */ + else return pi+2.0*pio2_lo; /* acos(-1)= pi */ + } + return (x-x)/(x-x); /* acos(|x|>1) is NaN */ + } + if(ix<0x3fe00000) { /* |x| < 0.5 */ + if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/ + z = x*x; + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); + q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); + r = p/q; + return pio2_hi - (x - (pio2_lo-x*r)); + } else if (hx<0) { /* x < -0.5 */ + z = (one+x)*0.5; + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); + q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); + s = __ieee754_sqrt(z); + r = p/q; + w = r*s-pio2_lo; + return pi - 2.0*(s+w); + } else { /* x > 0.5 */ + z = (one-x)*0.5; + s = __ieee754_sqrt(z); + df = s; + SET_LOW_WORD(df,0); + c = (z-df*df)/(s+df); + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); + q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); + r = p/q; + w = r*s+c; + return 2.0*(df+w); + } +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_asin.c b/libjava/classpath/native/fdlibm/e_asin.c new file mode 100644 index 00000000000..90fc77ffc3b --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_asin.c @@ -0,0 +1,120 @@ + +/* @(#)e_asin.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_asin(x) + * Method : + * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ... + * we approximate asin(x) on [0,0.5] by + * asin(x) = x + x*x^2*R(x^2) + * where + * R(x^2) is a rational approximation of (asin(x)-x)/x^3 + * and its remez error is bounded by + * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75) + * + * For x in [0.5,1] + * asin(x) = pi/2-2*asin(sqrt((1-x)/2)) + * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2; + * then for x>0.98 + * asin(x) = pi/2 - 2*(s+s*z*R(z)) + * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) + * For x<=0.98, let pio4_hi = pio2_hi/2, then + * f = hi part of s; + * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) + * and + * asin(x) = pi/2 - 2*(s+s*z*R(z)) + * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) + * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN with invalid signal. + * + */ + + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +huge = 1.000e+300, +pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ +pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ +pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ + /* coefficient for R(x^2) */ +pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ +pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ +pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ +pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ +pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ +pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ +qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ +qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ +qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ +qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ + +#ifdef __STDC__ + double __ieee754_asin(double x) +#else + double __ieee754_asin(x) + double x; +#endif +{ + double t = 0., w, p, q, c, r, s; + int32_t hx,ix; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>= 0x3ff00000) { /* |x|>= 1 */ + uint32_t lx; + GET_LOW_WORD(lx,x); + if(((ix-0x3ff00000)|lx)==0) + /* asin(1)=+-pi/2 with inexact */ + return x*pio2_hi+x*pio2_lo; + return (x-x)/(x-x); /* asin(|x|>1) is NaN */ + } else if (ix<0x3fe00000) { /* |x|<0.5 */ + if(ix<0x3e400000) { /* if |x| < 2**-27 */ + if(huge+x>one) return x;/* return x with inexact if x!=0*/ + } else + t = x*x; + p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); + q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); + w = p/q; + return x+x*w; + } + /* 1> |x|>= 0.5 */ + w = one-fabs(x); + t = w*0.5; + p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); + q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); + s = __ieee754_sqrt(t); + if(ix>=0x3FEF3333) { /* if |x| > 0.975 */ + w = p/q; + t = pio2_hi-(2.0*(s+s*w)-pio2_lo); + } else { + w = s; + SET_LOW_WORD(w,0); + c = (t-w*w)/(s+w); + r = p/q; + p = 2.0*s*r-(pio2_lo-2.0*c); + q = pio4_hi-2.0*w; + t = pio4_hi-(p-q); + } + if(hx>0) return t; else return -t; +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_atan2.c b/libjava/classpath/native/fdlibm/e_atan2.c new file mode 100644 index 00000000000..c75448db26c --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_atan2.c @@ -0,0 +1,131 @@ + +/* @(#)e_atan2.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +/* __ieee754_atan2(y,x) + * Method : + * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). + * 2. Reduce x to positive by (if x and y are unexceptional): + * ARG (x+iy) = arctan(y/x) ... if x > 0, + * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, + * + * Special cases: + * + * ATAN2((anything), NaN ) is NaN; + * ATAN2(NAN , (anything) ) is NaN; + * ATAN2(+-0, +(anything but NaN)) is +-0 ; + * ATAN2(+-0, -(anything but NaN)) is +-pi ; + * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; + * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; + * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; + * ATAN2(+-INF,+INF ) is +-pi/4 ; + * ATAN2(+-INF,-INF ) is +-3pi/4; + * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +tiny = 1.0e-300, +zero = 0.0, +pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ +pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ +pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ +pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ + +#ifdef __STDC__ + double __ieee754_atan2(double y, double x) +#else + double __ieee754_atan2(y,x) + double y,x; +#endif +{ + double z; + int32_t k,m,hx,hy,ix,iy; + uint32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + ix = hx&0x7fffffff; + EXTRACT_WORDS(hy,ly,y); + iy = hy&0x7fffffff; + if(((ix|((lx|-lx)>>31))>0x7ff00000)|| + ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */ + return x+y; + if(((hx-0x3ff00000)|lx)==0) return atan(y); /* x=1.0 */ + m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ + + /* when y = 0 */ + if((iy|ly)==0) { + switch(m) { + case 0: + case 1: return y; /* atan(+-0,+anything)=+-0 */ + case 2: return pi+tiny;/* atan(+0,-anything) = pi */ + case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ + } + } + /* when x = 0 */ + if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; + + /* when x is INF */ + if(ix==0x7ff00000) { + if(iy==0x7ff00000) { + switch(m) { + case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ + case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ + case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ + case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ + } + } else { + switch(m) { + case 0: return zero ; /* atan(+...,+INF) */ + case 1: return -zero ; /* atan(-...,+INF) */ + case 2: return pi+tiny ; /* atan(+...,-INF) */ + case 3: return -pi-tiny ; /* atan(-...,-INF) */ + } + } + } + /* when y is INF */ + if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; + + /* compute y/x */ + k = (iy-ix)>>20; + if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */ + else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */ + else z=atan(fabs(y/x)); /* safe to do y/x */ + switch (m) { + case 0: return z ; /* atan(+,+) */ + case 1: { + uint32_t zh; + GET_HIGH_WORD(zh,z); + SET_HIGH_WORD(z,zh ^ 0x80000000); + } + return z ; /* atan(-,+) */ + case 2: return pi-(z-pi_lo);/* atan(+,-) */ + default: /* case 3 */ + return (z-pi_lo)-pi;/* atan(-,-) */ + } +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_exp.c b/libjava/classpath/native/fdlibm/e_exp.c new file mode 100644 index 00000000000..ad37f86b029 --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_exp.c @@ -0,0 +1,167 @@ + +/* @(#)e_exp.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_exp(x) + * Returns the exponential of x. + * + * Method + * 1. Argument reduction: + * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. + * Given x, find r and integer k such that + * + * x = k*ln2 + r, |r| <= 0.5*ln2. + * + * Here r will be represented as r = hi-lo for better + * accuracy. + * + * 2. Approximation of exp(r) by a special rational function on + * the interval [0,0.34658]: + * Write + * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... + * We use a special Reme algorithm on [0,0.34658] to generate + * a polynomial of degree 5 to approximate R. The maximum error + * of this polynomial approximation is bounded by 2**-59. In + * other words, + * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 + * (where z=r*r, and the values of P1 to P5 are listed below) + * and + * | 5 | -59 + * | 2.0+P1*z+...+P5*z - R(z) | <= 2 + * | | + * The computation of exp(r) thus becomes + * 2*r + * exp(r) = 1 + ------- + * R - r + * r*R1(r) + * = 1 + r + ----------- (for better accuracy) + * 2 - R1(r) + * where + * 2 4 10 + * R1(r) = r - (P1*r + P2*r + ... + P5*r ). + * + * 3. Scale back to obtain exp(x): + * From step 1, we have + * exp(x) = 2^k * exp(r) + * + * Special cases: + * exp(INF) is INF, exp(NaN) is NaN; + * exp(-INF) is 0, and + * for finite argument, only exp(0)=1 is exact. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Misc. info. + * For IEEE double + * if x > 7.09782712893383973096e+02 then exp(x) overflow + * if x < -7.45133219101941108420e+02 then exp(x) underflow + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +one = 1.0, +halF[2] = {0.5,-0.5,}, +huge = 1.0e+300, +twom1000= 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/ +o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ +u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */ +ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ + -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */ +ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ + -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */ +invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ + + +#ifdef __STDC__ + double __ieee754_exp(double x) /* default IEEE double exp */ +#else + double __ieee754_exp(x) /* default IEEE double exp */ + double x; +#endif +{ + double y,hi = 0., lo = 0.,c,t; + int32_t k = 0, xsb; + uint32_t hx; + + GET_HIGH_WORD(hx,x); + xsb = (hx>>31)&1; /* sign bit of x */ + hx &= 0x7fffffff; /* high word of |x| */ + + /* filter out non-finite argument */ + if(hx >= 0x40862E42) { /* if |x|>=709.78... */ + if(hx>=0x7ff00000) { + uint32_t lx; + GET_LOW_WORD(lx,x); + if(((hx&0xfffff)|lx)!=0) + return x+x; /* NaN */ + else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ + } + if(x > o_threshold) return huge*huge; /* overflow */ + if(x < u_threshold) return twom1000*twom1000; /* underflow */ + } + + /* argument reduction */ + if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ + if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ + hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; + } else { + k = invln2*x+halF[xsb]; + t = k; + hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */ + lo = t*ln2LO[0]; + } + x = hi - lo; + } + else if(hx < 0x3e300000) { /* when |x|<2**-28 */ + if(huge+x>one) return one+x;/* trigger inexact */ + } + else k = 0; + + /* x is now in primary range */ + t = x*x; + c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); + if(k==0) return one-((x*c)/(c-2.0)-x); + else y = one-((lo-(x*c)/(2.0-c))-hi); + if(k >= -1021) { + uint32_t hy; + GET_HIGH_WORD(hy,y); + SET_HIGH_WORD(y,hy+(k<<20)); /* add k to y's exponent */ + return y; + } else { + uint32_t hy; + GET_HIGH_WORD(hy,y); + SET_HIGH_WORD(y,hy+((k+1000)<<20)); /* add k to y's exponent */ + return y*twom1000; + } +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_fmod.c b/libjava/classpath/native/fdlibm/e_fmod.c new file mode 100644 index 00000000000..1cf09907666 --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_fmod.c @@ -0,0 +1,140 @@ + +/* @(#)e_fmod.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * __ieee754_fmod(x,y) + * Return x mod y in exact arithmetic + * Method: shift and subtract + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double one = 1.0, Zero[] = {0.0, -0.0,}; +#else +static double one = 1.0, Zero[] = {0.0, -0.0,}; +#endif + +#ifdef __STDC__ + double __ieee754_fmod(double x, double y) +#else + double __ieee754_fmod(x,y) + double x,y ; +#endif +{ + int32_t n,hx,hy,hz,ix,iy,sx,i; + uint32_t lx,ly,lz; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hy,ly,y); + sx = hx&0x80000000; /* sign of x */ + hx ^=sx; /* |x| */ + hy &= 0x7fffffff; /* |y| */ + + /* purge off exception values */ + if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */ + ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */ + return (x*y)/(x*y); + if(hx<=hy) { + if((hx<hy)||(lx<ly)) return x; /* |x|<|y| return x */ + if(lx==ly) + return Zero[(uint32_t)sx>>31]; /* |x|=|y| return x*0*/ + } + + /* determine ix = ilogb(x) */ + if(hx<0x00100000) { /* subnormal x */ + if(hx==0) { + for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; + } else { + for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1; + } + } else ix = (hx>>20)-1023; + + /* determine iy = ilogb(y) */ + if(hy<0x00100000) { /* subnormal y */ + if(hy==0) { + for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; + } else { + for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1; + } + } else iy = (hy>>20)-1023; + + /* set up {hx,lx}, {hy,ly} and align y to x */ + if(ix >= -1022) + hx = 0x00100000|(0x000fffff&hx); + else { /* subnormal x, shift x to normal */ + n = -1022-ix; + if(n<=31) { + hx = (hx<<n)|(lx>>(32-n)); + lx <<= n; + } else { + hx = lx<<(n-32); + lx = 0; + } + } + if(iy >= -1022) + hy = 0x00100000|(0x000fffff&hy); + else { /* subnormal y, shift y to normal */ + n = -1022-iy; + if(n<=31) { + hy = (hy<<n)|(ly>>(32-n)); + ly <<= n; + } else { + hy = ly<<(n-32); + ly = 0; + } + } + + /* fix point fmod */ + n = ix - iy; + while(n--) { + hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1; + if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;} + else { + if((hz|lz)==0) /* return sign(x)*0 */ + return Zero[(uint32_t)sx>>31]; + hx = hz+hz+(lz>>31); lx = lz+lz; + } + } + hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1; + if(hz>=0) {hx=hz;lx=lz;} + + /* convert back to floating value and restore the sign */ + if((hx|lx)==0) /* return sign(x)*0 */ + return Zero[(uint32_t)sx>>31]; + while(hx<0x00100000) { /* normalize x */ + hx = hx+hx+(lx>>31); lx = lx+lx; + iy -= 1; + } + if(iy>= -1022) { /* normalize output */ + hx = ((hx-0x00100000)|((iy+1023)<<20)); + INSERT_WORDS(x,hx|sx,lx); + } else { /* subnormal output */ + n = -1022 - iy; + if(n<=20) { + lx = (lx>>n)|((uint32_t)hx<<(32-n)); + hx >>= n; + } else if (n<=31) { + lx = (hx<<(32-n))|(lx>>n); hx = sx; + } else { + lx = hx>>(n-32); hx = sx; + } + INSERT_WORDS(x,hx|sx,lx); + x *= one; /* create necessary signal */ + } + return x; /* exact output */ +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_log.c b/libjava/classpath/native/fdlibm/e_log.c new file mode 100644 index 00000000000..093473e1048 --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_log.c @@ -0,0 +1,152 @@ + +/* @(#)e_log.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_log(x) + * Return the logrithm of x + * + * Method : + * 1. Argument Reduction: find k and f such that + * x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Approximation of log(1+f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s + * (the values of Lg1 to Lg7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lg1*s +...+Lg7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log(1+f) = f - s*(f - R) (if f is not too large) + * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) + * + * 3. Finally, log(x) = k*ln2 + log(1+f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log(x) is NaN with signal if x < 0 (including -INF) ; + * log(+INF) is +INF; log(0) is -INF with signal; + * log(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ +ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ +two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double __ieee754_log(double x) +#else + double __ieee754_log(x) + double x; +#endif +{ + double hfsq,f,s,z,R,w,t1,t2,dk; + int32_t k,hx,i,j; + uint32_t lx; + + EXTRACT_WORDS(hx,lx,x); + + k=0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx&0x7fffffff)|lx)==0) + return -two54/zero; /* log(+-0)=-inf */ + if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ + k -= 54; x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx,x); + } + if (hx >= 0x7ff00000) return x+x; + k += (hx>>20)-1023; + hx &= 0x000fffff; + i = (hx+0x95f64)&0x100000; + SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ + k += (i>>20); + f = x-1.0; + if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ + if(f==zero) { + if(k==0) + return zero; + else { + dk=(double)k; + return dk*ln2_hi+dk*ln2_lo; + } + } + R = f*f*(0.5-0.33333333333333333*f); + if(k==0) return f-R; else {dk=(double)k; + return dk*ln2_hi-((R-dk*ln2_lo)-f);} + } + s = f/(2.0+f); + dk = (double)k; + z = s*s; + i = hx-0x6147a; + w = z*z; + j = 0x6b851-hx; + t1= w*(Lg2+w*(Lg4+w*Lg6)); + t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); + i |= j; + R = t2+t1; + if(i>0) { + hfsq=0.5*f*f; + if(k==0) return f-(hfsq-s*(hfsq+R)); else + return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); + } else { + if(k==0) return f-s*(f-R); else + return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); + } +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_pow.c b/libjava/classpath/native/fdlibm/e_pow.c new file mode 100644 index 00000000000..b21c0e92b39 --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_pow.c @@ -0,0 +1,312 @@ + +/* @(#)e_pow.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_pow(x,y) return x**y + * + * n + * Method: Let x = 2 * (1+f) + * 1. Compute and return log2(x) in two pieces: + * log2(x) = w1 + w2, + * where w1 has 53-24 = 29 bit trailing zeros. + * 2. Perform y*log2(x) = n+y' by simulating muti-precision + * arithmetic, where |y'|<=0.5. + * 3. Return x**y = 2**n*exp(y'*log2) + * + * Special cases: + * 1. (anything) ** 0 is 1 + * 2. (anything) ** 1 is itself + * 3. (anything) ** NAN is NAN + * 4. NAN ** (anything except 0) is NAN + * 5. +-(|x| > 1) ** +INF is +INF + * 6. +-(|x| > 1) ** -INF is +0 + * 7. +-(|x| < 1) ** +INF is +0 + * 8. +-(|x| < 1) ** -INF is +INF + * 9. +-1 ** +-INF is NAN + * 10. +0 ** (+anything except 0, NAN) is +0 + * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 + * 12. +0 ** (-anything except 0, NAN) is +INF + * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF + * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) + * 15. +INF ** (+anything except 0,NAN) is +INF + * 16. +INF ** (-anything except 0,NAN) is +0 + * 17. -INF ** (anything) = -0 ** (-anything) + * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) + * 19. (-anything except 0 and inf) ** (non-integer) is NAN + * + * Accuracy: + * pow(x,y) returns x**y nearly rounded. In particular + * pow(integer,integer) + * always returns the correct integer provided it is + * representable. + * + * Constants : + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +bp[] = {1.0, 1.5,}, +dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ +dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ +zero = 0.0, +one = 1.0, +two = 2.0, +two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ +huge = 1.0e300, +tiny = 1.0e-300, + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ +L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ +L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ +L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ +L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ +L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ +lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ +lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ +ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ +cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ +cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ +cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ +ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ +ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ +ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ + +#ifdef __STDC__ + double __ieee754_pow(double x, double y) +#else + double __ieee754_pow(x,y) + double x, y; +#endif +{ + double z,ax,z_h,z_l,p_h,p_l; + double y1,t1,t2,r,s,t,u,v,w; + int32_t i,j,k,yisint,n; + int32_t hx,hy,ix,iy; + uint32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hy,ly,y); + ix = hx&0x7fffffff; iy = hy&0x7fffffff; + + /* y==zero: x**0 = 1 */ + if((iy|ly)==0) return one; + + /* +-NaN return x+y */ + if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || + iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) + return x+y; + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if(hx<0) { + if(iy>=0x43400000) yisint = 2; /* even integer y */ + else if(iy>=0x3ff00000) { + k = (iy>>20)-0x3ff; /* exponent */ + if(k>20) { + j = ly>>(52-k); + if((uint32_t)(j<<(52-k))==ly) yisint = 2-(j&1); + } else if(ly==0) { + j = iy>>(20-k); + if((j<<(20-k))==iy) yisint = 2-(j&1); + } + } + } + + /* special value of y */ + if(ly==0) { + if (iy==0x7ff00000) { /* y is +-inf */ + if(((ix-0x3ff00000)|lx)==0) + return y - y; /* inf**+-1 is NaN */ + else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */ + return (hy>=0)? y: zero; + else /* (|x|<1)**-,+inf = inf,0 */ + return (hy<0)?-y: zero; + } + if(iy==0x3ff00000) { /* y is +-1 */ + if(hy<0) return one/x; else return x; + } + if(hy==0x40000000) return x*x; /* y is 2 */ + if(hy==0x3fe00000) { /* y is 0.5 */ + if(hx>=0) /* x >= +0 */ + return __ieee754_sqrt(x); + } + } + + ax = fabs(x); + /* special value of x */ + if(lx==0) { + if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ + z = ax; /*x is +-0,+-inf,+-1*/ + if(hy<0) z = one/z; /* z = (1/|x|) */ + if(hx<0) { + if(((ix-0x3ff00000)|yisint)==0) { + z = (z-z)/(z-z); /* (-1)**non-int is NaN */ + } else if(yisint==1) + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + return z; + } + } + + /* (x<0)**(non-int) is NaN */ + /* GCJ LOCAL: This used to be + if((((hx>>31)+1)|yisint)==0) return (x-x)/(x-x); + but ANSI C says a right shift of a signed negative quantity is + implementation defined. */ + if(((((uint32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x); + + /* |y| is huge */ + if(iy>0x41e00000) { /* if |y| > 2**31 */ + if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ + if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + } + /* over/underflow if x is not close to one */ + if(ix<0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = x-1; /* t has 20 trailing zeros */ + w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25)); + u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ + v = t*ivln2_l-w*ivln2; + t1 = u+v; + SET_LOW_WORD(t1,0); + t2 = v-(t1-u); + } else { + double s2,s_h,s_l,t_h,t_l; + n = 0; + /* take care subnormal number */ + if(ix<0x00100000) + {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); } + n += ((ix)>>20)-0x3ff; + j = ix&0x000fffff; + /* determine interval */ + ix = j|0x3ff00000; /* normalize ix */ + if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */ + else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */ + else {k=0;n+=1;ix -= 0x00100000;} + SET_HIGH_WORD(ax,ix); + + /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */ + u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */ + v = one/(ax+bp[k]); + s = u*v; + s_h = s; + SET_LOW_WORD(s_h,0); + /* t_h=ax+bp[k] High */ + t_h = zero; + SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18)); + t_l = ax - (t_h-bp[k]); + s_l = v*((u-s_h*t_h)-s_h*t_l); + /* compute log(ax) */ + s2 = s*s; + r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); + r += s_l*(s_h+s); + s2 = s_h*s_h; + t_h = 3.0+s2+r; + SET_LOW_WORD(t_h,0); + t_l = r-((t_h-3.0)-s2); + /* u+v = s*(1+...) */ + u = s_h*t_h; + v = s_l*t_h+t_l*s; + /* 2/(3log2)*(s+...) */ + p_h = u+v; + SET_LOW_WORD(p_h,0); + p_l = v-(p_h-u); + z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l*p_h+p_l*cp+dp_l[k]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double)n; + t1 = (((z_h+z_l)+dp_h[k])+t); + SET_LOW_WORD(t1,0); + t2 = z_l-(((t1-t)-dp_h[k])-z_h); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if(((((uint32_t)hx>>31)-1)|(yisint-1))==0) + s = -one;/* (-ve)**(odd int) */ + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + y1 = y; + SET_LOW_WORD(y1,0); + p_l = (y-y1)*t1+y*t2; + p_h = y1*t1; + z = p_l+p_h; + EXTRACT_WORDS(j,i,z); + if (j>=0x40900000) { /* z >= 1024 */ + if(((j-0x40900000)|i)!=0) /* if z > 1024 */ + return s*huge*huge; /* overflow */ + else { + if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */ + } + } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ + if(((j-0xc090cc00)|i)!=0) /* z < -1075 */ + return s*tiny*tiny; /* underflow */ + else { + if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ + } + } + /* + * compute 2**(p_h+p_l) + */ + i = j&0x7fffffff; + k = (i>>20)-0x3ff; + n = 0; + if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j+(0x00100000>>(k+1)); + k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ + t = zero; + SET_HIGH_WORD(t,n&~(0x000fffff>>k)); + n = ((n&0x000fffff)|0x00100000)>>(20-k); + if(j<0) n = -n; + p_h -= t; + } + t = p_l+p_h; + SET_LOW_WORD(t,0); + u = t*lg2_h; + v = (p_l-(t-p_h))*lg2+t*lg2_l; + z = u+v; + w = v-(z-u); + t = z*z; + t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); + r = (z*t1)/(t1-two)-(w+z*w); + z = one-(r-z); + GET_HIGH_WORD(j,z); + j += (n<<20); + if((j>>20)<=0) z = scalbn(z,(int)n); /* subnormal output */ + else SET_HIGH_WORD(z,j); + return s*z; +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_rem_pio2.c b/libjava/classpath/native/fdlibm/e_rem_pio2.c new file mode 100644 index 00000000000..543234c60c5 --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_rem_pio2.c @@ -0,0 +1,185 @@ + +/* @(#)e_rem_pio2.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +/* __ieee754_rem_pio2(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __kernel_rem_pio2() + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + */ +#ifdef __STDC__ +static const int32_t two_over_pi[] = { +#else +static int32_t two_over_pi[] = { +#endif +0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, +0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, +0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, +0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, +0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, +0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, +0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, +0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, +0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, +0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, +0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, +}; + +#ifdef __STDC__ +static const int32_t npio2_hw[] = { +#else +static int32_t npio2_hw[] = { +#endif +0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, +0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, +0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, +0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C, +0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, +0x404858EB, 0x404921FB, +}; + +/* + * invpio2: 53 bits of 2/pi + * pio2_1: first 33 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 33 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 33 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ + +#ifdef __STDC__ +static const double +#else +static double +#endif +zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ +half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ +invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ +pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ +pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ +pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ +pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ +pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ +pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +#ifdef __STDC__ + int32_t __ieee754_rem_pio2(double x, double *y) +#else + int32_t __ieee754_rem_pio2(x,y) + double x,y[]; +#endif +{ + double z = 0., w, t, r, fn; + double tx[3]; + int32_t i,j,n,ix,hx; + int e0,nx; + uint32_t low; + + GET_HIGH_WORD(hx,x); /* high word of x */ + ix = hx&0x7fffffff; + if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ + {y[0] = x; y[1] = 0; return 0;} + if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ + if(hx>0) { + z = x - pio2_1; + if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z - pio2_1t; + y[1] = (z-y[0])-pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z -= pio2_2; + y[0] = z - pio2_2t; + y[1] = (z-y[0])-pio2_2t; + } + return 1; + } else { /* negative x */ + z = x + pio2_1; + if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z + pio2_1t; + y[1] = (z-y[0])+pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z += pio2_2; + y[0] = z + pio2_2t; + y[1] = (z-y[0])+pio2_2t; + } + return -1; + } + } + if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ + t = fabs(x); + n = (int32_t) (t*invpio2+half); + fn = (double)n; + r = t-fn*pio2_1; + w = fn*pio2_1t; /* 1st round good to 85 bit */ + if(n<32&&ix!=npio2_hw[n-1]) { + y[0] = r-w; /* quick check no cancellation */ + } else { + uint32_t high; + j = ix>>20; + y[0] = r-w; + GET_HIGH_WORD(high,y[0]); + i = j-((high>>20)&0x7ff); + if(i>16) { /* 2nd iteration needed, good to 118 */ + t = r; + w = fn*pio2_2; + r = t-w; + w = fn*pio2_2t-((t-r)-w); + y[0] = r-w; + GET_HIGH_WORD(high,y[0]); + i = j-((high>>20)&0x7ff); + if(i>49) { /* 3rd iteration need, 151 bits acc */ + t = r; /* will cover all possible cases */ + w = fn*pio2_3; + r = t-w; + w = fn*pio2_3t-((t-r)-w); + y[0] = r-w; + } + } + } + y[1] = (r-y[0])-w; + if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} + else return n; + } + /* + * all other (large) arguments + */ + if(ix>=0x7ff00000) { /* x is inf or NaN */ + y[0]=y[1]=x-x; return 0; + } + /* set z = scalbn(|x|,ilogb(x)-23) */ + GET_LOW_WORD(low,x); + SET_LOW_WORD(z,low); + e0 = (int)((ix>>20)-1046); /* e0 = ilogb(z)-23; */ + SET_HIGH_WORD(z, ix - ((int32_t)e0<<20)); + for(i=0;i<2;i++) { + tx[i] = (double)((int32_t)(z)); + z = (z-tx[i])*two24; + } + tx[2] = z; + nx = 3; + while(tx[nx-1]==zero) nx--; /* skip zero term */ + n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi); + if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} + return n; +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_remainder.c b/libjava/classpath/native/fdlibm/e_remainder.c new file mode 100644 index 00000000000..4716d8d05fd --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_remainder.c @@ -0,0 +1,80 @@ + +/* @(#)e_remainder.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_remainder(x,p) + * Return : + * returns x REM p = x - [x/p]*p as if in infinite + * precise arithmetic, where [x/p] is the (infinite bit) + * integer nearest x/p (in half way case choose the even one). + * Method : + * Based on fmod() return x-[x/p]chopped*p exactlp. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + + +#ifdef __STDC__ + double __ieee754_remainder(double x, double p) +#else + double __ieee754_remainder(x,p) + double x,p; +#endif +{ + int32_t hx,hp; + uint32_t sx,lx,lp; + double p_half; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hp,lp,p); + sx = hx&0x80000000; + hp &= 0x7fffffff; + hx &= 0x7fffffff; + + /* purge off exception values */ + if((hp|lp)==0) return (x*p)/(x*p); /* p = 0 */ + if((hx>=0x7ff00000)|| /* x not finite */ + ((hp>=0x7ff00000)&& /* p is NaN */ + (((hp-0x7ff00000)|lp)!=0))) + return (x*p)/(x*p); + + + if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p); /* now x < 2p */ + if (((hx-hp)|(lx-lp))==0) return zero*x; + x = fabs(x); + p = fabs(p); + if (hp<0x00200000) { + if(x+x>p) { + x-=p; + if(x+x>=p) x -= p; + } + } else { + p_half = 0.5*p; + if(x>p_half) { + x-=p; + if(x>=p_half) x -= p; + } + } + GET_HIGH_WORD(hx,x); + SET_HIGH_WORD(x,hx^sx); + return x; +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_scalb.c b/libjava/classpath/native/fdlibm/e_scalb.c new file mode 100644 index 00000000000..0bb924b43ee --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_scalb.c @@ -0,0 +1,55 @@ + +/* @(#)e_scalb.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * __ieee754_scalb(x, fn) is provide for + * passing various standard test suite. One + * should use scalbn() instead. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef _SCALB_INT +#ifdef __STDC__ + double __ieee754_scalb(double x, int fn) +#else + double __ieee754_scalb(x,fn) + double x; int fn; +#endif +#else +#ifdef __STDC__ + double __ieee754_scalb(double x, double fn) +#else + double __ieee754_scalb(x,fn) + double x, fn; +#endif +#endif +{ +#ifdef _SCALB_INT + return scalbn(x,fn); +#else + if (isnan(x)||isnan(fn)) return x*fn; + if (!finite(fn)) { + if(fn>0.0) return x*fn; + else return x/(-fn); + } + if (rint(fn)!=fn) return (fn-fn)/(fn-fn); + if ( fn > 65000.0) return scalbn(x, 65000); + if (-fn > 65000.0) return scalbn(x,-65000); + return scalbn(x,(int)fn); +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/e_sqrt.c b/libjava/classpath/native/fdlibm/e_sqrt.c new file mode 100644 index 00000000000..1d566a0847e --- /dev/null +++ b/libjava/classpath/native/fdlibm/e_sqrt.c @@ -0,0 +1,452 @@ + +/* @(#)e_sqrt.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_sqrt(x) + * Return correctly rounded sqrt. + * ------------------------------------------ + * | Use the hardware sqrt if you have one | + * ------------------------------------------ + * Method: + * Bit by bit method using integer arithmetic. (Slow, but portable) + * 1. Normalization + * Scale x to y in [1,4) with even powers of 2: + * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then + * sqrt(x) = 2^k * sqrt(y) + * 2. Bit by bit computation + * Let q = sqrt(y) truncated to i bit after binary point (q = 1), + * i 0 + * i+1 2 + * s = 2*q , and y = 2 * ( y - q ). (1) + * i i i i + * + * To compute q from q , one checks whether + * i+1 i + * + * -(i+1) 2 + * (q + 2 ) <= y. (2) + * i + * -(i+1) + * If (2) is false, then q = q ; otherwise q = q + 2 . + * i+1 i i+1 i + * + * With some algebric manipulation, it is not difficult to see + * that (2) is equivalent to + * -(i+1) + * s + 2 <= y (3) + * i i + * + * The advantage of (3) is that s and y can be computed by + * i i + * the following recurrence formula: + * if (3) is false + * + * s = s , y = y ; (4) + * i+1 i i+1 i + * + * otherwise, + * -i -(i+1) + * s = s + 2 , y = y - s - 2 (5) + * i+1 i i+1 i i + * + * One may easily use induction to prove (4) and (5). + * Note. Since the left hand side of (3) contain only i+2 bits, + * it does not necessary to do a full (53-bit) comparison + * in (3). + * 3. Final rounding + * After generating the 53 bits result, we compute one more bit. + * Together with the remainder, we can decide whether the + * result is exact, bigger than 1/2ulp, or less than 1/2ulp + * (it will never equal to 1/2ulp). + * The rounding mode can be detected by checking whether + * huge + tiny is equal to huge, and whether huge - tiny is + * equal to huge for some floating point number "huge" and "tiny". + * + * Special cases: + * sqrt(+-0) = +-0 ... exact + * sqrt(inf) = inf + * sqrt(-ve) = NaN ... with invalid signal + * sqrt(NaN) = NaN ... with invalid signal for signaling NaN + * + * Other methods : see the appended file at the end of the program below. + *--------------- + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double one = 1.0, tiny=1.0e-300; +#else +static double one = 1.0, tiny=1.0e-300; +#endif + +#ifdef __STDC__ + double __ieee754_sqrt(double x) +#else + double __ieee754_sqrt(x) + double x; +#endif +{ + double z; + int32_t sign = (int)0x80000000; + uint32_t r,t1,s1,ix1,q1; + int32_t ix0,s0,q,m,t,i; + + EXTRACT_WORDS(ix0,ix1,x); + + /* take care of Inf and NaN */ + if((ix0&0x7ff00000)==0x7ff00000) { + return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf + sqrt(-inf)=sNaN */ + } + /* take care of zero */ + if(ix0<=0) { + if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ + else if(ix0<0) + return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ + } + /* normalize x */ + m = (ix0>>20); + if(m==0) { /* subnormal x */ + while(ix0==0) { + m -= 21; + ix0 |= (ix1>>11); ix1 <<= 21; + } + for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; + m -= i-1; + ix0 |= (ix1>>(32-i)); + ix1 <<= i; + } + m -= 1023; /* unbias exponent */ + ix0 = (ix0&0x000fffff)|0x00100000; + if(m&1){ /* odd m, double x to make it even */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ + r = 0x00200000; /* r = moving bit from right to left */ + + while(r!=0) { + t = s0+r; + if(t<=ix0) { + s0 = t+r; + ix0 -= t; + q += r; + } + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + r>>=1; + } + + r = sign; + while(r!=0) { + t1 = s1+r; + t = s0; + if((t<ix0)||((t==ix0)&&(t1<=ix1))) { + s1 = t1+r; + if(((t1&sign)==(uint32_t)sign)&&(s1&sign)==0) s0 += 1; + ix0 -= t; + if (ix1 < t1) ix0 -= 1; + ix1 -= t1; + q1 += r; + } + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + r>>=1; + } + + /* use floating add to find out rounding direction */ + if((ix0|ix1)!=0) { + z = one-tiny; /* trigger inexact flag */ + if (z>=one) { + z = one+tiny; + if (q1==(uint32_t)0xffffffff) { q1=0; q += 1;} + else if (z>one) { + if (q1==(uint32_t)0xfffffffe) q+=1; + q1+=2; + } else + q1 += (q1&1); + } + } + ix0 = (q>>1)+0x3fe00000; + ix1 = q1>>1; + if ((q&1)==1) ix1 |= sign; + ix0 += (m <<20); + INSERT_WORDS(z,ix0,ix1); + return z; +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ + +/* +Other methods (use floating-point arithmetic) +------------- +(This is a copy of a drafted paper by Prof W. Kahan +and K.C. Ng, written in May, 1986) + + Two algorithms are given here to implement sqrt(x) + (IEEE double precision arithmetic) in software. + Both supply sqrt(x) correctly rounded. The first algorithm (in + Section A) uses newton iterations and involves four divisions. + The second one uses reciproot iterations to avoid division, but + requires more multiplications. Both algorithms need the ability + to chop results of arithmetic operations instead of round them, + and the INEXACT flag to indicate when an arithmetic operation + is executed exactly with no roundoff error, all part of the + standard (IEEE 754-1985). The ability to perform shift, add, + subtract and logical AND operations upon 32-bit words is needed + too, though not part of the standard. + +A. sqrt(x) by Newton Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + + 1 11 52 ...widths + ------------------------------------------------------ + x: |s| e | f | + ------------------------------------------------------ + msb lsb msb lsb ...order + + + ------------------------ ------------------------ + x0: |s| e | f1 | x1: | f2 | + ------------------------ ------------------------ + + By performing shifts and subtracts on x0 and x1 (both regarded + as integers), we obtain an 8-bit approximation of sqrt(x) as + follows. + + k := (x0>>1) + 0x1ff80000; + y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits + Here k is a 32-bit integer and T1[] is an integer array containing + correction terms. Now magically the floating value of y (y's + leading 32-bit word is y0, the value of its trailing word is 0) + approximates sqrt(x) to almost 8-bit. + + Value of T1: + static int T1[32]= { + 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, + 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, + 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, + 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; + + (2) Iterative refinement + + Apply Heron's rule three times to y, we have y approximates + sqrt(x) to within 1 ulp (Unit in the Last Place): + + y := (y+x/y)/2 ... almost 17 sig. bits + y := (y+x/y)/2 ... almost 35 sig. bits + y := y-(y-x/y)/2 ... within 1 ulp + + + Remark 1. + Another way to improve y to within 1 ulp is: + + y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) + y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) + + 2 + (x-y )*y + y := y + 2* ---------- ...within 1 ulp + 2 + 3y + x + + + This formula has one division fewer than the one above; however, + it requires more multiplications and additions. Also x must be + scaled in advance to avoid spurious overflow in evaluating the + expression 3y*y+x. Hence it is not recommended uless division + is slow. If division is very slow, then one should use the + reciproot algorithm given in section B. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + I := FALSE; ... reset INEXACT flag I + R := RZ; ... set rounding mode to round-toward-zero + z := x/y; ... chopped quotient, possibly inexact + If(not I) then { ... if the quotient is exact + if(z=y) { + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + } else { + z := z - ulp; ... special rounding + } + } + i := TRUE; ... sqrt(x) is inexact + If (r=RN) then z=z+ulp ... rounded-to-nearest + If (r=RP) then { ... round-toward-+inf + y = y+ulp; z=z+ulp; + } + y := y+z; ... chopped sum + y0:=y0-0x00100000; ... y := y/2 is correctly rounded. + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + + (4) Special cases + + Square root of +inf, +-0, or NaN is itself; + Square root of a negative number is NaN with invalid signal. + + +B. sqrt(x) by Reciproot Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + (see section A). By performing shifs and subtracts on x0 and y0, + we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. + + k := 0x5fe80000 - (x0>>1); + y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits + + Here k is a 32-bit integer and T2[] is an integer array + containing correction terms. Now magically the floating + value of y (y's leading 32-bit word is y0, the value of + its trailing word y1 is set to zero) approximates 1/sqrt(x) + to almost 7.8-bit. + + Value of T2: + static int T2[64]= { + 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, + 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, + 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, + 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, + 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, + 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, + 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, + 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; + + (2) Iterative refinement + + Apply Reciproot iteration three times to y and multiply the + result by x to get an approximation z that matches sqrt(x) + to about 1 ulp. To be exact, we will have + -1ulp < sqrt(x)-z<1.0625ulp. + + ... set rounding mode to Round-to-nearest + y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) + y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) + ... special arrangement for better accuracy + z := x*y ... 29 bits to sqrt(x), with z*y<1 + z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) + + Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that + (a) the term z*y in the final iteration is always less than 1; + (b) the error in the final result is biased upward so that + -1 ulp < sqrt(x) - z < 1.0625 ulp + instead of |sqrt(x)-z|<1.03125ulp. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + R := RZ; ... set rounding mode to round-toward-zero + switch(r) { + case RN: ... round-to-nearest + if(x<= z*(z-ulp)...chopped) z = z - ulp; else + if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; + break; + case RZ:case RM: ... round-to-zero or round-to--inf + R:=RP; ... reset rounding mod to round-to-+inf + if(x<z*z ... rounded up) z = z - ulp; else + if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; + break; + case RP: ... round-to-+inf + if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else + if(x>z*z ...chopped) z = z+ulp; + break; + } + + Remark 3. The above comparisons can be done in fixed point. For + example, to compare x and w=z*z chopped, it suffices to compare + x1 and w1 (the trailing parts of x and w), regarding them as + two's complement integers. + + ...Is z an exact square root? + To determine whether z is an exact square root of x, let z1 be the + trailing part of z, and also let x0 and x1 be the leading and + trailing parts of x. + + If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 + I := 1; ... Raise Inexact flag: z is not exact + else { + j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 + k := z1 >> 26; ... get z's 25-th and 26-th + fraction bits + I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); + } + R:= r ... restore rounded mode + return sqrt(x):=z. + + If multiplication is cheaper then the foregoing red tape, the + Inexact flag can be evaluated by + + I := i; + I := (z*z!=x) or I. + + Note that z*z can overwrite I; this value must be sensed if it is + True. + + Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be + zero. + + -------------------- + z1: | f2 | + -------------------- + bit 31 bit 0 + + Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd + or even of logb(x) have the following relations: + + ------------------------------------------------- + bit 27,26 of z1 bit 1,0 of x1 logb(x) + ------------------------------------------------- + 00 00 odd and even + 01 01 even + 10 10 odd + 10 00 even + 11 01 even + ------------------------------------------------- + + (4) Special cases (see (4) of Section A). + + */ diff --git a/libjava/classpath/native/fdlibm/fdlibm.h b/libjava/classpath/native/fdlibm/fdlibm.h new file mode 100644 index 00000000000..156a03c1e45 --- /dev/null +++ b/libjava/classpath/native/fdlibm/fdlibm.h @@ -0,0 +1,354 @@ + +/* @(#)fdlibm.h 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993, 2000 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#ifndef __CLASSPATH_FDLIBM_H__ +#define __CLASSPATH_FDLIBM_H__ + +/* AIX needs _XOPEN_SOURCE */ +#ifdef _AIX +#define _XOPEN_SOURCE +#endif + +#include <config.h> +#include <stdlib.h> + +/* GCJ LOCAL: Include files. */ +#include "ieeefp.h" + +#include "mprec.h" + +/* CYGNUS LOCAL: Default to XOPEN_MODE. */ +#define _XOPEN_MODE + +#ifdef __P +#undef __P +#endif + +#ifdef __STDC__ +#define __P(p) p +#else +#define __P(p) () +#endif + +#ifndef HUGE +#define HUGE ((float)3.40282346638528860e+38) +#endif + +/* + * set X_TLOSS = pi*2**52, which is possibly defined in <values.h> + * (one may replace the following line by "#include <values.h>") + */ + +#define X_TLOSS 1.41484755040568800000e+16 + +/* These typedefs are true for the targets running Java. */ + +#define _IEEE_LIBM + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ANSI/POSIX + */ +extern double acos __P((double)); +extern double asin __P((double)); +extern double atan __P((double)); +extern double atan2 __P((double, double)); +extern double cos __P((double)); +extern double sin __P((double)); +extern double tan __P((double)); + +extern double cosh __P((double)); +extern double sinh __P((double)); +extern double tanh __P((double)); + +extern double exp __P((double)); +extern double frexp __P((double, int *)); +extern double ldexp __P((double, int)); +extern double log __P((double)); +extern double log10 __P((double)); +extern double modf __P((double, double *)); + +extern double pow __P((double, double)); +extern double sqrt __P((double)); + +extern double ceil __P((double)); +extern double fabs __P((double)); +extern double floor __P((double)); +extern double fmod __P((double, double)); + +extern double erf __P((double)); +extern double erfc __P((double)); +extern double gamma __P((double)); +extern double hypot __P((double, double)); +extern int isnan __P((double)); +extern int finite __P((double)); +extern double j0 __P((double)); +extern double j1 __P((double)); +extern double jn __P((int, double)); +extern double lgamma __P((double)); +extern double y0 __P((double)); +extern double y1 __P((double)); +extern double yn __P((int, double)); + +extern double acosh __P((double)); +extern double asinh __P((double)); +extern double atanh __P((double)); +extern double cbrt __P((double)); +extern double logb __P((double)); +extern double nextafter __P((double, double)); +extern double remainder __P((double, double)); + +/* Functions that are not documented, and are not in <math.h>. */ + +extern double logb __P((double)); +#ifdef _SCALB_INT +extern double scalb __P((double, int)); +#else +extern double scalb __P((double, double)); +#endif +extern double significand __P((double)); + +/* ieee style elementary functions */ +extern double __ieee754_sqrt __P((double)); +extern double __ieee754_acos __P((double)); +extern double __ieee754_acosh __P((double)); +extern double __ieee754_log __P((double)); +extern double __ieee754_atanh __P((double)); +extern double __ieee754_asin __P((double)); +extern double __ieee754_atan2 __P((double,double)); +extern double __ieee754_exp __P((double)); +extern double __ieee754_cosh __P((double)); +extern double __ieee754_fmod __P((double,double)); +extern double __ieee754_pow __P((double,double)); +extern double __ieee754_lgamma_r __P((double,int *)); +extern double __ieee754_gamma_r __P((double,int *)); +extern double __ieee754_log10 __P((double)); +extern double __ieee754_sinh __P((double)); +extern double __ieee754_hypot __P((double,double)); +extern double __ieee754_j0 __P((double)); +extern double __ieee754_j1 __P((double)); +extern double __ieee754_y0 __P((double)); +extern double __ieee754_y1 __P((double)); +extern double __ieee754_jn __P((int,double)); +extern double __ieee754_yn __P((int,double)); +extern double __ieee754_remainder __P((double,double)); +extern int32_t __ieee754_rem_pio2 __P((double,double*)); +#ifdef _SCALB_INT +extern double __ieee754_scalb __P((double,int)); +#else +extern double __ieee754_scalb __P((double,double)); +#endif + +/* fdlibm kernel function */ +extern double __kernel_standard __P((double,double,int)); +extern double __kernel_sin __P((double,double,int)); +extern double __kernel_cos __P((double,double)); +extern double __kernel_tan __P((double,double,int)); +extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int32_t*)); + +/* Undocumented float functions. */ +extern float logbf __P((float)); +#ifdef _SCALB_INT +extern float scalbf __P((float, int)); +#else +extern float scalbf __P((float, float)); +#endif +extern float significandf __P((float)); + +/* + * Functions callable from C, intended to support IEEE arithmetic. + */ +extern double copysign __P((double, double)); +extern int ilogb __P((double)); +extern double rint __P((double)); +extern float rintf __P((float)); +extern double scalbn __P((double, int)); + +/* ieee style elementary float functions */ +extern float __ieee754_sqrtf __P((float)); +extern float __ieee754_acosf __P((float)); +extern float __ieee754_acoshf __P((float)); +extern float __ieee754_logf __P((float)); +extern float __ieee754_atanhf __P((float)); +extern float __ieee754_asinf __P((float)); +extern float __ieee754_atan2f __P((float,float)); +extern float __ieee754_expf __P((float)); +extern float __ieee754_coshf __P((float)); +extern float __ieee754_fmodf __P((float,float)); +extern float __ieee754_powf __P((float,float)); +extern float __ieee754_lgammaf_r __P((float,int *)); +extern float __ieee754_gammaf_r __P((float,int *)); +extern float __ieee754_log10f __P((float)); +extern float __ieee754_sinhf __P((float)); +extern float __ieee754_hypotf __P((float,float)); +extern float __ieee754_j0f __P((float)); +extern float __ieee754_j1f __P((float)); +extern float __ieee754_y0f __P((float)); +extern float __ieee754_y1f __P((float)); +extern float __ieee754_jnf __P((int,float)); +extern float __ieee754_ynf __P((int,float)); +extern float __ieee754_remainderf __P((float,float)); +extern int32_t __ieee754_rem_pio2f __P((float,float*)); +#ifdef _SCALB_INT +extern float __ieee754_scalbf __P((float,int)); +#else +extern float __ieee754_scalbf __P((float,float)); +#endif + +/* float versions of fdlibm kernel functions */ +extern float __kernel_sinf __P((float,float,int)); +extern float __kernel_cosf __P((float,float)); +extern float __kernel_tanf __P((float,float,int)); +extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const int32_t*)); + +/* The original code used statements like + n0 = ((*(int*)&one)>>29)^1; * index of high word * + ix0 = *(n0+(int*)&x); * high word of x * + ix1 = *((1-n0)+(int*)&x); * low word of x * + to dig two 32 bit words out of the 64 bit IEEE floating point + value. That is non-ANSI, and, moreover, the gcc instruction + scheduler gets it wrong. We instead use the following macros. + Unlike the original code, we determine the endianness at compile + time, not at run time; I don't see much benefit to selecting + endianness at run time. */ + +#ifndef __IEEE_BIG_ENDIAN +#ifndef __IEEE_LITTLE_ENDIAN + #error Must define endianness +#endif +#endif + +/* A union which permits us to convert between a double and two 32 bit + ints. */ + +#ifdef __IEEE_BIG_ENDIAN + +typedef union +{ + double value; + struct + { + uint32_t msw; + uint32_t lsw; + } parts; +} ieee_double_shape_type; + +#endif + +#ifdef __IEEE_LITTLE_ENDIAN + +typedef union +{ + double value; + struct + { + uint32_t lsw; + uint32_t msw; + } parts; +} ieee_double_shape_type; + +#endif + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Get the more significant 32 bit int from a double. */ + +#define GET_HIGH_WORD(i,d) \ +do { \ + ieee_double_shape_type gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ +} while (0) + +/* Get the less significant 32 bit int from a double. */ + +#define GET_LOW_WORD(i,d) \ +do { \ + ieee_double_shape_type gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS(d,ix0,ix1) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Set the more significant 32 bits of a double from an int. */ + +#define SET_HIGH_WORD(d,v) \ +do { \ + ieee_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Set the less significant 32 bits of a double from an int. */ + +#define SET_LOW_WORD(d,v) \ +do { \ + ieee_double_shape_type sl_u; \ + sl_u.value = (d); \ + sl_u.parts.lsw = (v); \ + (d) = sl_u.value; \ +} while (0) + +/* A union which permits us to convert between a float and a 32 bit + int. */ + +typedef union +{ + float value; + uint32_t word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + +#ifdef __cplusplus +} +#endif + +#endif /* __CLASSPATH_FDLIBM_H__ */ diff --git a/libjava/classpath/native/fdlibm/ieeefp.h b/libjava/classpath/native/fdlibm/ieeefp.h new file mode 100644 index 00000000000..405baab5840 --- /dev/null +++ b/libjava/classpath/native/fdlibm/ieeefp.h @@ -0,0 +1,167 @@ +#ifndef __CLASSPATH_IEEEFP_H__ +#define __CLASSPATH_IEEEFP_H__ + +#ifndef __IEEE_BIG_ENDIAN +#ifndef __IEEE_LITTLE_ENDIAN + +#ifdef __alpha__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#if defined(__arm__) || defined(__thumb__) +/* ARM traditionally used big-endian words; and within those words the + byte ordering was big or little endian depending upon the target. + Modern floating-point formats are naturally ordered; in this case + __VFP_FP__ will be defined, even if soft-float. */ +#ifdef __VFP_FP__ +#ifdef __ARMEL__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#else +#define __IEEE_BIG_ENDIAN +#ifdef __ARMEL__ +#define __IEEE_BYTES_LITTLE_ENDIAN +#endif +#endif +#endif + +#ifdef __hppa__ +#define __IEEE_BIG_ENDIAN +#endif + +#if defined (__sparc) || defined (__sparc__) +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __m32r__ +#ifdef __LITTLE_ENDIAN__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#endif + +#if defined(__m68k__) || defined(__mc68000__) +#define __IEEE_BIG_ENDIAN +#endif + +#if defined (__H8300__) || defined (__H8300H__) +#define __IEEE_BIG_ENDIAN +#define __SMALL_BITFIELDS +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __H8500__ +#define __IEEE_BIG_ENDIAN +#define __SMALL_BITFIELDS +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __sh__ +#ifdef __LITTLE_ENDIAN__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __SH3E__ +#define _DOUBLE_IS_32BITS +#endif +#endif + +#ifdef _AM29K +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __i386__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __x86_64__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __i960__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __MIPSEL__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __MIPSEB__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __pj__ +#ifdef __pjl__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#endif + +/* necv70 was __IEEE_LITTLE_ENDIAN. */ + +#ifdef __W65__ +#define __IEEE_LITTLE_ENDIAN +#define __SMALL_BITFIELDS +#define _DOUBLE_IS_32BITS +#endif + +#if defined(__Z8001__) || defined(__Z8002__) +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __m88k__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __v800 +#define __IEEE_LITTLE_ENDIAN +#endif + +#if defined (__PPC__) || defined (__ppc__) || defined (__ppc64__) +#if (defined(_BIG_ENDIAN) && _BIG_ENDIAN) || (defined(_AIX) && _AIX) \ + || defined (__APPLE__) +#define __IEEE_BIG_ENDIAN +#else +#if (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN) || (defined(__sun__) && __sun__) || (defined(__WIN32__) && __WIN32__) +#define __IEEE_LITTLE_ENDIAN +#endif +#endif +#endif + +#ifdef __fr30__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __mcore__ +#define __IEEE_BIG_ENDIAN +#endif + + +#ifdef __ia64__ +#ifdef __BIG_ENDIAN__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __s390__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifndef __IEEE_BIG_ENDIAN +#ifndef __IEEE_LITTLE_ENDIAN +#error Endianess not declared!! +#endif /* not __IEEE_LITTLE_ENDIAN */ +#endif /* not __IEEE_BIG_ENDIAN */ + +#endif /* not __IEEE_LITTLE_ENDIAN */ +#endif /* not __IEEE_BIG_ENDIAN */ + +#endif /* __CLASSPATH_IEEEFP_H__ */ diff --git a/libjava/classpath/native/fdlibm/java-assert.h b/libjava/classpath/native/fdlibm/java-assert.h new file mode 100644 index 00000000000..6f178bd9e98 --- /dev/null +++ b/libjava/classpath/native/fdlibm/java-assert.h @@ -0,0 +1,38 @@ +// java-assert.h - Header file holding assertion definitions. -*- c++ -*- + +/* Copyright (C) 1998, 1999 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#ifndef __JAVA_ASSERT_H__ +#define __JAVA_ASSERT_H__ + +// This is a libgcj implementation header. + +void _Jv_Abort (const char *, const char *, int, const char *) + __attribute__ ((__noreturn__)); + +#ifdef DEBUG +#define _Jv_AssertDoCall(Message) _Jv_Abort (__FUNCTION__, __FILE__, __LINE__, Message) + +#define JvAssertMessage(Expr, Message) \ + do { if (! (Expr)) _Jv_AssertDoCall (Message); } while (0) +#define JvAssert(Expr) \ + do { if (! (Expr)) _Jv_AssertDoCall (# Expr); } while (0) + +#define JvFail(Message) _Jv_AssertDoCall (Message) + +#else /* DEBUG */ + +#define _Jv_AssertDoCall(Message) +#define JvAssertMessage(Expr, Message) +#define JvAssert(Expr) +#define JvFail(Message) _Jv_Abort (0, 0, 0, Message) + +#endif /* not DEBUG */ + +#endif /* __JAVA_ASSERT_H__ */ diff --git a/libjava/classpath/native/fdlibm/k_cos.c b/libjava/classpath/native/fdlibm/k_cos.c new file mode 100644 index 00000000000..acf50a82e83 --- /dev/null +++ b/libjava/classpath/native/fdlibm/k_cos.c @@ -0,0 +1,96 @@ + +/* @(#)k_cos.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * __kernel_cos( x, y ) + * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * + * Algorithm + * 1. Since cos(-x) = cos(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. + * 3. cos(x) is approximated by a polynomial of degree 14 on + * [0,pi/4] + * 4 14 + * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x + * where the remez error is + * + * | 2 4 6 8 10 12 14 | -58 + * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 + * | | + * + * 4 6 8 10 12 14 + * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then + * cos(x) = 1 - x*x/2 + r + * since cos(x+y) ~ cos(x) - sin(x)*y + * ~ cos(x) - x*y, + * a correction term is necessary in cos(x) and hence + * cos(x+y) = 1 - (x*x/2 - (r - x*y)) + * For better accuracy when x > 0.3, let qx = |x|/4 with + * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. + * Then + * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)). + * Note that 1-qx and (x*x/2-qx) is EXACT here, and the + * magnitude of the latter is at least a quarter of x*x/2, + * thus, reducing the rounding error in the subtraction. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ +C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ +C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ +C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ +C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ +C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ + +#ifdef __STDC__ + double __kernel_cos(double x, double y) +#else + double __kernel_cos(x, y) + double x,y; +#endif +{ + double a,hz,z,r,qx; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; /* ix = |x|'s high word*/ + if(ix<0x3e400000) { /* if x < 2**27 */ + if(((int)x)==0) return one; /* generate inexact */ + } + z = x*x; + r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); + if(ix < 0x3FD33333) /* if |x| < 0.3 */ + return one - (0.5*z - (z*r - x*y)); + else { + if(ix > 0x3fe90000) { /* x > 0.78125 */ + qx = 0.28125; + } else { + INSERT_WORDS(qx,ix-0x00200000,0); /* x/4 */ + } + hz = 0.5*z-qx; + a = one-qx; + return a - (hz - (z*r-x*y)); + } +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/k_rem_pio2.c b/libjava/classpath/native/fdlibm/k_rem_pio2.c new file mode 100644 index 00000000000..2f4ca17256c --- /dev/null +++ b/libjava/classpath/native/fdlibm/k_rem_pio2.c @@ -0,0 +1,320 @@ + +/* @(#)k_rem_pio2.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) + * double x[],y[]; int e0,nx,prec; int ipio2[]; + * + * __kernel_rem_pio2 return the last three digits of N with + * y = x - N*pi/2 + * so that |y| < pi/2. + * + * The method is to compute the integer (mod 8) and fraction parts of + * (2/pi)*x without doing the full multiplication. In general we + * skip the part of the product that are known to be a huge integer ( + * more accurately, = 0 mod 8 ). Thus the number of operations are + * independent of the exponent of the input. + * + * (2/pi) is represented by an array of 24-bit integers in ipio2[]. + * + * Input parameters: + * x[] The input value (must be positive) is broken into nx + * pieces of 24-bit integers in double precision format. + * x[i] will be the i-th 24 bit of x. The scaled exponent + * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 + * match x's up to 24 bits. + * + * Example of breaking a double positive z into x[0]+x[1]+x[2]: + * e0 = ilogb(z)-23 + * z = scalbn(z,-e0) + * for i = 0,1,2 + * x[i] = floor(z) + * z = (z-x[i])*2**24 + * + * + * y[] ouput result in an array of double precision numbers. + * The dimension of y[] is: + * 24-bit precision 1 + * 53-bit precision 2 + * 64-bit precision 2 + * 113-bit precision 3 + * The actual value is the sum of them. Thus for 113-bit + * precison, one may have to do something like: + * + * long double t,w,r_head, r_tail; + * t = (long double)y[2] + (long double)y[1]; + * w = (long double)y[0]; + * r_head = t+w; + * r_tail = w - (r_head - t); + * + * e0 The exponent of x[0] + * + * nx dimension of x[] + * + * prec an integer indicating the precision: + * 0 24 bits (single) + * 1 53 bits (double) + * 2 64 bits (extended) + * 3 113 bits (quad) + * + * ipio2[] + * integer array, contains the (24*i)-th to (24*i+23)-th + * bit of 2/pi after binary point. The corresponding + * floating value is + * + * ipio2[i] * 2^(-24(i+1)). + * + * External function: + * double scalbn(), floor(); + * + * + * Here is the description of some local variables: + * + * jk jk+1 is the initial number of terms of ipio2[] needed + * in the computation. The recommended value is 2,3,4, + * 6 for single, double, extended,and quad. + * + * jz local integer variable indicating the number of + * terms of ipio2[] used. + * + * jx nx - 1 + * + * jv index for pointing to the suitable ipio2[] for the + * computation. In general, we want + * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 + * is an integer. Thus + * e0-3-24*jv >= 0 or (e0-3)/24 >= jv + * Hence jv = max(0,(e0-3)/24). + * + * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. + * + * q[] double array with integral value, representing the + * 24-bits chunk of the product of x and 2/pi. + * + * q0 the corresponding exponent of q[0]. Note that the + * exponent for q[i] would be q0-24*i. + * + * PIo2[] double precision array, obtained by cutting pi/2 + * into 24 bits chunks. + * + * f[] ipio2[] in floating point + * + * iq[] integer array by breaking up q[] in 24-bits chunk. + * + * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] + * + * ih integer. If >0 it indicates q[] is >= 0.5, hence + * it also indicates the *sign* of the result. + * + */ + + +/* + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const int init_jk[] = {2,3,4,6}; /* initial value for jk */ +#else +static int init_jk[] = {2,3,4,6}; +#endif + +#ifdef __STDC__ +static const double PIo2[] = { +#else +static double PIo2[] = { +#endif + 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ + 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ + 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ + 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ + 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ + 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ + 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ +}; + +#ifdef __STDC__ +static const double +#else +static double +#endif +zero = 0.0, +one = 1.0, +two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ +twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ + +#ifdef __STDC__ + int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2) +#else + int __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) + double x[], y[]; int e0,nx,prec; int32_t ipio2[]; +#endif +{ + int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; + double z,fw,f[20],fq[20],q[20]; + + /* initialize jk*/ + jk = init_jk[prec]; + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx-1; + jv = (e0-3)/24; if(jv<0) jv=0; + q0 = e0-24*(jv+1); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + j = jv-jx; m = jx+jk; + for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j]; + + /* compute q[0],q[1],...q[jk] */ + for (i=0;i<=jk;i++) { + for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; + } + + jz = jk; +recompute: + /* distill q[] into iq[] reversingly */ + for(i=0,j=jz,z=q[jz];j>0;i++,j--) { + fw = (double)((int32_t)(twon24* z)); + iq[i] = (int32_t)(z-two24*fw); + z = q[j-1]+fw; + } + + /* compute n */ + z = scalbn(z,(int)q0); /* actual value of z */ + z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ + n = (int32_t) z; + z -= (double)n; + ih = 0; + if(q0>0) { /* need iq[jz-1] to determine n */ + i = (iq[jz-1]>>(24-q0)); n += i; + iq[jz-1] -= i<<(24-q0); + ih = iq[jz-1]>>(23-q0); + } + else if(q0==0) ih = iq[jz-1]>>23; + else if(z>=0.5) ih=2; + + if(ih>0) { /* q > 0.5 */ + n += 1; carry = 0; + for(i=0;i<jz ;i++) { /* compute 1-q */ + j = iq[i]; + if(carry==0) { + if(j!=0) { + carry = 1; iq[i] = 0x1000000- j; + } + } else iq[i] = 0xffffff - j; + } + if(q0>0) { /* rare case: chance is 1 in 12 */ + switch(q0) { + case 1: + iq[jz-1] &= 0x7fffff; break; + case 2: + iq[jz-1] &= 0x3fffff; break; + } + } + if(ih==2) { + z = one - z; + if(carry!=0) z -= scalbn(one,(int)q0); + } + } + + /* check if recomputation is needed */ + if(z==zero) { + j = 0; + for (i=jz-1;i>=jk;i--) j |= iq[i]; + if(j==0) { /* need recomputation */ + for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ + + for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ + f[jx+i] = (double) ipio2[jv+i]; + for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; + q[i] = fw; + } + jz += k; + goto recompute; + } + } + + /* chop off zero terms */ + if(z==0.0) { + jz -= 1; q0 -= 24; + while(iq[jz]==0) { jz--; q0-=24;} + } else { /* break z into 24-bit if necessary */ + z = scalbn(z,-(int)q0); + if(z>=two24) { + fw = (double)((int32_t)(twon24*z)); + iq[jz] = (int32_t)(z-two24*fw); + jz += 1; q0 += 24; + iq[jz] = (int32_t) fw; + } else iq[jz] = (int32_t) z ; + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbn(one,(int)q0); + for(i=jz;i>=0;i--) { + q[i] = fw*(double)iq[i]; fw*=twon24; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for(i=jz;i>=0;i--) { + for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; + fq[jz-i] = fw; + } + + /* compress fq[] into y[] */ + switch(prec) { + case 0: + fw = 0.0; + for (i=jz;i>=0;i--) fw += fq[i]; + y[0] = (ih==0)? fw: -fw; + break; + case 1: + case 2: + fw = 0.0; + for (i=jz;i>=0;i--) fw += fq[i]; + y[0] = (ih==0)? fw: -fw; + fw = fq[0]-fw; + for (i=1;i<=jz;i++) fw += fq[i]; + y[1] = (ih==0)? fw: -fw; + break; + case 3: /* painful */ + for (i=jz;i>0;i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (i=jz;i>1;i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; + if(ih==0) { + y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; + } else { + y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; + } + } + return n&7; +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/k_sin.c b/libjava/classpath/native/fdlibm/k_sin.c new file mode 100644 index 00000000000..b4ad387c589 --- /dev/null +++ b/libjava/classpath/native/fdlibm/k_sin.c @@ -0,0 +1,79 @@ + +/* @(#)k_sin.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __kernel_sin( x, y, iy) + * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). + * + * Algorithm + * 1. Since sin(-x) = -sin(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0. + * 3. sin(x) is approximated by a polynomial of degree 13 on + * [0,pi/4] + * 3 13 + * sin(x) ~ x + S1*x + ... + S6*x + * where + * + * |sin(x) 2 4 6 8 10 12 | -58 + * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 + * | x | + * + * 4. sin(x+y) = sin(x) + sin'(x')*y + * ~ sin(x) + (1-x*x/2)*y + * For better accuracy, let + * 3 2 2 2 2 + * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) + * then 3 2 + * sin(x) = x + (S1*x + (x *(r-y/2)+y)) + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ +S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ +S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ +S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ +S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ +S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + +#ifdef __STDC__ + double __kernel_sin(double x, double y, int iy) +#else + double __kernel_sin(x, y, iy) + double x,y; int iy; /* iy=0 if y is zero */ +#endif +{ + double z,r,v; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; /* high word of x */ + if(ix<0x3e400000) /* |x| < 2**-27 */ + {if((int)x==0) return x;} /* generate inexact */ + z = x*x; + v = z*x; + r = S2+z*(S3+z*(S4+z*(S5+z*S6))); + if(iy==0) return x+v*(S1+z*r); + else return x-((z*(half*y-v*r)-y)-v*S1); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/k_tan.c b/libjava/classpath/native/fdlibm/k_tan.c new file mode 100644 index 00000000000..a1067a70a0d --- /dev/null +++ b/libjava/classpath/native/fdlibm/k_tan.c @@ -0,0 +1,132 @@ + +/* @(#)k_tan.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __kernel_tan( x, y, k ) + * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input k indicates whether tan (if k=1) or + * -1/tan (if k= -1) is returned. + * + * Algorithm + * 1. Since tan(-x) = -tan(x), we need only to consider positive x. + * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. + * 3. tan(x) is approximated by a odd polynomial of degree 27 on + * [0,0.67434] + * 3 27 + * tan(x) ~ x + T1*x + ... + T13*x + * where + * + * |tan(x) 2 4 26 | -59.2 + * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 + * | x | + * + * Note: tan(x+y) = tan(x) + tan'(x)*y + * ~ tan(x) + (1+x*x)*y + * Therefore, for better accuracy in computing tan(x+y), let + * 3 2 2 2 2 + * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) + * then + * 3 2 + * tan(x+y) = x + (T1*x + (x *(r+y)+y)) + * + * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then + * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) + * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ +pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */ +T[] = { + 3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */ + 1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */ + 5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */ + 2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */ + 8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */ + 3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */ + 1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */ + 5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */ + 2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */ + 7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */ + 7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */ + -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */ + 2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */ +}; + +#ifdef __STDC__ + double __kernel_tan(double x, double y, int iy) +#else + double __kernel_tan(x, y, iy) + double x,y; int iy; +#endif +{ + double z,r,v,w,s; + int32_t ix,hx; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; /* high word of |x| */ + if(ix<0x3e300000) /* x < 2**-28 */ + {if((int)x==0) { /* generate inexact */ + uint32_t low; + GET_LOW_WORD(low,x); + if(((ix|low)|(iy+1))==0) return one/fabs(x); + else return (iy==1)? x: -one/x; + } + } + if(ix>=0x3FE59428) { /* |x|>=0.6744 */ + if(hx<0) {x = -x; y = -y;} + z = pio4-x; + w = pio4lo-y; + x = z+w; y = 0.0; + } + z = x*x; + w = z*z; + /* Break x^5*(T[1]+x^2*T[2]+...) into + * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) + */ + r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11])))); + v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12]))))); + s = z*x; + r = y + z*(s*(r+v)+y); + r += T[0]*s; + w = x+r; + if(ix>=0x3FE59428) { + v = (double)iy; + return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r))); + } + if(iy==1) return w; + else { /* if allow error up to 2 ulp, + simply return -1.0/(x+r) here */ + /* compute -1.0/(x+r) accurately */ + double a,t; + z = w; + SET_LOW_WORD(z,0); + v = r-(z - x); /* z+v = r+x */ + t = a = -1.0/w; /* a = -1.0/w */ + SET_LOW_WORD(t,0); + s = 1.0+t*z; + return t+a*(s+t*v); + } +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/mprec.c b/libjava/classpath/native/fdlibm/mprec.c new file mode 100644 index 00000000000..00679ed3918 --- /dev/null +++ b/libjava/classpath/native/fdlibm/mprec.c @@ -0,0 +1,958 @@ +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991 by AT&T. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_8087 for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_MC68k for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Sudden_Underflow for IEEE-format machines without gradual + * underflow (i.e., that flush to zero on underflow). + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic. + * #define Unsigned_Shifts if >> does treats its left operand as unsigned. + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define Just_16 to store 16 bits per 32-bit long when doing high-precision + * integer arithmetic. Whether this speeds things up or slows things + * down depends on the machine and the number being converted. + */ + +#include <stdlib.h> +#include <string.h> +#include <java-assert.h> +#include "mprec.h" + +/* reent.c knows this value */ +#define _Kmax 15 +#include <stdio.h> + +_Jv_Bigint * +_DEFUN (Balloc, (ptr, k), struct _Jv_reent *ptr _AND int k) +{ + _Jv_Bigint *rv = NULL; + + int i = 0; + int j = 1; + + JvAssert ((1 << k) < MAX_BIGNUM_WDS); + + while ((ptr->_allocation_map & j) && i < MAX_BIGNUMS) + i++, j <<= 1; + + JvAssert (i < MAX_BIGNUMS); + + if (i >= MAX_BIGNUMS) + return NULL; + + ptr->_allocation_map |= j; + rv = &ptr->_freelist[i]; + + rv->_k = k; + rv->_maxwds = 32; + + return rv; +} + + +void +_DEFUN (Bfree, (ptr, v), struct _Jv_reent *ptr _AND _Jv_Bigint * v) +{ + long i; + + i = v - ptr->_freelist; + + JvAssert (i >= 0 && i < MAX_BIGNUMS); + + if (i >= 0 && i < MAX_BIGNUMS) + ptr->_allocation_map &= ~ (1 << i); +} + + +_Jv_Bigint * +_DEFUN (multadd, (ptr, b, m, a), + struct _Jv_reent *ptr _AND + _Jv_Bigint * b _AND + int m _AND + int a) +{ + int i, wds; + unsigned long *x, y; +#ifdef Pack_32 + unsigned long xi, z; +#endif + _Jv_Bigint *b1; + + wds = b->_wds; + x = b->_x; + i = 0; + do + { +#ifdef Pack_32 + xi = *x; + y = (xi & 0xffff) * m + a; + z = (xi >> 16) * m + (y >> 16); + a = (int) (z >> 16); + *x++ = (z << 16) + (y & 0xffff); +#else + y = *x * m + a; + a = (int) (y >> 16); + *x++ = y & 0xffff; +#endif + } + while (++i < wds); + if (a) + { + if (wds >= b->_maxwds) + { + b1 = Balloc (ptr, b->_k + 1); + Bcopy (b1, b); + Bfree (ptr, b); + b = b1; + } + b->_x[wds++] = a; + b->_wds = wds; + } + return b; +} + +_Jv_Bigint * +_DEFUN (s2b, (ptr, s, nd0, nd, y9), + struct _Jv_reent * ptr _AND + _CONST char *s _AND + int nd0 _AND + int nd _AND + unsigned long y9) +{ + _Jv_Bigint *b; + int i, k; + long x, y; + + x = (nd + 8) / 9; + for (k = 0, y = 1; x > y; y <<= 1, k++); +#ifdef Pack_32 + b = Balloc (ptr, k); + b->_x[0] = y9; + b->_wds = 1; +#else + b = Balloc (ptr, k + 1); + b->_x[0] = y9 & 0xffff; + b->_wds = (b->_x[1] = y9 >> 16) ? 2 : 1; +#endif + + i = 9; + if (9 < nd0) + { + s += 9; + do + b = multadd (ptr, b, 10, *s++ - '0'); + while (++i < nd0); + s++; + } + else + s += 10; + for (; i < nd; i++) + b = multadd (ptr, b, 10, *s++ - '0'); + return b; +} + +int +_DEFUN (hi0bits, + (x), register unsigned long x) +{ + register int k = 0; + + if (!(x & 0xffff0000)) + { + k = 16; + x <<= 16; + } + if (!(x & 0xff000000)) + { + k += 8; + x <<= 8; + } + if (!(x & 0xf0000000)) + { + k += 4; + x <<= 4; + } + if (!(x & 0xc0000000)) + { + k += 2; + x <<= 2; + } + if (!(x & 0x80000000)) + { + k++; + if (!(x & 0x40000000)) + return 32; + } + return k; +} + +int +_DEFUN (lo0bits, (y), unsigned long *y) +{ + register int k; + register unsigned long x = *y; + + if (x & 7) + { + if (x & 1) + return 0; + if (x & 2) + { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + k = 0; + if (!(x & 0xffff)) + { + k = 16; + x >>= 16; + } + if (!(x & 0xff)) + { + k += 8; + x >>= 8; + } + if (!(x & 0xf)) + { + k += 4; + x >>= 4; + } + if (!(x & 0x3)) + { + k += 2; + x >>= 2; + } + if (!(x & 1)) + { + k++; + x >>= 1; + if (!(x & 1)) + return 32; + } + *y = x; + return k; +} + +_Jv_Bigint * +_DEFUN (i2b, (ptr, i), struct _Jv_reent * ptr _AND int i) +{ + _Jv_Bigint *b; + + b = Balloc (ptr, 1); + b->_x[0] = i; + b->_wds = 1; + return b; +} + +_Jv_Bigint * +_DEFUN (mult, (ptr, a, b), struct _Jv_reent * ptr _AND _Jv_Bigint * a _AND _Jv_Bigint * b) +{ + _Jv_Bigint *c; + int k, wa, wb, wc; + unsigned long carry, y, z; + unsigned long *x, *xa, *xae, *xb, *xbe, *xc, *xc0; +#ifdef Pack_32 + unsigned long z2; +#endif + + if (a->_wds < b->_wds) + { + c = a; + a = b; + b = c; + } + k = a->_k; + wa = a->_wds; + wb = b->_wds; + wc = wa + wb; + if (wc > a->_maxwds) + k++; + c = Balloc (ptr, k); + for (x = c->_x, xa = x + wc; x < xa; x++) + *x = 0; + xa = a->_x; + xae = xa + wa; + xb = b->_x; + xbe = xb + wb; + xc0 = c->_x; +#ifdef Pack_32 + for (; xb < xbe; xb++, xc0++) + { + if ((y = *xb & 0xffff)) + { + x = xa; + xc = xc0; + carry = 0; + do + { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc (xc, z2, z); + } + while (x < xae); + *xc = carry; + } + if ((y = *xb >> 16)) + { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do + { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc (xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } + while (x < xae); + *xc = z2; + } + } +#else + for (; xb < xbe; xc0++) + { + if ((y = *xb++)) + { + x = xa; + xc = xc0; + carry = 0; + do + { + z = *x++ * y + *xc + carry; + carry = z >> 16; + *xc++ = z & 0xffff; + } + while (x < xae); + *xc = carry; + } + } +#endif + for (xc0 = c->_x, xc = xc0 + wc; wc > 0 && !*--xc; --wc); + c->_wds = wc; + return c; +} + +_Jv_Bigint * +_DEFUN (pow5mult, + (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int k) +{ + _Jv_Bigint *b1, *p5, *p51; + int i; + static _CONST int p05[3] = {5, 25, 125}; + + if ((i = k & 3)) + b = multadd (ptr, b, p05[i - 1], 0); + + if (!(k >>= 2)) + return b; + if (!(p5 = ptr->_p5s)) + { + /* first time */ + p5 = ptr->_p5s = i2b (ptr, 625); + p5->_next = 0; + } + for (;;) + { + if (k & 1) + { + b1 = mult (ptr, b, p5); + Bfree (ptr, b); + b = b1; + } + if (!(k >>= 1)) + break; + if (!(p51 = p5->_next)) + { + p51 = p5->_next = mult (ptr, p5, p5); + p51->_next = 0; + } + p5 = p51; + } + return b; +} + +_Jv_Bigint * +_DEFUN (lshift, (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int k) +{ + int i, k1, n, n1; + _Jv_Bigint *b1; + unsigned long *x, *x1, *xe, z; + +#ifdef Pack_32 + n = k >> 5; +#else + n = k >> 4; +#endif + k1 = b->_k; + n1 = n + b->_wds + 1; + for (i = b->_maxwds; n1 > i; i <<= 1) + k1++; + b1 = Balloc (ptr, k1); + x1 = b1->_x; + for (i = 0; i < n; i++) + *x1++ = 0; + x = b->_x; + xe = x + b->_wds; +#ifdef Pack_32 + if (k &= 0x1f) + { + k1 = 32 - k; + z = 0; + do + { + *x1++ = *x << k | z; + z = *x++ >> k1; + } + while (x < xe); + if ((*x1 = z)) + ++n1; + } +#else + if (k &= 0xf) + { + k1 = 16 - k; + z = 0; + do + { + *x1++ = (*x << k & 0xffff) | z; + z = *x++ >> k1; + } + while (x < xe); + if ((*x1 = z)) + ++n1; + } +#endif + else + do + *x1++ = *x++; + while (x < xe); + b1->_wds = n1 - 1; + Bfree (ptr, b); + return b1; +} + +int +_DEFUN (cmp, (a, b), _Jv_Bigint * a _AND _Jv_Bigint * b) +{ + unsigned long *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->_wds; + j = b->_wds; +#ifdef DEBUG + if (i > 1 && !a->_x[i - 1]) + Bug ("cmp called with a->_x[a->_wds-1] == 0"); + if (j > 1 && !b->_x[j - 1]) + Bug ("cmp called with b->_x[b->_wds-1] == 0"); +#endif + if (i -= j) + return i; + xa0 = a->_x; + xa = xa0 + j; + xb0 = b->_x; + xb = xb0 + j; + for (;;) + { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; +} + +_Jv_Bigint * +_DEFUN (diff, (ptr, a, b), struct _Jv_reent * ptr _AND + _Jv_Bigint * a _AND _Jv_Bigint * b) +{ + _Jv_Bigint *c; + int i, wa, wb; + long borrow, y; /* We need signed shifts here. */ + unsigned long *xa, *xae, *xb, *xbe, *xc; +#ifdef Pack_32 + long z; +#endif + + i = cmp (a, b); + if (!i) + { + c = Balloc (ptr, 0); + c->_wds = 1; + c->_x[0] = 0; + return c; + } + if (i < 0) + { + c = a; + a = b; + b = c; + i = 1; + } + else + i = 0; + c = Balloc (ptr, a->_k); + c->_sign = i; + wa = a->_wds; + xa = a->_x; + xae = xa + wa; + wb = b->_wds; + xb = b->_x; + xbe = xb + wb; + xc = c->_x; + borrow = 0; +#ifdef Pack_32 + do + { + y = (*xa & 0xffff) - (*xb & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend (borrow, y); + z = (*xa++ >> 16) - (*xb++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend (borrow, z); + Storeinc (xc, z, y); + } + while (xb < xbe); + while (xa < xae) + { + y = (*xa & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend (borrow, y); + z = (*xa++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend (borrow, z); + Storeinc (xc, z, y); + } +#else + do + { + y = *xa++ - *xb++ + borrow; + borrow = y >> 16; + Sign_Extend (borrow, y); + *xc++ = y & 0xffff; + } + while (xb < xbe); + while (xa < xae) + { + y = *xa++ + borrow; + borrow = y >> 16; + Sign_Extend (borrow, y); + *xc++ = y & 0xffff; + } +#endif + while (!*--xc) + wa--; + c->_wds = wa; + return c; +} + +double +_DEFUN (ulp, (_x), double _x) +{ + union double_union x, a; + register long L; + + x.d = _x; + + L = (word0 (x) & Exp_mask) - (P - 1) * Exp_msk1; +#ifndef Sudden_Underflow + if (L > 0) + { +#endif +#ifdef IBM + L |= Exp_msk1 >> 4; +#endif + word0 (a) = L; +#ifndef _DOUBLE_IS_32BITS + word1 (a) = 0; +#endif + +#ifndef Sudden_Underflow + } + else + { + L = -L >> Exp_shift; + if (L < Exp_shift) + { + word0 (a) = 0x80000 >> L; +#ifndef _DOUBLE_IS_32BITS + word1 (a) = 0; +#endif + } + else + { + word0 (a) = 0; + L -= Exp_shift; +#ifndef _DOUBLE_IS_32BITS + word1 (a) = L >= 31 ? 1 : 1 << (31 - L); +#endif + } + } +#endif + return a.d; +} + +double +_DEFUN (b2d, (a, e), + _Jv_Bigint * a _AND int *e) +{ + unsigned long *xa, *xa0, w, y, z; + int k; + union double_union d; +#ifdef VAX + unsigned long d0, d1; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + + xa0 = a->_x; + xa = xa0 + a->_wds; + y = *--xa; +#ifdef DEBUG + if (!y) + Bug ("zero y in b2d"); +#endif + k = hi0bits (y); + *e = 32 - k; +#ifdef Pack_32 + if (k < Ebits) + { + d0 = Exp_1 | y >> (Ebits - k); + w = xa > xa0 ? *--xa : 0; +#ifndef _DOUBLE_IS_32BITS + d1 = y << (32 - Ebits + k) | w >> (Ebits - k); +#endif + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + if (k -= Ebits) + { + d0 = Exp_1 | y << k | z >> (32 - k); + y = xa > xa0 ? *--xa : 0; +#ifndef _DOUBLE_IS_32BITS + d1 = z << k | y >> (32 - k); +#endif + } + else + { + d0 = Exp_1 | y; +#ifndef _DOUBLE_IS_32BITS + d1 = z; +#endif + } +#else + if (k < Ebits + 16) + { + z = xa > xa0 ? *--xa : 0; + d0 = Exp_1 | y << (k - Ebits) | z >> (Ebits + 16 - k); + w = xa > xa0 ? *--xa : 0; + y = xa > xa0 ? *--xa : 0; + d1 = z << (k + 16 - Ebits) | w << (k - Ebits) | y >> (16 + Ebits - k); + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + w = xa > xa0 ? *--xa : 0; + k -= Ebits + 16; + d0 = Exp_1 | y << (k + 16) | z << k | w >> (16 - k); + y = xa > xa0 ? *--xa : 0; + d1 = w << (k + 16) | y << k; +#endif +ret_d: +#ifdef VAX + word0 (d) = d0 >> 16 | d0 << 16; + word1 (d) = d1 >> 16 | d1 << 16; +#else +#undef d0 +#undef d1 +#endif + return d.d; +} + +_Jv_Bigint * +_DEFUN (d2b, + (ptr, _d, e, bits), + struct _Jv_reent * ptr _AND + double _d _AND + int *e _AND + int *bits) + +{ + union double_union d; + _Jv_Bigint *b; + int de, i, k; + unsigned long *x, y, z; +#ifdef VAX + unsigned long d0, d1; + d.d = _d; + d0 = word0 (d) >> 16 | word0 (d) << 16; + d1 = word1 (d) >> 16 | word1 (d) << 16; +#else +#define d0 word0(d) +#define d1 word1(d) + d.d = _d; +#endif + +#ifdef Pack_32 + b = Balloc (ptr, 1); +#else + b = Balloc (ptr, 2); +#endif + x = b->_x; + + z = d0 & Frac_mask; + d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ +#ifdef Sudden_Underflow + de = (int) (d0 >> Exp_shift); +#ifndef IBM + z |= Exp_msk11; +#endif +#else + if ((de = (int) (d0 >> Exp_shift))) + z |= Exp_msk1; +#endif +#ifdef Pack_32 +#ifndef _DOUBLE_IS_32BITS + if ((y = d1)) + { + if ((k = lo0bits (&y))) + { + x[0] = y | z << (32 - k); + z >>= k; + } + else + x[0] = y; + i = b->_wds = (x[1] = z) ? 2 : 1; + } + else +#endif + { +#ifdef DEBUG + if (!z) + Bug ("Zero passed to d2b"); +#endif + k = lo0bits (&z); + x[0] = z; + i = b->_wds = 1; +#ifndef _DOUBLE_IS_32BITS + k += 32; +#endif + } +#else + if ((y = d1)) + { + if ((k = lo0bits (&y))) + if (k >= 16) + { + x[0] = y | (z << (32 - k) & 0xffff); + x[1] = z >> (k - 16) & 0xffff; + x[2] = z >> k; + i = 2; + } + else + { + x[0] = y & 0xffff; + x[1] = (y >> 16 | z << (16 - k)) & 0xffff; + x[2] = z >> k & 0xffff; + x[3] = z >> (k + 16); + i = 3; + } + else + { + x[0] = y & 0xffff; + x[1] = y >> 16; + x[2] = z & 0xffff; + x[3] = z >> 16; + i = 3; + } + } + else + { +#ifdef DEBUG + if (!z) + Bug ("Zero passed to d2b"); +#endif + k = lo0bits (&z); + if (k >= 16) + { + x[0] = z; + i = 0; + } + else + { + x[0] = z & 0xffff; + x[1] = z >> 16; + i = 1; + } + k += 32; + } + while (!x[i]) + --i; + b->_wds = i + 1; +#endif +#ifndef Sudden_Underflow + if (de) + { +#endif +#ifdef IBM + *e = (de - Bias - (P - 1) << 2) + k; + *bits = 4 * P + 8 - k - hi0bits (word0 (d) & Frac_mask); +#else + *e = de - Bias - (P - 1) + k; + *bits = P - k; +#endif +#ifndef Sudden_Underflow + } + else + { + *e = de - Bias - (P - 1) + 1 + k; +#ifdef Pack_32 + *bits = 32 * i - hi0bits (x[i - 1]); +#else + *bits = (i + 2) * 16 - hi0bits (x[i]); +#endif + } +#endif + return b; +} +#undef d0 +#undef d1 + +double +_DEFUN (ratio, (a, b), _Jv_Bigint * a _AND _Jv_Bigint * b) + +{ + union double_union da, db; + int k, ka, kb; + + da.d = b2d (a, &ka); + db.d = b2d (b, &kb); +#ifdef Pack_32 + k = ka - kb + 32 * (a->_wds - b->_wds); +#else + k = ka - kb + 16 * (a->_wds - b->_wds); +#endif +#ifdef IBM + if (k > 0) + { + word0 (da) += (k >> 2) * Exp_msk1; + if (k &= 3) + da.d *= 1 << k; + } + else + { + k = -k; + word0 (db) += (k >> 2) * Exp_msk1; + if (k &= 3) + db.d *= 1 << k; + } +#else + if (k > 0) + word0 (da) += k * Exp_msk1; + else + { + k = -k; + word0 (db) += k * Exp_msk1; + } +#endif + return da.d / db.d; +} + + +_CONST double + tens[] = +{ + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22, 1e23, 1e24 + +}; + +#if !defined(_DOUBLE_IS_32BITS) && !defined(__v800) +_CONST double bigtens[] = +{1e16, 1e32, 1e64, 1e128, 1e256}; + +_CONST double tinytens[] = +{1e-16, 1e-32, 1e-64, 1e-128, 1e-256}; +#else +_CONST double bigtens[] = +{1e16, 1e32}; + +_CONST double tinytens[] = +{1e-16, 1e-32}; +#endif + + diff --git a/libjava/classpath/native/fdlibm/mprec.h b/libjava/classpath/native/fdlibm/mprec.h new file mode 100644 index 00000000000..d796b81de82 --- /dev/null +++ b/libjava/classpath/native/fdlibm/mprec.h @@ -0,0 +1,402 @@ +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991, 2000 by AT&T. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +#ifndef __CLASSPATH_MPREC_H__ +#define __CLASSPATH_MPREC_H__ + +#include <config.h> +#include "ieeefp.h" + +#if defined HAVE_STDINT_H +#include <stdint.h> +#elif defined HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#if defined HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#if defined HAVE_SYS_CONFIG_H +#include <sys/config.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* ISO C99 int type declarations */ + +#if !defined HAVE_INT32_DEFINED && defined HAVE_BSD_INT32_DEFINED +typedef u_int32_t uint32_t; +#endif + +#if !defined HAVE_BSD_INT32_DEFINED && !defined HAVE_INT32_DEFINED +/* FIXME this could have problems with systems that don't define SI to be 4 */ +typedef int int32_t __attribute__((mode(SI))); + +/* This is a blatant hack: on Solaris 2.5, pthread.h defines uint32_t + in pthread.h, which we sometimes include. We protect our + definition the same way Solaris 2.5 does, to avoid redefining it. */ +# ifndef _UINT32_T +typedef unsigned int uint32_t __attribute__((mode(SI))); +# endif +#endif + + /* These typedefs are true for the targets running Java. */ + +#ifdef __IEEE_LITTLE_ENDIAN +#define IEEE_8087 +#endif + +#ifdef __IEEE_BIG_ENDIAN +#define IEEE_MC68k +#endif + +#ifdef __Z8000__ +#define Just_16 +#endif + +#ifdef DEBUG +#include "stdio.h" +#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} +#endif + + +#ifdef Unsigned_Shifts +#define Sign_Extend(a,b) if (b < 0) a |= (uint32_t)0xffff0000; +#else +#define Sign_Extend(a,b) /*no-op*/ +#endif + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#endif + +/* If we are going to examine or modify specific bits in a double using + the word0 and/or word1 macros, then we must wrap the double inside + a union. This is necessary to avoid undefined behavior according to + the ANSI C spec. */ +union double_union +{ + double d; + uint32_t i[2]; +}; + +#ifdef IEEE_8087 +#define word0(x) (x.i[1]) +#define word1(x) (x.i[0]) +#else +#define word0(x) (x.i[0]) +#define word1(x) (x.i[1]) +#endif + +/* The following definition of Storeinc is appropriate for MIPS processors. + * An alternative that might be better on some machines is + * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) + */ +#if defined(IEEE_8087) + defined(VAX) +#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ +((unsigned short *)a)[0] = (unsigned short)c, a++) +#else +#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ +((unsigned short *)a)[1] = (unsigned short)c, a++) +#endif + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#if defined(IEEE_8087) + defined(IEEE_MC68k) +#if defined (_DOUBLE_IS_32BITS) +#define Exp_shift 23 +#define Exp_shift1 23 +#define Exp_msk1 ((uint32_t)0x00800000L) +#define Exp_msk11 ((uint32_t)0x00800000L) +#define Exp_mask ((uint32_t)0x7f800000L) +#define P 24 +#define Bias 127 +#if 0 +#define IEEE_Arith /* it is, but the code doesn't handle IEEE singles yet */ +#endif +#define Emin (-126) +#define Exp_1 ((uint32_t)0x3f800000L) +#define Exp_11 ((uint32_t)0x3f800000L) +#define Ebits 8 +#define Frac_mask ((uint32_t)0x007fffffL) +#define Frac_mask1 ((uint32_t)0x007fffffL) +#define Ten_pmax 10 +#define Sign_bit ((uint32_t)0x80000000L) +#define Ten_pmax 10 +#define Bletch 2 +#define Bndry_mask ((uint32_t)0x007fffffL) +#define Bndry_mask1 ((uint32_t)0x007fffffL) +#define LSB 1 +#define Sign_bit ((uint32_t)0x80000000L) +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 5 +#define Int_max 6 +#define Infinite(x) (word0(x) == ((uint32_t)0x7f800000L)) +#undef word0 +#undef word1 + +#define word0(x) (x.i[0]) +#define word1(x) 0 +#else + +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 ((uint32_t)0x100000L) +#define Exp_msk11 ((uint32_t)0x100000L) +#define Exp_mask ((uint32_t)0x7ff00000L) +#define P 53 +#define Bias 1023 +#define IEEE_Arith +#define Emin (-1022) +#define Exp_1 ((uint32_t)0x3ff00000L) +#define Exp_11 ((uint32_t)0x3ff00000L) +#define Ebits 11 +#define Frac_mask ((uint32_t)0xfffffL) +#define Frac_mask1 ((uint32_t)0xfffffL) +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask ((uint32_t)0xfffffL) +#define Bndry_mask1 ((uint32_t)0xfffffL) +#define LSB 1 +#define Sign_bit ((uint32_t)0x80000000L) +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#define Infinite(x) (word0(x) == ((uint32_t)0x7ff00000L)) /* sufficient test for here */ +#endif + +#else +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 ((uint32_t)0x1000000L) +#define Exp_msk11 ((uint32_t)0x1000000L) +#define Exp_mask ((uint32_t)0x7f000000L) +#define P 14 +#define Bias 65 +#define Exp_1 ((uint32_t)0x41000000L) +#define Exp_11 ((uint32_t)0x41000000L) +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask ((uint32_t)0xffffffL) +#define Frac_mask1 ((uint32_t)0xffffffL) +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask ((uint32_t)0xefffffL) +#define Bndry_mask1 ((uint32_t)0xffffffL) +#define LSB 1 +#define Sign_bit ((uint32_t)0x80000000L) +#define Log2P 4 +#define Tiny0 ((uint32_t)0x100000L) +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 ((uint32_t)0x800000L) +#define Exp_mask ((uint32_t)0x7f80L) +#define P 56 +#define Bias 129 +#define Exp_1 ((uint32_t)0x40800000L) +#define Exp_11 ((uint32_t)0x4080L) +#define Ebits 8 +#define Frac_mask ((uint32_t)0x7fffffL) +#define Frac_mask1 ((uint32_t)0xffff007fL) +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask ((uint32_t)0xffff007fL) +#define Bndry_mask1 ((uint32_t)0xffff007fL) +#define LSB ((uint32_t)0x10000L) +#define Sign_bit ((uint32_t)0x8000L) +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif +#endif + +#ifndef IEEE_Arith +#define ROUND_BIASED +#endif + +#ifdef RND_PRODQUOT +#define rounded_product(a,b) a = rnd_prod(a, b) +#define rounded_quotient(a,b) a = rnd_quot(a, b) +#ifdef KR_headers +extern double rnd_prod(), rnd_quot(); +#else +extern double rnd_prod(double, double), rnd_quot(double, double); +#endif +#else +#define rounded_product(a,b) a *= b +#define rounded_quotient(a,b) a /= b +#endif + +#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) +#define Big1 ((uint32_t)0xffffffffL) + +#ifndef Just_16 +/* When Pack_32 is not defined, we store 16 bits per 32-bit long. + * This makes some inner loops simpler and sometimes saves work + * during multiplications, but it often seems to make things slightly + * slower. Hence the default is now to store 32 bits per long. + */ + +#ifndef Pack_32 +#if SIZEOF_VOID_P != 8 +#define Pack_32 +#endif +#endif +#endif + + +#define MAX_BIGNUMS 16 +#define MAX_BIGNUM_WDS 32 + +struct _Jv_Bigint +{ + struct _Jv_Bigint *_next; + int _k, _maxwds, _sign, _wds; + unsigned long _x[MAX_BIGNUM_WDS]; +}; + + +#define _PTR void * +#define _AND , +#define _NOARGS void +#define _CONST const +#define _VOLATILE volatile +#define _SIGNED signed +#define _DOTS , ... +#define _VOID void +#define _EXFUN(name, proto) name proto +#define _DEFUN(name, arglist, args) name(args) +#define _DEFUN_VOID(name) name(_NOARGS) +#define _CAST_VOID (void) + + +struct _Jv_reent +{ + /* local copy of errno */ + int _errno; + + /* used by mprec routines */ + struct _Jv_Bigint *_result; + int _result_k; + struct _Jv_Bigint *_p5s; + + struct _Jv_Bigint _freelist[MAX_BIGNUMS]; + int _allocation_map; + + int num; +}; + + +typedef struct _Jv_Bigint _Jv_Bigint; + +#define Balloc _Jv_Balloc +#define Bfree _Jv_Bfree +#define multadd _Jv_multadd +#define s2b _Jv_s2b +#define lo0bits _Jv_lo0bits +#define hi0bits _Jv_hi0bits +#define i2b _Jv_i2b +#define mult _Jv_mult +#define pow5mult _Jv_pow5mult +#define lshift _Jv_lshift +#define cmp _Jv__mcmp +#define diff _Jv__mdiff +#define ulp _Jv_ulp +#define b2d _Jv_b2d +#define d2b _Jv_d2b +#define ratio _Jv_ratio + +#define tens _Jv__mprec_tens +#define bigtens _Jv__mprec_bigtens +#define tinytens _Jv__mprec_tinytens + +#define _dtoa _Jv_dtoa +#define _dtoa_r _Jv_dtoa_r +#define _strtod_r _Jv_strtod_r + +extern double _EXFUN(_strtod_r, (struct _Jv_reent *ptr, const char *s00, char **se)); +extern char* _EXFUN(_dtoa_r, (struct _Jv_reent *ptr, double d, + int mode, int ndigits, int *decpt, int *sign, + char **rve, int float_type)); +void _EXFUN(_dtoa, (double d, int mode, int ndigits, int *decpt, int *sign, + char **rve, char *buf, int float_type)); + +double _EXFUN(ulp,(double x)); +double _EXFUN(b2d,(_Jv_Bigint *a , int *e)); +_Jv_Bigint * _EXFUN(Balloc,(struct _Jv_reent *p, int k)); +void _EXFUN(Bfree,(struct _Jv_reent *p, _Jv_Bigint *v)); +_Jv_Bigint * _EXFUN(multadd,(struct _Jv_reent *p, _Jv_Bigint *, int, int)); +_Jv_Bigint * _EXFUN(s2b,(struct _Jv_reent *, const char*, int, int, unsigned long)); +_Jv_Bigint * _EXFUN(i2b,(struct _Jv_reent *,int)); +_Jv_Bigint * _EXFUN(mult, (struct _Jv_reent *, _Jv_Bigint *, _Jv_Bigint *)); +_Jv_Bigint * _EXFUN(pow5mult, (struct _Jv_reent *, _Jv_Bigint *, int k)); +int _EXFUN(hi0bits,(unsigned long)); +int _EXFUN(lo0bits,(unsigned long *)); +_Jv_Bigint * _EXFUN(d2b,(struct _Jv_reent *p, double d, int *e, int *bits)); +_Jv_Bigint * _EXFUN(lshift,(struct _Jv_reent *p, _Jv_Bigint *b, int k)); +_Jv_Bigint * _EXFUN(diff,(struct _Jv_reent *p, _Jv_Bigint *a, _Jv_Bigint *b)); +int _EXFUN(cmp,(_Jv_Bigint *a, _Jv_Bigint *b)); + +double _EXFUN(ratio,(_Jv_Bigint *a, _Jv_Bigint *b)); +#define Bcopy(x,y) memcpy((char *)&x->_sign, (char *)&y->_sign, y->_wds*sizeof(long) + 2*sizeof(int)) + +#if defined(_DOUBLE_IS_32BITS) && defined(__v800) +#define n_bigtens 2 +#else +#define n_bigtens 5 +#endif + +extern _CONST double tinytens[]; +extern _CONST double bigtens[]; +extern _CONST double tens[]; + +#ifdef __cplusplus +} +#endif + +#endif /* __CLASSPATH_MPREC_H__ */ diff --git a/libjava/classpath/native/fdlibm/s_atan.c b/libjava/classpath/native/fdlibm/s_atan.c new file mode 100644 index 00000000000..2ee74585423 --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_atan.c @@ -0,0 +1,181 @@ + +/* @(#)s_atan.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +/* +FUNCTION + <<atan>>, <<atanf>>---arc tangent + +INDEX + atan +INDEX + atanf + +ANSI_SYNOPSIS + #include <math.h> + double atan(double <[x]>); + float atanf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double atan(<[x]>); + double <[x]>; + + float atanf(<[x]>); + float <[x]>; + +DESCRIPTION + +<<atan>> computes the inverse tangent (arc tangent) of the input value. + +<<atanf>> is identical to <<atan>>, save that it operates on <<floats>>. + +RETURNS +@ifinfo +<<atan>> returns a value in radians, in the range of -pi/2 to pi/2. +@end ifinfo +@tex +<<atan>> returns a value in radians, in the range of $-\pi/2$ to $\pi/2$. +@end tex + +PORTABILITY +<<atan>> is ANSI C. <<atanf>> is an extension. + +*/ + +/* atan(x) + * Method + * 1. Reduce x to positive by atan(x) = -atan(-x). + * 2. According to the integer k=4t+0.25 chopped, t=x, the argument + * is further reduced to one of the following intervals and the + * arctangent of t is evaluated by the corresponding formula: + * + * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) + * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) + * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) + * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) + * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double atanhi[] = { +#else +static double atanhi[] = { +#endif + 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ + 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ + 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ + 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ +}; + +#ifdef __STDC__ +static const double atanlo[] = { +#else +static double atanlo[] = { +#endif + 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ + 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ + 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ + 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ +}; + +#ifdef __STDC__ +static const double aT[] = { +#else +static double aT[] = { +#endif + 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ + -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ + 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ + -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ + 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ + -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ + 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ + -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ + 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ + -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ + 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ +}; + +#ifdef __STDC__ + static const double +#else + static double +#endif +one = 1.0, +huge = 1.0e300; + +#ifdef __STDC__ + double atan(double x) +#else + double atan(x) + double x; +#endif +{ + double w,s1,s2,z; + int32_t ix,hx,id; + + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x44100000) { /* if |x| >= 2^66 */ + uint32_t low; + GET_LOW_WORD(low,x); + if(ix>0x7ff00000|| + (ix==0x7ff00000&&(low!=0))) + return x+x; /* NaN */ + if(hx>0) return atanhi[3]+atanlo[3]; + else return -atanhi[3]-atanlo[3]; + } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ + if (ix < 0x3e200000) { /* |x| < 2^-29 */ + if(huge+x>one) return x; /* raise inexact */ + } + id = -1; + } else { + x = fabs(x); + if (ix < 0x3ff30000) { /* |x| < 1.1875 */ + if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ + id = 0; x = (2.0*x-one)/(2.0+x); + } else { /* 11/16<=|x|< 19/16 */ + id = 1; x = (x-one)/(x+one); + } + } else { + if (ix < 0x40038000) { /* |x| < 2.4375 */ + id = 2; x = (x-1.5)/(one+1.5*x); + } else { /* 2.4375 <= |x| < 2^66 */ + id = 3; x = -1.0/x; + } + }} + /* end of argument reduction */ + z = x*x; + w = z*z; + /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ + s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); + s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); + if (id<0) return x - x*(s1+s2); + else { + z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); + return (hx<0)? -z:z; + } +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/s_ceil.c b/libjava/classpath/native/fdlibm/s_ceil.c new file mode 100644 index 00000000000..250373b40d1 --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_ceil.c @@ -0,0 +1,80 @@ + +/* @(#)s_ceil.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * ceil(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to ceil(x). + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double huge = 1.0e300; +#else +static double huge = 1.0e300; +#endif + +#ifdef __STDC__ + double ceil(double x) +#else + double ceil(x) + double x; +#endif +{ + int32_t i0,i1,j0; + uint32_t i,j; + EXTRACT_WORDS(i0,i1,x); + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0<0) {i0=0x80000000;i1=0;} + else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} + } + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0>0) i0 += (0x00100000)>>j0; + i0 &= (~i); i1=0; + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((uint32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0>0) { + if(j0==20) i0+=1; + else { + j = i1 + (1<<(52-j0)); + if(j<(uint32_t)i1) i0+=1; /* got a carry */ + i1 = j; + } + } + i1 &= (~i); + } + } + INSERT_WORDS(x,i0,i1); + return x; +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/s_copysign.c b/libjava/classpath/native/fdlibm/s_copysign.c new file mode 100644 index 00000000000..4804df130dc --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_copysign.c @@ -0,0 +1,82 @@ + +/* @(#)s_copysign.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION +<<copysign>>, <<copysignf>>---sign of <[y]>, magnitude of <[x]> + +INDEX + copysign +INDEX + copysignf + +ANSI_SYNOPSIS + #include <math.h> + double copysign (double <[x]>, double <[y]>); + float copysignf (float <[x]>, float <[y]>); + +TRAD_SYNOPSIS + #include <math.h> + double copysign (<[x]>, <[y]>) + double <[x]>; + double <[y]>; + + float copysignf (<[x]>, <[y]>) + float <[x]>; + float <[y]>; + +DESCRIPTION +<<copysign>> constructs a number with the magnitude (absolute value) +of its first argument, <[x]>, and the sign of its second argument, +<[y]>. + +<<copysignf>> does the same thing; the two functions differ only in +the type of their arguments and result. + +RETURNS +<<copysign>> returns a <<double>> with the magnitude of +<[x]> and the sign of <[y]>. +<<copysignf>> returns a <<float>> with the magnitude of +<[x]> and the sign of <[y]>. + +PORTABILITY +<<copysign>> is not required by either ANSI C or the System V Interface +Definition (Issue 2). + +*/ + +/* + * copysign(double x, double y) + * copysign(x,y) returns a value with the magnitude of x and + * with the sign bit of y. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double copysign(double x, double y) +#else + double copysign(x,y) + double x,y; +#endif +{ + uint32_t hx,hy; + GET_HIGH_WORD(hx,x); + GET_HIGH_WORD(hy,y); + SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000)); + return x; +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/s_cos.c b/libjava/classpath/native/fdlibm/s_cos.c new file mode 100644 index 00000000000..be1538d4c0b --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_cos.c @@ -0,0 +1,82 @@ + +/* @(#)s_cos.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* cos(x) + * Return cosine function of x. + * + * kernel function: + * __kernel_sin ... sine function on [-pi/4,pi/4] + * __kernel_cos ... cosine function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double cos(double x) +#else + double cos(x) + double x; +#endif +{ + double y[2],z=0.0; + int32_t n,ix; + + /* High word of x. */ + GET_HIGH_WORD(ix,x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if(ix <= 0x3fe921fb) return __kernel_cos(x,z); + + /* cos(Inf or NaN) is NaN */ + else if (ix>=0x7ff00000) return x-x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x,y); + switch(n&3) { + case 0: return __kernel_cos(y[0],y[1]); + case 1: return -__kernel_sin(y[0],y[1],1); + case 2: return -__kernel_cos(y[0],y[1]); + default: + return __kernel_sin(y[0],y[1],1); + } + } +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/s_fabs.c b/libjava/classpath/native/fdlibm/s_fabs.c new file mode 100644 index 00000000000..dfee33fecdb --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_fabs.c @@ -0,0 +1,73 @@ + +/* @(#)s_fabs.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION + <<fabs>>, <<fabsf>>---absolute value (magnitude) +INDEX + fabs +INDEX + fabsf + +ANSI_SYNOPSIS + #include <math.h> + double fabs(double <[x]>); + float fabsf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double fabs(<[x]>) + double <[x]>; + + float fabsf(<[x]>) + float <[x]>; + +DESCRIPTION +<<fabs>> and <<fabsf>> calculate +@tex +$|x|$, +@end tex +the absolute value (magnitude) of the argument <[x]>, by direct +manipulation of the bit representation of <[x]>. + +RETURNS +The calculated value is returned. No errors are detected. + +PORTABILITY +<<fabs>> is ANSI. +<<fabsf>> is an extension. + +*/ + +/* + * fabs(x) returns the absolute value of x. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double fabs(double x) +#else + double fabs(x) + double x; +#endif +{ + uint32_t high; + GET_HIGH_WORD(high,x); + SET_HIGH_WORD(x,high&0x7fffffff); + return x; +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/s_finite.c b/libjava/classpath/native/fdlibm/s_finite.c new file mode 100644 index 00000000000..3e6c8122b25 --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_finite.c @@ -0,0 +1,31 @@ + +/* @(#)s_finite.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * finite(x) returns 1 is x is finite, else 0; + * no branching! + */ + +#include "fdlibm.h" + +#ifdef __STDC__ + int finite(double x) +#else + int finite(x) + double x; +#endif +{ + uint32_t high; + GET_HIGH_WORD(high,x); + return (unsigned)((high&0x7fffffff)-0x7ff00000)>>31; +} diff --git a/libjava/classpath/native/fdlibm/s_floor.c b/libjava/classpath/native/fdlibm/s_floor.c new file mode 100644 index 00000000000..77e39cb7de0 --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_floor.c @@ -0,0 +1,134 @@ + +/* @(#)s_floor.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION +<<floor>>, <<floorf>>, <<ceil>>, <<ceilf>>---floor and ceiling +INDEX + floor +INDEX + floorf +INDEX + ceil +INDEX + ceilf + +ANSI_SYNOPSIS + #include <math.h> + double floor(double <[x]>); + float floorf(float <[x]>); + double ceil(double <[x]>); + float ceilf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double floor(<[x]>) + double <[x]>; + float floorf(<[x]>) + float <[x]>; + double ceil(<[x]>) + double <[x]>; + float ceilf(<[x]>) + float <[x]>; + +DESCRIPTION +<<floor>> and <<floorf>> find +@tex +$\lfloor x \rfloor$, +@end tex +the nearest integer less than or equal to <[x]>. +<<ceil>> and <<ceilf>> find +@tex +$\lceil x\rceil$, +@end tex +the nearest integer greater than or equal to <[x]>. + +RETURNS +<<floor>> and <<ceil>> return the integer result as a double. +<<floorf>> and <<ceilf>> return the integer result as a float. + +PORTABILITY +<<floor>> and <<ceil>> are ANSI. +<<floorf>> and <<ceilf>> are extensions. + + +*/ + +/* + * floor(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to floor(x). + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double huge = 1.0e300; +#else +static double huge = 1.0e300; +#endif + +#ifdef __STDC__ + double floor(double x) +#else + double floor(x) + double x; +#endif +{ + int32_t i0,i1,j0; + uint32_t i,j; + EXTRACT_WORDS(i0,i1,x); + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0>=0) {i0=i1=0;} + else if(((i0&0x7fffffff)|i1)!=0) + { i0=0xbff00000;i1=0;} + } + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0<0) i0 += (0x00100000)>>j0; + i0 &= (~i); i1=0; + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((uint32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0<0) { + if(j0==20) i0+=1; + else { + j = i1+(1<<(52-j0)); + if(j<(uint32_t)i1) i0 +=1 ; /* got a carry */ + i1=j; + } + } + i1 &= (~i); + } + } + INSERT_WORDS(x,i0,i1); + return x; +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/s_rint.c b/libjava/classpath/native/fdlibm/s_rint.c new file mode 100644 index 00000000000..5d3f8114e2b --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_rint.c @@ -0,0 +1,87 @@ + +/* @(#)s_rint.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * rint(x) + * Return x rounded to integral value according to the prevailing + * rounding mode. + * Method: + * Using floating addition. + * Exception: + * Inexact flag raised if x not equal to rint(x). + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +#ifdef __STDC__ + double rint(double x) +#else + double rint(x) + double x; +#endif +{ + int32_t i0,j0,sx; + uint32_t i,i1; + double t; + volatile double w; + EXTRACT_WORDS(i0,i1,x); + sx = (i0>>31)&1; + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { + if(((i0&0x7fffffff)|i1)==0) return x; + i1 |= (i0&0x0fffff); + i0 &= 0xfffe0000; + i0 |= ((i1|-i1)>>12)&0x80000; + SET_HIGH_WORD(x,i0); + w = TWO52[sx]+x; + t = w-TWO52[sx]; + GET_HIGH_WORD(i0,t); + SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + i>>=1; + if(((i0&i)|i1)!=0) { + if(j0==19) i1 = 0x40000000; else + i0 = (i0&(~i))|((0x20000)>>j0); + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((uint32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + i>>=1; + if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); + } + INSERT_WORDS(x,i0,i1); + w = TWO52[sx]+x; + return w-TWO52[sx]; +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/s_scalbn.c b/libjava/classpath/native/fdlibm/s_scalbn.c new file mode 100644 index 00000000000..36ee88981ba --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_scalbn.c @@ -0,0 +1,104 @@ + +/* @(#)s_scalbn.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION +<<scalbn>>, <<scalbnf>>---scale by integer +INDEX + scalbn +INDEX + scalbnf + +ANSI_SYNOPSIS + #include <math.h> + double scalbn(double <[x]>, int <[y]>); + float scalbnf(float <[x]>, int <[y]>); + +TRAD_SYNOPSIS + #include <math.h> + double scalbn(<[x]>,<[y]>) + double <[x]>; + int <[y]>; + float scalbnf(<[x]>,<[y]>) + float <[x]>; + int <[y]>; + +DESCRIPTION +<<scalbn>> and <<scalbnf>> scale <[x]> by <[n]>, returning <[x]> times +2 to the power <[n]>. The result is computed by manipulating the +exponent, rather than by actually performing an exponentiation or +multiplication. + +RETURNS +<[x]> times 2 to the power <[n]>. + +PORTABILITY +Neither <<scalbn>> nor <<scalbnf>> is required by ANSI C or by the System V +Interface Definition (Issue 2). + +*/ + +/* + * scalbn (double x, int n) + * scalbn(x,n) returns x* 2**n computed by exponent + * manipulation rather than by actually performing an + * exponentiation or a multiplication. + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +huge = 1.0e+300, +tiny = 1.0e-300; + +#ifdef __STDC__ + double scalbn (double x, int n) +#else + double scalbn (x,n) + double x; int n; +#endif +{ + int32_t k,hx,lx; + EXTRACT_WORDS(hx,lx,x); + k = (hx&0x7ff00000)>>20; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ + x *= two54; + GET_HIGH_WORD(hx,x); + k = ((hx&0x7ff00000)>>20) - 54; + if (n< -50000) return tiny*x; /*underflow*/ + } + if (k==0x7ff) return x+x; /* NaN or Inf */ + k = k+n; + if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */ + if (k > 0) /* normal result */ + {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;} + if (k <= -54) { + if (n > 50000) /* in case integer overflow in n+k */ + return huge*copysign(huge,x); /*overflow*/ + else return tiny*copysign(tiny,x); /*underflow*/ + } + k += 54; /* subnormal result */ + SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); + return x*twom54; +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/s_sin.c b/libjava/classpath/native/fdlibm/s_sin.c new file mode 100644 index 00000000000..d315455549c --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_sin.c @@ -0,0 +1,132 @@ + +/* @(#)s_sin.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION + <<sin>>, <<sinf>>, <<cos>>, <<cosf>>---sine or cosine +INDEX +sin +INDEX +sinf +INDEX +cos +INDEX +cosf +ANSI_SYNOPSIS + #include <math.h> + double sin(double <[x]>); + float sinf(float <[x]>); + double cos(double <[x]>); + float cosf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double sin(<[x]>) + double <[x]>; + float sinf(<[x]>) + float <[x]>; + + double cos(<[x]>) + double <[x]>; + float cosf(<[x]>) + float <[x]>; + +DESCRIPTION + <<sin>> and <<cos>> compute (respectively) the sine and cosine + of the argument <[x]>. Angles are specified in radians. + + <<sinf>> and <<cosf>> are identical, save that they take and + return <<float>> values. + + +RETURNS + The sine or cosine of <[x]> is returned. + +PORTABILITY + <<sin>> and <<cos>> are ANSI C. + <<sinf>> and <<cosf>> are extensions. + +QUICKREF + sin ansi pure + sinf - pure +*/ + +/* sin(x) + * Return sine function of x. + * + * kernel function: + * __kernel_sin ... sine function on [-pi/4,pi/4] + * __kernel_cos ... cose function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double sin(double x) +#else + double sin(x) + double x; +#endif +{ + double y[2],z=0.0; + int32_t n,ix; + + /* High word of x. */ + GET_HIGH_WORD(ix,x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0); + + /* sin(Inf or NaN) is NaN */ + else if (ix>=0x7ff00000) return x-x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x,y); + switch(n&3) { + case 0: return __kernel_sin(y[0],y[1],1); + case 1: return __kernel_cos(y[0],y[1]); + case 2: return -__kernel_sin(y[0],y[1],1); + default: + return -__kernel_cos(y[0],y[1]); + } + } +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/s_tan.c b/libjava/classpath/native/fdlibm/s_tan.c new file mode 100644 index 00000000000..20995fcbdee --- /dev/null +++ b/libjava/classpath/native/fdlibm/s_tan.c @@ -0,0 +1,114 @@ + +/* @(#)s_tan.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + + +/* + +FUNCTION + <<tan>>, <<tanf>>---tangent + +INDEX +tan +INDEX +tanf + +ANSI_SYNOPSIS + #include <math.h> + double tan(double <[x]>); + float tanf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double tan(<[x]>) + double <[x]>; + + float tanf(<[x]>) + float <[x]>; + + +DESCRIPTION +<<tan>> computes the tangent of the argument <[x]>. +Angles are specified in radians. + +<<tanf>> is identical, save that it takes and returns <<float>> values. + +RETURNS +The tangent of <[x]> is returned. + +PORTABILITY +<<tan>> is ANSI. <<tanf>> is an extension. +*/ + +/* tan(x) + * Return tangent function of x. + * + * kernel function: + * __kernel_tan ... tangent function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double tan(double x) +#else + double tan(x) + double x; +#endif +{ + double y[2],z=0.0; + int32_t n,ix; + + /* High word of x. */ + GET_HIGH_WORD(ix,x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1); + + /* tan(Inf or NaN) is NaN */ + else if (ix>=0x7ff00000) return x-x; /* NaN */ + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x,y); + return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even + -1 -- n odd */ + } +} + +#endif /* _DOUBLE_IS_32BITS */ diff --git a/libjava/classpath/native/fdlibm/sf_fabs.c b/libjava/classpath/native/fdlibm/sf_fabs.c new file mode 100644 index 00000000000..34f88afc4e6 --- /dev/null +++ b/libjava/classpath/native/fdlibm/sf_fabs.c @@ -0,0 +1,47 @@ +/* sf_fabs.c -- float version of s_fabs.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * fabsf(x) returns the absolute value of x. + */ + +#include "fdlibm.h" + +#ifdef __STDC__ + float fabsf(float x) +#else + float fabsf(x) + float x; +#endif +{ + uint32_t ix; + GET_FLOAT_WORD(ix,x); + SET_FLOAT_WORD(x,ix&0x7fffffff); + return x; +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double fabs(double x) +#else + double fabs(x) + double x; +#endif +{ + return (double) fabsf((float) x); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/sf_rint.c b/libjava/classpath/native/fdlibm/sf_rint.c new file mode 100644 index 00000000000..f442072874e --- /dev/null +++ b/libjava/classpath/native/fdlibm/sf_rint.c @@ -0,0 +1,80 @@ +/* sf_rint.c -- float version of s_rint.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float +#else +static float +#endif +TWO23[2]={ + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ +}; + +#ifdef __STDC__ + float rintf(float x) +#else + float rintf(x) + float x; +#endif +{ + int32_t i0,j0,sx; + uint32_t i,i1; + float w,t; + GET_FLOAT_WORD(i0,x); + sx = (i0>>31)&1; + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { + if((i0&0x7fffffff)==0) return x; + i1 = (i0&0x07fffff); + i0 &= 0xfff00000; + i0 |= ((i1|-i1)>>9)&0x400000; + SET_FLOAT_WORD(x,i0); + w = TWO23[sx]+x; + t = w-TWO23[sx]; + GET_FLOAT_WORD(i0,t); + SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + i>>=1; + if((i0&i)!=0) i0 = (i0&(~i))|((0x100000)>>j0); + } + } else { + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + w = TWO23[sx]+x; + return w-TWO23[sx]; +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double rint(double x) +#else + double rint(x) + double x; +#endif +{ + return (double) rintf((float) x); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/strtod.c b/libjava/classpath/native/fdlibm/strtod.c new file mode 100644 index 00000000000..b3e09124721 --- /dev/null +++ b/libjava/classpath/native/fdlibm/strtod.c @@ -0,0 +1,719 @@ +/* +FUNCTION + <<strtod>>, <<strtodf>>---string to double or float + +INDEX + strtod +INDEX + _strtod_r +INDEX + strtodf + +ANSI_SYNOPSIS + #include <stdlib.h> + double strtod(const char *<[str]>, char **<[tail]>); + float strtodf(const char *<[str]>, char **<[tail]>); + + double _strtod_r(void *<[reent]>, + const char *<[str]>, char **<[tail]>); + +TRAD_SYNOPSIS + #include <stdlib.h> + double strtod(<[str]>,<[tail]>) + char *<[str]>; + char **<[tail]>; + + float strtodf(<[str]>,<[tail]>) + char *<[str]>; + char **<[tail]>; + + double _strtod_r(<[reent]>,<[str]>,<[tail]>) + char *<[reent]>; + char *<[str]>; + char **<[tail]>; + +DESCRIPTION + The function <<strtod>> parses the character string <[str]>, + producing a substring which can be converted to a double + value. The substring converted is the longest initial + subsequence of <[str]>, beginning with the first + non-whitespace character, that has the format: + .[+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>] + The substring contains no characters if <[str]> is empty, consists + entirely of whitespace, or if the first non-whitespace + character is something other than <<+>>, <<->>, <<.>>, or a + digit. If the substring is empty, no conversion is done, and + the value of <[str]> is stored in <<*<[tail]>>>. Otherwise, + the substring is converted, and a pointer to the final string + (which will contain at least the terminating null character of + <[str]>) is stored in <<*<[tail]>>>. If you want no + assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>. + <<strtodf>> is identical to <<strtod>> except for its return type. + + This implementation returns the nearest machine number to the + input decimal string. Ties are broken by using the IEEE + round-even rule. + + The alternate function <<_strtod_r>> is a reentrant version. + The extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS + <<strtod>> returns the converted substring value, if any. If + no conversion could be performed, 0 is returned. If the + correct value is out of the range of representable values, + plus or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is + stored in errno. If the correct value would cause underflow, 0 + is returned and <<ERANGE>> is stored in errno. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991 by AT&T. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +#include <string.h> +#include <float.h> +#include <errno.h> +#include "mprec.h" + +double +_DEFUN (_strtod_r, (ptr, s00, se), + struct _Jv_reent *ptr _AND + _CONST char *s00 _AND + char **se) +{ + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e1, esign, i, j, + k, nd, nd0, nf, nz, nz0, sign; + int digits = 0; /* Number of digits found in fraction part. */ + long e; + _CONST char *s, *s0, *s1; + double aadj, aadj1, adj; + long L; + unsigned long y, z; + union double_union rv, rv0; + + _Jv_Bigint *bb = NULL, *bb1, *bd = NULL, *bd0, *bs = NULL, *delta = NULL; + sign = nz0 = nz = 0; + rv.d = 0.; + for (s = s00;; s++) + switch (*s) + { + case '-': + sign = 1; + /* no break */ + case '+': + if (*++s) + goto break2; + /* no break */ + case 0: + s = s00; + goto ret; + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + case ' ': + continue; + default: + goto break2; + } +break2: + if (*s == '0') + { + digits++; + nz0 = 1; + while (*++s == '0') + digits++; + if (!*s) + goto ret; + } + s0 = s; + y = z = 0; + for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) + { + digits++; + if (nd < 9) + y = 10 * y + c - '0'; + else if (nd < 16) + z = 10 * z + c - '0'; + } + nd0 = nd; + if (c == '.') + { + c = *++s; + if (!nd) + { + for (; c == '0'; c = *++s) + { + digits++; + nz++; + } + if (c > '0' && c <= '9') + { + digits++; + s0 = s; + nf += nz; + nz = 0; + goto have_dig; + } + goto dig_done; + } + for (; c >= '0' && c <= '9'; c = *++s) + { + digits++; + have_dig: + nz++; + if (c -= '0') + { + nf += nz; + for (i = 1; i < nz; i++) + if (nd++ < 9) + y *= 10; + else if (nd <= DBL_DIG + 1) + z *= 10; + if (nd++ < 9) + y = 10 * y + c; + else if (nd <= DBL_DIG + 1) + z = 10 * z + c; + nz = 0; + } + } + } +dig_done: + e = 0; + if (c == 'e' || c == 'E') + { + if (!nd && !nz && !nz0) + { + s = s00; + goto ret; + } + s00 = s; + esign = 0; + switch (c = *++s) + { + case '-': + esign = 1; + case '+': + c = *++s; + } + if (c >= '0' && c <= '9') + { + while (c == '0') + c = *++s; + if (c > '0' && c <= '9') + { + e = c - '0'; + s1 = s; + while ((c = *++s) >= '0' && c <= '9') + e = 10 * e + c - '0'; + if (s - s1 > 8) + /* Avoid confusion from exponents + * so large that e might overflow. + */ + e = 9999999L; + if (esign) + e = -e; + } + } + else + { + /* No exponent after an 'E' : that's an error. */ + ptr->_errno = EINVAL; + e = 0; + s = s00; + goto ret; + } + } + if (!nd) + { + if (!nz && !nz0) + s = s00; + goto ret; + } + e1 = e -= nf; + + /* Now we have nd0 digits, starting at s0, followed by a + * decimal point, followed by nd-nd0 digits. The number we're + * after is the integer represented by those digits times + * 10**e */ + + if (!nd0) + nd0 = nd; + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + rv.d = y; + if (k > 9) + rv.d = tens[k - 9] * rv.d + z; + bd0 = 0; + if (nd <= DBL_DIG +#ifndef RND_PRODQUOT + && FLT_ROUNDS == 1 +#endif + ) + { + if (!e) + goto ret; + if (e > 0) + { + if (e <= Ten_pmax) + { +#ifdef VAX + goto vax_ovfl_check; +#else + /* rv.d = */ rounded_product (rv.d, tens[e]); + goto ret; +#endif + } + i = DBL_DIG - nd; + if (e <= Ten_pmax + i) + { + /* A fancier test would sometimes let us do + * this for larger i values. + */ + e -= i; + rv.d *= tens[i]; +#ifdef VAX + /* VAX exponent range is so narrow we must + * worry about overflow here... + */ + vax_ovfl_check: + word0 (rv) -= P * Exp_msk1; + /* rv.d = */ rounded_product (rv.d, tens[e]); + if ((word0 (rv) & Exp_mask) + > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) + goto ovfl; + word0 (rv) += P * Exp_msk1; +#else + /* rv.d = */ rounded_product (rv.d, tens[e]); +#endif + goto ret; + } + } +#ifndef Inaccurate_Divide + else if (e >= -Ten_pmax) + { + /* rv.d = */ rounded_quotient (rv.d, tens[-e]); + goto ret; + } +#endif + } + e1 += nd - k; + + /* Get starting approximation = rv.d * 10**e1 */ + + if (e1 > 0) + { + if ((i = e1 & 15)) + rv.d *= tens[i]; + + if (e1 &= ~15) + { + if (e1 > DBL_MAX_10_EXP) + { + ovfl: + ptr->_errno = ERANGE; + + /* Force result to IEEE infinity. */ + word0 (rv) = Exp_mask; + word1 (rv) = 0; + + if (bd0) + goto retfree; + goto ret; + } + if (e1 >>= 4) + { + for (j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv.d *= bigtens[j]; + /* The last multiplication could overflow. */ + word0 (rv) -= P * Exp_msk1; + rv.d *= bigtens[j]; + if ((z = word0 (rv) & Exp_mask) + > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) + goto ovfl; + if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) + { + /* set to largest number */ + /* (Can't trust DBL_MAX) */ + word0 (rv) = Big0; +#ifndef _DOUBLE_IS_32BITS + word1 (rv) = Big1; +#endif + } + else + word0 (rv) += P * Exp_msk1; + } + + } + } + else if (e1 < 0) + { + e1 = -e1; + if ((i = e1 & 15)) + rv.d /= tens[i]; + if (e1 &= ~15) + { + e1 >>= 4; + if (e1 >= 1 << n_bigtens) + goto undfl; + for (j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv.d *= tinytens[j]; + /* The last multiplication could underflow. */ + rv0.d = rv.d; + rv.d *= tinytens[j]; + if (!rv.d) + { + rv.d = 2. * rv0.d; + rv.d *= tinytens[j]; + if (!rv.d) + { + undfl: + rv.d = 0.; + ptr->_errno = ERANGE; + if (bd0) + goto retfree; + goto ret; + } +#ifndef _DOUBLE_IS_32BITS + word0 (rv) = Tiny0; + word1 (rv) = Tiny1; +#else + word0 (rv) = Tiny1; +#endif + /* The refinement below will clean + * this approximation up. + */ + } + } + } + + /* Now the hard part -- adjusting rv to the correct value.*/ + + /* Put digits into bd: true value = bd * 10^e */ + + bd0 = s2b (ptr, s0, nd0, nd, y); + + for (;;) + { + bd = Balloc (ptr, bd0->_k); + Bcopy (bd, bd0); + bb = d2b (ptr, rv.d, &bbe, &bbbits); /* rv.d = bb * 2^bbe */ + bs = i2b (ptr, 1); + + if (e >= 0) + { + bb2 = bb5 = 0; + bd2 = bd5 = e; + } + else + { + bb2 = bb5 = -e; + bd2 = bd5 = 0; + } + if (bbe >= 0) + bb2 += bbe; + else + bd2 -= bbe; + bs2 = bb2; +#ifdef Sudden_Underflow +#ifdef IBM + j = 1 + 4 * P - 3 - bbbits + ((bbe + bbbits - 1) & 3); +#else + j = P + 1 - bbbits; +#endif +#else + i = bbe + bbbits - 1; /* logb(rv.d) */ + if (i < Emin) /* denormal */ + j = bbe + (P - Emin); + else + j = P + 1 - bbbits; +#endif + bb2 += j; + bd2 += j; + i = bb2 < bd2 ? bb2 : bd2; + if (i > bs2) + i = bs2; + if (i > 0) + { + bb2 -= i; + bd2 -= i; + bs2 -= i; + } + if (bb5 > 0) + { + bs = pow5mult (ptr, bs, bb5); + bb1 = mult (ptr, bs, bb); + Bfree (ptr, bb); + bb = bb1; + } + if (bb2 > 0) + bb = lshift (ptr, bb, bb2); + if (bd5 > 0) + bd = pow5mult (ptr, bd, bd5); + if (bd2 > 0) + bd = lshift (ptr, bd, bd2); + if (bs2 > 0) + bs = lshift (ptr, bs, bs2); + delta = diff (ptr, bb, bd); + dsign = delta->_sign; + delta->_sign = 0; + i = cmp (delta, bs); + if (i < 0) + { + /* Error is less than half an ulp -- check for + * special case of mantissa a power of two. + */ + if (dsign || word1 (rv) || word0 (rv) & Bndry_mask) + break; + delta = lshift (ptr, delta, Log2P); + if (cmp (delta, bs) > 0) + goto drop_down; + break; + } + if (i == 0) + { + /* exactly half-way between */ + if (dsign) + { + if ((word0 (rv) & Bndry_mask1) == Bndry_mask1 + && word1 (rv) == 0xffffffff) + { + /*boundary case -- increment exponent*/ + word0 (rv) = (word0 (rv) & Exp_mask) + + Exp_msk1 +#ifdef IBM + | Exp_msk1 >> 4 +#endif + ; +#ifndef _DOUBLE_IS_32BITS + word1 (rv) = 0; +#endif + break; + } + } + else if (!(word0 (rv) & Bndry_mask) && !word1 (rv)) + { + drop_down: + /* boundary case -- decrement exponent */ +#ifdef Sudden_Underflow + L = word0 (rv) & Exp_mask; +#ifdef IBM + if (L < Exp_msk1) +#else + if (L <= Exp_msk1) +#endif + goto undfl; + L -= Exp_msk1; +#else + L = (word0 (rv) & Exp_mask) - Exp_msk1; +#endif + word0 (rv) = L | Bndry_mask1; +#ifndef _DOUBLE_IS_32BITS + word1 (rv) = 0xffffffff; +#endif +#ifdef IBM + goto cont; +#else + break; +#endif + } +#ifndef ROUND_BIASED + if (!(word1 (rv) & LSB)) + break; +#endif + if (dsign) + rv.d += ulp (rv.d); +#ifndef ROUND_BIASED + else + { + rv.d -= ulp (rv.d); +#ifndef Sudden_Underflow + if (!rv.d) + goto undfl; +#endif + } +#endif + break; + } + if ((aadj = ratio (delta, bs)) <= 2.) + { + if (dsign) + aadj = aadj1 = 1.; + else if (word1 (rv) || word0 (rv) & Bndry_mask) + { +#ifndef Sudden_Underflow + if (word1 (rv) == Tiny1 && !word0 (rv)) + goto undfl; +#endif + aadj = 1.; + aadj1 = -1.; + } + else + { + /* special case -- power of FLT_RADIX to be */ + /* rounded down... */ + + if (aadj < 2. / FLT_RADIX) + aadj = 1. / FLT_RADIX; + else + aadj *= 0.5; + aadj1 = -aadj; + } + } + else + { + aadj *= 0.5; + aadj1 = dsign ? aadj : -aadj; +#ifdef Check_FLT_ROUNDS + switch (FLT_ROUNDS) + { + case 2: /* towards +infinity */ + aadj1 -= 0.5; + break; + case 0: /* towards 0 */ + case 3: /* towards -infinity */ + aadj1 += 0.5; + } +#else + if (FLT_ROUNDS == 0) + aadj1 += 0.5; +#endif + } + y = word0 (rv) & Exp_mask; + + /* Check for overflow */ + + if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) + { + rv0.d = rv.d; + word0 (rv) -= P * Exp_msk1; + adj = aadj1 * ulp (rv.d); + rv.d += adj; + if ((word0 (rv) & Exp_mask) >= + Exp_msk1 * (DBL_MAX_EXP + Bias - P)) + { + if (word0 (rv0) == Big0 && word1 (rv0) == Big1) + goto ovfl; +#ifdef _DOUBLE_IS_32BITS + word0 (rv) = Big1; +#else + word0 (rv) = Big0; + word1 (rv) = Big1; +#endif + goto cont; + } + else + word0 (rv) += P * Exp_msk1; + } + else + { +#ifdef Sudden_Underflow + if ((word0 (rv) & Exp_mask) <= P * Exp_msk1) + { + rv0.d = rv.d; + word0 (rv) += P * Exp_msk1; + adj = aadj1 * ulp (rv.d); + rv.d += adj; +#ifdef IBM + if ((word0 (rv) & Exp_mask) < P * Exp_msk1) +#else + if ((word0 (rv) & Exp_mask) <= P * Exp_msk1) +#endif + { + if (word0 (rv0) == Tiny0 + && word1 (rv0) == Tiny1) + goto undfl; + word0 (rv) = Tiny0; + word1 (rv) = Tiny1; + goto cont; + } + else + word0 (rv) -= P * Exp_msk1; + } + else + { + adj = aadj1 * ulp (rv.d); + rv.d += adj; + } +#else + /* Compute adj so that the IEEE rounding rules will + * correctly round rv.d + adj in some half-way cases. + * If rv.d * ulp(rv.d) is denormalized (i.e., + * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid + * trouble from bits lost to denormalization; + * example: 1.2e-307 . + */ + if (y <= (P - 1) * Exp_msk1 && aadj >= 1.) + { + aadj1 = (double) (int) (aadj + 0.5); + if (!dsign) + aadj1 = -aadj1; + } + adj = aadj1 * ulp (rv.d); + rv.d += adj; +#endif + } + z = word0 (rv) & Exp_mask; + if (y == z) + { + /* Can we stop now? */ + L = aadj; + aadj -= L; + /* The tolerances below are conservative. */ + if (dsign || word1 (rv) || word0 (rv) & Bndry_mask) + { + if (aadj < .4999999 || aadj > .5000001) + break; + } + else if (aadj < .4999999 / FLT_RADIX) + break; + } + cont: + Bfree (ptr, bb); + Bfree (ptr, bd); + Bfree (ptr, bs); + Bfree (ptr, delta); + } +retfree: + Bfree (ptr, bb); + Bfree (ptr, bd); + Bfree (ptr, bs); + Bfree (ptr, bd0); + Bfree (ptr, delta); +ret: + if (se) + *se = (char *) s; + if (digits == 0) + ptr->_errno = EINVAL; + return sign ? -rv.d : rv.d; +} + diff --git a/libjava/classpath/native/fdlibm/w_acos.c b/libjava/classpath/native/fdlibm/w_acos.c new file mode 100644 index 00000000000..c9ca99c4041 --- /dev/null +++ b/libjava/classpath/native/fdlibm/w_acos.c @@ -0,0 +1,118 @@ + +/* @(#)w_acos.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION + <<acos>>, <<acosf>>---arc cosine + +INDEX + acos +INDEX + acosf + +ANSI_SYNOPSIS + #include <math.h> + double acos(double <[x]>); + float acosf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double acos(<[x]>) + double <[x]>; + + float acosf(<[x]>) + float <[x]>; + + + +DESCRIPTION + + <<acos>> computes the inverse cosine (arc cosine) of the input value. + Arguments to <<acos>> must be in the range @minus{}1 to 1. + + <<acosf>> is identical to <<acos>>, except that it performs + its calculations on <<floats>>. + +RETURNS + @ifinfo + <<acos>> and <<acosf>> return values in radians, in the range of 0 to pi. + @end ifinfo + @tex + <<acos>> and <<acosf>> return values in radians, in the range of <<0>> to $\pi$. + @end tex + + If <[x]> is not between @minus{}1 and 1, the returned value is NaN + (not a number) the global variable <<errno>> is set to <<EDOM>>, and a + <<DOMAIN error>> message is sent as standard error output. + + You can modify error handling for these functions using <<matherr>>. + + +QUICKREF ANSI SVID POSIX RENTRANT + acos y,y,y,m + acosf n,n,n,m + +MATHREF + acos, [-1,1], acos(arg),,, + acos, NAN, arg,DOMAIN,EDOM + +MATHREF + acosf, [-1,1], acosf(arg),,, + acosf, NAN, argf,DOMAIN,EDOM + +*/ + +/* + * wrap_acos(x) + */ + +#include "fdlibm.h" +#include <errno.h> + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double acos(double x) /* wrapper acos */ +#else + double acos(x) /* wrapper acos */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_acos(x); +#else + double z; + struct exception exc; + z = __ieee754_acos(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(fabs(x)>1.0) { + /* acos(|x|>1) */ + exc.type = DOMAIN; + exc.name = "acos"; + exc.err = 0; + exc.arg1 = exc.arg2 = x; + exc.retval = 0.0; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } else + return z; +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/w_asin.c b/libjava/classpath/native/fdlibm/w_asin.c new file mode 100644 index 00000000000..f6cb271d392 --- /dev/null +++ b/libjava/classpath/native/fdlibm/w_asin.c @@ -0,0 +1,121 @@ + +/* @(#)w_asin.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +/* +FUNCTION + <<asin>>, <<asinf>>---arc sine + +INDEX + asin +INDEX + asinf + +ANSI_SYNOPSIS + #include <math.h> + double asin(double <[x]>); + float asinf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double asin(<[x]>) + double <[x]>; + + float asinf(<[x]>) + float <[x]>; + + +DESCRIPTION + +<<asin>> computes the inverse sine (arc sine) of the argument <[x]>. +Arguments to <<asin>> must be in the range @minus{}1 to 1. + +<<asinf>> is identical to <<asin>>, other than taking and +returning floats. + +You can modify error handling for these routines using <<matherr>>. + +RETURNS +@ifinfo +<<asin>> returns values in radians, in the range of -pi/2 to pi/2. +@end ifinfo +@tex +<<asin>> returns values in radians, in the range of $-\pi/2$ to $\pi/2$. +@end tex + +If <[x]> is not in the range @minus{}1 to 1, <<asin>> and <<asinf>> +return NaN (not a number), set the global variable <<errno>> to +<<EDOM>>, and issue a <<DOMAIN error>> message. + +You can change this error treatment using <<matherr>>. + +QUICKREF ANSI SVID POSIX RENTRANT + asin y,y,y,m + asinf n,n,n,m + +MATHREF + asin, -1<=arg<=1, asin(arg),,, + asin, NAN, arg,EDOM, DOMAIN + +MATHREF + asinf, -1<=arg<=1, asin(arg),,, + asinf, NAN, arg,EDOM, DOMAIN + + +*/ + +/* + * wrapper asin(x) + */ + + +#include "fdlibm.h" +#include <errno.h> + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double asin(double x) /* wrapper asin */ +#else + double asin(x) /* wrapper asin */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_asin(x); +#else + double z; + struct exception exc; + z = __ieee754_asin(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(fabs(x)>1.0) { + /* asin(|x|>1) */ + exc.type = DOMAIN; + exc.name = "asin"; + exc.err = 0; + exc.arg1 = exc.arg2 = x; + exc.retval = 0.0; + if(_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } else + return z; +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/w_atan2.c b/libjava/classpath/native/fdlibm/w_atan2.c new file mode 100644 index 00000000000..91742c72b91 --- /dev/null +++ b/libjava/classpath/native/fdlibm/w_atan2.c @@ -0,0 +1,117 @@ + +/* @(#)w_atan2.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +/* +FUNCTION + <<atan2>>, <<atan2f>>---arc tangent of y/x + +INDEX + atan2 +INDEX + atan2f + +ANSI_SYNOPSIS + #include <math.h> + double atan2(double <[y]>,double <[x]>); + float atan2f(float <[y]>,float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double atan2(<[y]>,<[x]>); + double <[y]>; + double <[x]>; + + float atan2f(<[y]>,<[x]>); + float <[y]>; + float <[x]>; + +DESCRIPTION + +<<atan2>> computes the inverse tangent (arc tangent) of <[y]>/<[x]>. +<<atan2>> produces the correct result even for angles near +@ifinfo +pi/2 or -pi/2 +@end ifinfo +@tex +$\pi/2$ or $-\pi/2$ +@end tex +(that is, when <[x]> is near 0). + +<<atan2f>> is identical to <<atan2>>, save that it takes and returns +<<float>>. + +RETURNS +<<atan2>> and <<atan2f>> return a value in radians, in the range of +@ifinfo +-pi to pi. +@end ifinfo +@tex +$-\pi$ to $\pi$. +@end tex + +If both <[x]> and <[y]> are 0.0, <<atan2>> causes a <<DOMAIN>> error. + +You can modify error handling for these functions using <<matherr>>. + +PORTABILITY +<<atan2>> is ANSI C. <<atan2f>> is an extension. + + +*/ + +/* + * wrapper atan2(y,x) + */ + +#include "fdlibm.h" +#include <errno.h> + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double atan2(double y, double x) /* wrapper atan2 */ +#else + double atan2(y,x) /* wrapper atan2 */ + double y,x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_atan2(y,x); +#else + double z; + struct exception exc; + z = __ieee754_atan2(y,x); + if(_LIB_VERSION == _IEEE_||isnan(x)||isnan(y)) return z; + if(x==0.0&&y==0.0) { + /* atan2(+-0,+-0) */ + exc.arg1 = y; + exc.arg2 = x; + exc.type = DOMAIN; + exc.name = "atan2"; + exc.err = 0; + exc.retval = 0.0; + if(_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } else + return z; +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/w_exp.c b/libjava/classpath/native/fdlibm/w_exp.c new file mode 100644 index 00000000000..45e087b45f9 --- /dev/null +++ b/libjava/classpath/native/fdlibm/w_exp.c @@ -0,0 +1,140 @@ + +/* @(#)w_exp.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION + <<exp>>, <<expf>>---exponential +INDEX + exp +INDEX + expf + +ANSI_SYNOPSIS + #include <math.h> + double exp(double <[x]>); + float expf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double exp(<[x]>); + double <[x]>; + + float expf(<[x]>); + float <[x]>; + +DESCRIPTION + <<exp>> and <<expf>> calculate the exponential of <[x]>, that is, + @ifinfo + e raised to the power <[x]> (where e + @end ifinfo + @tex + $e^x$ (where $e$ + @end tex + is the base of the natural system of logarithms, approximately 2.71828). + + You can use the (non-ANSI) function <<matherr>> to specify + error handling for these functions. + +RETURNS + On success, <<exp>> and <<expf>> return the calculated value. + If the result underflows, the returned value is <<0>>. If the + result overflows, the returned value is <<HUGE_VAL>>. In + either case, <<errno>> is set to <<ERANGE>>. + +PORTABILITY + <<exp>> is ANSI C. <<expf>> is an extension. + +*/ + +/* + * wrapper exp(x) + */ + +#include "fdlibm.h" +#include <errno.h> + +#ifndef _DOUBLE_IS_32BITS + +#ifndef _IEEE_LIBM + +#ifdef __STDC__ +static const double +#else +static double +#endif +o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ +u_threshold= -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */ + +#endif + +#ifdef __STDC__ + double exp(double x) /* wrapper exp */ +#else + double exp(x) /* wrapper exp */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_exp(x); +#else + double z; + struct exception exc; + z = __ieee754_exp(x); + if(_LIB_VERSION == _IEEE_) return z; + if(finite(x)) { + if(x>o_threshold) { + /* exp(finite) overflow */ +#ifndef HUGE_VAL +#define HUGE_VAL inf + double inf = 0.0; + + SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */ +#endif + exc.type = OVERFLOW; + exc.name = "exp"; + exc.err = 0; + exc.arg1 = exc.arg2 = x; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } else if(x<u_threshold) { + /* exp(finite) underflow */ + exc.type = UNDERFLOW; + exc.name = "exp"; + exc.err = 0; + exc.arg1 = exc.arg2 = x; + exc.retval = 0.0; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } + } + return z; +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/w_fmod.c b/libjava/classpath/native/fdlibm/w_fmod.c new file mode 100644 index 00000000000..b6b36cb76ab --- /dev/null +++ b/libjava/classpath/native/fdlibm/w_fmod.c @@ -0,0 +1,107 @@ + +/* @(#)w_fmod.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION +<<fmod>>, <<fmodf>>---floating-point remainder (modulo) + +INDEX +fmod +INDEX +fmodf + +ANSI_SYNOPSIS +#include <math.h> +double fmod(double <[x]>, double <[y]>) +float fmodf(float <[x]>, float <[y]>) + +TRAD_SYNOPSIS +#include <math.h> +double fmod(<[x]>, <[y]>) +double (<[x]>, <[y]>); + +float fmodf(<[x]>, <[y]>) +float (<[x]>, <[y]>); + +DESCRIPTION +The <<fmod>> and <<fmodf>> functions compute the floating-point +remainder of <[x]>/<[y]> (<[x]> modulo <[y]>). + +RETURNS +The <<fmod>> function returns the value +@ifinfo +<[x]>-<[i]>*<[y]>, +@end ifinfo +@tex +$x-i\times y$, +@end tex +for the largest integer <[i]> such that, if <[y]> is nonzero, the +result has the same sign as <[x]> and magnitude less than the +magnitude of <[y]>. + +<<fmod(<[x]>,0)>> returns NaN, and sets <<errno>> to <<EDOM>>. + +You can modify error treatment for these functions using <<matherr>>. + +PORTABILITY +<<fmod>> is ANSI C. <<fmodf>> is an extension. +*/ + +/* + * wrapper fmod(x,y) + */ + +#include "fdlibm.h" +#include <errno.h> + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double fmod(double x, double y) /* wrapper fmod */ +#else + double fmod(x,y) /* wrapper fmod */ + double x,y; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_fmod(x,y); +#else + double z; + struct exception exc; + z = __ieee754_fmod(x,y); + if(_LIB_VERSION == _IEEE_ ||isnan(y)||isnan(x)) return z; + if(y==0.0) { + /* fmod(x,0) */ + exc.type = DOMAIN; + exc.name = "fmod"; + exc.arg1 = x; + exc.arg2 = y; + exc.err = 0; + if (_LIB_VERSION == _SVID_) + exc.retval = x; + else + exc.retval = 0.0/0.0; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } else + return z; +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/w_log.c b/libjava/classpath/native/fdlibm/w_log.c new file mode 100644 index 00000000000..dcc8b9762ec --- /dev/null +++ b/libjava/classpath/native/fdlibm/w_log.c @@ -0,0 +1,115 @@ + +/* @(#)w_log.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION + <<log>>, <<logf>>---natural logarithms + +INDEX + log +INDEX + logf + +ANSI_SYNOPSIS + #include <math.h> + double log(double <[x]>); + float logf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double log(<[x]>); + double <[x]>; + + float logf(<[x]>); + float <[x]>; + +DESCRIPTION +Return the natural logarithm of <[x]>, that is, its logarithm base e +(where e is the base of the natural system of logarithms, 2.71828@dots{}). +<<log>> and <<logf>> are identical save for the return and argument types. + +You can use the (non-ANSI) function <<matherr>> to specify error +handling for these functions. + +RETURNS +Normally, returns the calculated value. When <[x]> is zero, the +returned value is <<-HUGE_VAL>> and <<errno>> is set to <<ERANGE>>. +When <[x]> is negative, the returned value is <<-HUGE_VAL>> and +<<errno>> is set to <<EDOM>>. You can control the error behavior via +<<matherr>>. + +PORTABILITY +<<log>> is ANSI, <<logf>> is an extension. +*/ + +/* + * wrapper log(x) + */ + +#include "fdlibm.h" +#include <errno.h> + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double log(double x) /* wrapper log */ +#else + double log(x) /* wrapper log */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_log(x); +#else + double z; + struct exception exc; + z = __ieee754_log(x); + if(_LIB_VERSION == _IEEE_ || isnan(x) || x > 0.0) return z; +#ifndef HUGE_VAL +#define HUGE_VAL inf + double inf = 0.0; + + SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */ +#endif + exc.name = "log"; + exc.err = 0; + exc.arg1 = x; + exc.arg2 = x; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if(x==0.0) { + /* log(0) */ + exc.type = SING; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = EDOM; + } + } else { + /* log(x<0) */ + exc.type = DOMAIN; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + errno = EDOM; + } + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/fdlibm/w_pow.c b/libjava/classpath/native/fdlibm/w_pow.c new file mode 100644 index 00000000000..3df099a1714 --- /dev/null +++ b/libjava/classpath/native/fdlibm/w_pow.c @@ -0,0 +1,231 @@ + + +/* @(#)w_pow.c 5.2 93/10/01 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION + <<pow>>, <<powf>>---x to the power y +INDEX + pow +INDEX + powf + + +ANSI_SYNOPSIS + #include <math.h> + double pow(double <[x]>, double <[y]>); + float pow(float <[x]>, float <[y]>); + +TRAD_SYNOPSIS + #include <math.h> + double pow(<[x]>, <[y]>); + double <[x]>, <[y]>; + + float pow(<[x]>, <[y]>); + float <[x]>, <[y]>; + +DESCRIPTION + <<pow>> and <<powf>> calculate <[x]> raised to the exp1.0nt <[y]>. + @tex + (That is, $x^y$.) + @end tex + +RETURNS + On success, <<pow>> and <<powf>> return the value calculated. + + When the argument values would produce overflow, <<pow>> + returns <<HUGE_VAL>> and set <<errno>> to <<ERANGE>>. If the + argument <[x]> passed to <<pow>> or <<powf>> is a negative + noninteger, and <[y]> is also not an integer, then <<errno>> + is set to <<EDOM>>. If <[x]> and <[y]> are both 0, then + <<pow>> and <<powf>> return <<1>>. + + You can modify error handling for these functions using <<matherr>>. + +PORTABILITY + <<pow>> is ANSI C. <<powf>> is an extension. */ + +/* + * wrapper pow(x,y) return x**y + */ + +#include "fdlibm.h" +#include <errno.h> + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double pow(double x, double y) /* wrapper pow */ +#else + double pow(x,y) /* wrapper pow */ + double x,y; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_pow(x,y); +#else + double z; +#ifndef HUGE_VAL +#define HUGE_VAL inf + double inf = 0.0; + + SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */ +#endif + struct exception exc; + z=__ieee754_pow(x,y); + if(_LIB_VERSION == _IEEE_|| isnan(y)) return z; + if(isnan(x)) { + if(y==0.0) { + /* pow(NaN,0.0) */ + /* error only if _LIB_VERSION == _SVID_ & _XOPEN_ */ + exc.type = DOMAIN; + exc.name = "pow"; + exc.err = 0; + exc.arg1 = x; + exc.arg2 = y; + exc.retval = x; + if (_LIB_VERSION == _IEEE_ || + _LIB_VERSION == _POSIX_) exc.retval = 1.0; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } else + return z; + } + if(x==0.0){ + if(y==0.0) { + /* pow(0.0,0.0) */ + /* error only if _LIB_VERSION == _SVID_ */ + exc.type = DOMAIN; + exc.name = "pow"; + exc.err = 0; + exc.arg1 = x; + exc.arg2 = y; + exc.retval = 0.0; + if (_LIB_VERSION != _SVID_) exc.retval = 1.0; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } + if(finite(y)&&y<0.0) { + /* 0**neg */ + exc.type = DOMAIN; + exc.name = "pow"; + exc.err = 0; + exc.arg1 = x; + exc.arg2 = y; + if (_LIB_VERSION == _SVID_) + exc.retval = 0.0; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } + return z; + } + if(!finite(z)) { + if(finite(x)&&finite(y)) { + if(isnan(z)) { + /* neg**non-integral */ + exc.type = DOMAIN; + exc.name = "pow"; + exc.err = 0; + exc.arg1 = x; + exc.arg2 = y; + if (_LIB_VERSION == _SVID_) + exc.retval = 0.0; + else + exc.retval = 0.0/0.0; /* X/Open allow NaN */ + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } else { + /* pow(x,y) overflow */ + exc.type = OVERFLOW; + exc.name = "pow"; + exc.err = 0; + exc.arg1 = x; + exc.arg2 = y; + if (_LIB_VERSION == _SVID_) { + exc.retval = HUGE; + y *= 0.5; + if(x<0.0&&rint(y)!=y) exc.retval = -HUGE; + } else { + exc.retval = HUGE_VAL; + y *= 0.5; + if(x<0.0&&rint(y)!=y) exc.retval = -HUGE_VAL; + } + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } + } + } + if(z==0.0&&finite(x)&&finite(y)) { + /* pow(x,y) underflow */ + exc.type = UNDERFLOW; + exc.name = "pow"; + exc.err = 0; + exc.arg1 = x; + exc.arg2 = y; + exc.retval = 0.0; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } + return z; +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ + + + + + + + + + + + + + + diff --git a/libjava/classpath/native/fdlibm/w_remainder.c b/libjava/classpath/native/fdlibm/w_remainder.c new file mode 100644 index 00000000000..a06be0e7b30 --- /dev/null +++ b/libjava/classpath/native/fdlibm/w_remainder.c @@ -0,0 +1,119 @@ + +/* @(#)w_remainder.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION +<<rint>>, <<rintf>>, <<remainder>>, <<remainderf>>---round and remainder +INDEX + rint +INDEX + rintf +INDEX + remainder +INDEX + remainderf + +ANSI_SYNOPSIS + #include <math.h> + double rint(double <[x]>); + float rintf(float <[x]>); + double remainder(double <[x]>, double <[y]>); + float remainderf(float <[x]>, float <[y]>); + +TRAD_SYNOPSIS + #include <math.h> + double rint(<[x]>) + double <[x]>; + float rintf(<[x]>) + float <[x]>; + double remainder(<[x]>,<[y]>) + double <[x]>, <[y]>; + float remainderf(<[x]>,<[y]>) + float <[x]>, <[y]>; + +DESCRIPTION +<<rint>> and <<rintf>> returns their argument rounded to the nearest +integer. <<remainder>> and <<remainderf>> find the remainder of +<[x]>/<[y]>; this value is in the range -<[y]>/2 .. +<[y]>/2. + +RETURNS +<<rint>> and <<remainder>> return the integer result as a double. + +PORTABILITY +<<rint>> and <<remainder>> are System V release 4. <<rintf>> and +<<remainderf>> are extensions. + +*/ + +/* + * wrapper remainder(x,p) + */ + +#include "fdlibm.h" +#include <errno.h> + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double remainder(double x, double y) /* wrapper remainder */ +#else + double remainder(x,y) /* wrapper remainder */ + double x,y; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_remainder(x,y); +#else + double z; + struct exception exc; + z = __ieee754_remainder(x,y); + if(_LIB_VERSION == _IEEE_ || isnan(y)) return z; + if(y==0.0) { + /* remainder(x,0) */ + exc.type = DOMAIN; + exc.name = "remainder"; + exc.err = 0; + exc.arg1 = x; + exc.arg2 = y; + exc.retval = 0.0/0.0; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } else + return z; +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ + + + + + + + + + + + + + + + + + diff --git a/libjava/classpath/native/fdlibm/w_sqrt.c b/libjava/classpath/native/fdlibm/w_sqrt.c new file mode 100644 index 00000000000..23a793ce74a --- /dev/null +++ b/libjava/classpath/native/fdlibm/w_sqrt.c @@ -0,0 +1,93 @@ + +/* @(#)w_sqrt.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +FUNCTION + <<sqrt>>, <<sqrtf>>---positive square root + +INDEX + sqrt +INDEX + sqrtf + +ANSI_SYNOPSIS + #include <math.h> + double sqrt(double <[x]>); + float sqrtf(float <[x]>); + +TRAD_SYNOPSIS + #include <math.h> + double sqrt(<[x]>); + float sqrtf(<[x]>); + +DESCRIPTION + <<sqrt>> computes the positive square root of the argument. + You can modify error handling for this function with + <<matherr>>. + +RETURNS + On success, the square root is returned. If <[x]> is real and + positive, then the result is positive. If <[x]> is real and + negative, the global value <<errno>> is set to <<EDOM>> (domain error). + + +PORTABILITY + <<sqrt>> is ANSI C. <<sqrtf>> is an extension. +*/ + +/* + * wrapper sqrt(x) + */ + +#include "fdlibm.h" +#include <errno.h> + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double sqrt(double x) /* wrapper sqrt */ +#else + double sqrt(x) /* wrapper sqrt */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_sqrt(x); +#else + struct exception exc; + double z; + z = __ieee754_sqrt(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(x<0.0) { + exc.type = DOMAIN; + exc.name = "sqrt"; + exc.err = 0; + exc.arg1 = exc.arg2 = x; + if (_LIB_VERSION == _SVID_) + exc.retval = 0.0; + else + exc.retval = 0.0/0.0; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + errno = EDOM; + } + if (exc.err != 0) + errno = exc.err; + return exc.retval; + } else + return z; +#endif +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/libjava/classpath/native/jni/.cvsignore b/libjava/classpath/native/jni/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/Makefile.am b/libjava/classpath/native/jni/Makefile.am new file mode 100644 index 00000000000..41d9a913bd1 --- /dev/null +++ b/libjava/classpath/native/jni/Makefile.am @@ -0,0 +1,20 @@ +## Input file for automake to generate the Makefile.in used by configure + +if CREATE_CORE_JNI_LIBRARIES + JNIDIRS = java-io java-lang java-net java-nio java-util +endif + +if CREATE_GTK_PEER_LIBRARIES + GTKDIR = gtk-peer +endif + +if CREATE_XMLJ_LIBRARY + XMLJDIR = xmlj +endif + +SUBDIRS = classpath $(JNIDIRS) $(GTKDIR) $(XMLJDIR) +DIST_SUBDIRS = classpath java-io java-lang java-net java-nio java-util \ + gtk-peer xmlj + +all-local: + cd $(top_srcdir) && scripts/check_jni_methods.sh diff --git a/libjava/classpath/native/jni/classpath/.cvsignore b/libjava/classpath/native/jni/classpath/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/classpath/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/classpath/Makefile.am b/libjava/classpath/native/jni/classpath/Makefile.am new file mode 100644 index 00000000000..0171d3728e0 --- /dev/null +++ b/libjava/classpath/native/jni/classpath/Makefile.am @@ -0,0 +1,10 @@ +noinst_LTLIBRARIES = libclasspath.la + +libclasspath_la_SOURCES = jcl.c jcl.h \ + jnilink.c jnilink.h \ + primlib.c primlib.h \ + native_state.c native_state.h + +AM_LDFLAGS = @CLASSPATH_MODULE@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@ diff --git a/libjava/classpath/native/jni/classpath/classpath_jawt.h b/libjava/classpath/native/jni/classpath/classpath_jawt.h new file mode 100644 index 00000000000..6ff5c53355e --- /dev/null +++ b/libjava/classpath/native/jni/classpath/classpath_jawt.h @@ -0,0 +1,64 @@ +/* classpath_awt.h -- libjawt's interface to the peer library + Copyright (C) 2005 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath 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, or (at your option) + any later version. + + GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + 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. */ + +/* + * libjawt.so is linked directly to the peer library with -l. This + * header declares all the functions that libjawt.so needs -- X-based + * peer libraries wanting to support libjawt.so must implement these + * functions. + */ + +#ifndef __classpath_jawt_h__ +#define __classpath_jawt_h__ + +#include <jni.h> +#include <X11/Xlib.h> + +#define CLASSPATH_JAWT_VERSION 0x10004 + +jint classpath_jawt_get_awt_version (); +Display* classpath_jawt_get_default_display (JNIEnv* env, jobject canvas); +Drawable classpath_jawt_get_drawable (JNIEnv* env, jobject canvas); +VisualID classpath_jawt_get_visualID (JNIEnv* env, jobject canvas); +jint classpath_jawt_object_lock (jobject lock); +void classpath_jawt_object_unlock (jobject lock); +jint classpath_jawt_lock (); +void classpath_jawt_unlock (); +jobject classpath_jawt_create_lock (); +void classpath_jawt_destroy_lock (jobject lock); + +#endif /* __classpath_jawt_h__ */ diff --git a/libjava/classpath/native/jni/classpath/jcl.c b/libjava/classpath/native/jni/classpath/jcl.c new file mode 100644 index 00000000000..03f9b3753cc --- /dev/null +++ b/libjava/classpath/native/jni/classpath/jcl.c @@ -0,0 +1,180 @@ +/* jcl.c + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <jcl.h> + +#ifndef __GNUC__ +#define __attribute__(x) /* nothing */ +#endif + +JNIEXPORT void JNICALL +JCL_ThrowException (JNIEnv * env, const char *className, const char *errMsg) +{ + jclass excClass; + if ((*env)->ExceptionOccurred (env)) + { + (*env)->ExceptionClear (env); + } + excClass = (*env)->FindClass (env, className); + if (excClass == NULL) + { + jclass errExcClass; + errExcClass = + (*env)->FindClass (env, "java/lang/ClassNotFoundException"); + if (errExcClass == NULL) + { + errExcClass = (*env)->FindClass (env, "java/lang/InternalError"); + if (errExcClass == NULL) + { + fprintf (stderr, "JCL: Utterly failed to throw exeption "); + fprintf (stderr, className); + fprintf (stderr, " with message "); + fprintf (stderr, errMsg); + return; + } + } + /* Removed this (more comprehensive) error string to avoid the need for + * a static variable or allocation of a buffer for this message in this + * (unlikely) error case. --Fridi. + * + * sprintf(errstr,"JCL: Failed to throw exception %s with message %s: could not find exception class.", className, errMsg); + */ + (*env)->ThrowNew (env, errExcClass, className); + } + (*env)->ThrowNew (env, excClass, errMsg); +} + +JNIEXPORT void *JNICALL +JCL_malloc (JNIEnv * env, size_t size) +{ + void *mem = malloc (size); + if (mem == NULL) + { + JCL_ThrowException (env, "java/lang/OutOfMemoryError", + "malloc() failed."); + return NULL; + } + return mem; +} + +JNIEXPORT void *JNICALL +JCL_realloc (JNIEnv * env, void *ptr, size_t size) +{ + ptr = realloc (ptr, size); + if (ptr == 0) + { + JCL_ThrowException (env, "java/lang/OutOfMemoryError", + "malloc() failed."); + return NULL; + } + return (ptr); +} + +JNIEXPORT void JNICALL +JCL_free (JNIEnv * env __attribute__ ((unused)), void *p) +{ + if (p != NULL) + { + free (p); + } +} + +JNIEXPORT const char *JNICALL +JCL_jstring_to_cstring (JNIEnv * env, jstring s) +{ + const char *cstr; + if (s == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", + "Null string"); + return NULL; + } + cstr = (const char *) (*env)->GetStringUTFChars (env, s, NULL); + if (cstr == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "GetStringUTFChars() failed."); + return NULL; + } + return cstr; +} + +JNIEXPORT void JNICALL +JCL_free_cstring (JNIEnv * env, jstring s, const char *cstr) +{ + (*env)->ReleaseStringUTFChars (env, s, cstr); +} + +JNIEXPORT jint JNICALL +JCL_MonitorEnter (JNIEnv * env, jobject o) +{ + jint retval = (*env)->MonitorEnter (env, o); + if (retval != 0) + { + JCL_ThrowException (env, "java/lang/InternalError", + "MonitorEnter() failed."); + } + return retval; +} + +JNIEXPORT jint JNICALL +JCL_MonitorExit (JNIEnv * env, jobject o) +{ + jint retval = (*env)->MonitorExit (env, o); + if (retval != 0) + { + JCL_ThrowException (env, "java/lang/InternalError", + "MonitorExit() failed."); + } + return retval; +} + +JNIEXPORT jclass JNICALL +JCL_FindClass (JNIEnv * env, const char *className) +{ + jclass retval = (*env)->FindClass (env, className); + if (retval == NULL) + { + JCL_ThrowException (env, "java/lang/ClassNotFoundException", className); + } + return retval; +} diff --git a/libjava/classpath/native/jni/classpath/jcl.h b/libjava/classpath/native/jni/classpath/jcl.h new file mode 100644 index 00000000000..e526b293966 --- /dev/null +++ b/libjava/classpath/native/jni/classpath/jcl.h @@ -0,0 +1,68 @@ +/* jcl.h + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef __JCL_H__ +#define __JCL_H__ + +#include <stddef.h> +#include <jni.h> +#include <config.h> + +JNIEXPORT jclass JNICALL JCL_FindClass (JNIEnv * env, const char *className); +JNIEXPORT void JNICALL JCL_ThrowException (JNIEnv * env, + const char *className, + const char *errMsg); +JNIEXPORT void *JNICALL JCL_malloc (JNIEnv * env, size_t size); +JNIEXPORT void *JNICALL JCL_realloc (JNIEnv * env, void *ptr, size_t size); +JNIEXPORT void JNICALL JCL_free (JNIEnv * env, void *p); +JNIEXPORT const char *JNICALL JCL_jstring_to_cstring (JNIEnv * env, + jstring s); +JNIEXPORT void JNICALL JCL_free_cstring (JNIEnv * env, jstring s, + const char *cstr); +JNIEXPORT jint JNICALL JCL_MonitorEnter (JNIEnv * env, jobject o); +JNIEXPORT jint JNICALL JCL_MonitorExit (JNIEnv * env, jobject o); + +#define JCL_RETHROW_EXCEPTION(env) if((*(env))->ExceptionOccurred((env)) != NULL) return NULL; + +/* Simple debug macro */ +#ifdef DEBUG +#define DBG(x) fprintf(stderr, (x)); +#else +#define DBG(x) +#endif + +#endif diff --git a/libjava/classpath/native/jni/classpath/jnilink.c b/libjava/classpath/native/jni/classpath/jnilink.c new file mode 100644 index 00000000000..15e73a7210b --- /dev/null +++ b/libjava/classpath/native/jni/classpath/jnilink.c @@ -0,0 +1,125 @@ +/* JNILINK 1.1: JNI version. + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include <stdlib.h> +#include <string.h> +#include <jcl.h> + +#include "jnilink.h" + +#define GETCLASS(c) *(jclass*)(c) + +JNIEXPORT jclass JNICALL +LINK_RelinkClass (JNIEnv * env, linkedClass * c, const char *name) +{ + jclass found; + LINK_UnlinkClass (env, *c); + + found = (*env)->FindClass (env, name); + if (found == NULL) + return NULL; + + *c = JCL_malloc (env, sizeof (jclass)); + if (*c == NULL) + return NULL; + + GETCLASS (*c) = (*env)->NewGlobalRef (env, found); + return GETCLASS (*c); +} + +JNIEXPORT jclass JNICALL +LINK_RelinkKnownClass (JNIEnv * env, linkedClass * c, jclass newClass) +{ + LINK_UnlinkClass (env, *c); + + *c = JCL_malloc (env, sizeof (jclass)); + if (*c == NULL) + return NULL; + + GETCLASS (*c) = (*env)->NewGlobalRef (env, newClass); + return newClass; +} + +JNIEXPORT jmethodID JNICALL +LINK_RelinkMethod (JNIEnv * env, jmethodID * m, linkedClass c, + const char *name, const char *sig) +{ + *m = (*env)->GetMethodID (env, GETCLASS (c), name, sig); + return *m; +} + +JNIEXPORT jmethodID JNICALL +LINK_RelinkStaticMethod (JNIEnv * env, jmethodID * m, linkedClass c, + const char *name, const char *sig) +{ + *m = (*env)->GetStaticMethodID (env, GETCLASS (c), name, sig); + return *m; +} + +JNIEXPORT jfieldID JNICALL +LINK_RelinkField (JNIEnv * env, jfieldID * f, linkedClass c, + const char *name, const char *sig) +{ + *f = (*env)->GetFieldID (env, GETCLASS (c), name, sig); + return *f; +} + +JNIEXPORT jfieldID JNICALL +LINK_RelinkStaticField (JNIEnv * env, jfieldID * f, linkedClass c, + const char *name, const char *sig) +{ + *f = (*env)->GetStaticFieldID (env, GETCLASS (c), name, sig); + return *f; +} + + +/* These are for when the class referencing the symbols is unloaded; it +destroys any object references + * the linker might have kept around. + */ +JNIEXPORT void JNICALL +LINK_UnlinkClass (JNIEnv * env, linkedClass * c) +{ + if (*c != NULL) + { + if (GETCLASS (*c) != NULL) + (*env)->DeleteGlobalRef (env, GETCLASS (*c)); + JCL_free (env, *c); + *c = NULL; + } +} diff --git a/libjava/classpath/native/jni/classpath/jnilink.h b/libjava/classpath/native/jni/classpath/jnilink.h new file mode 100644 index 00000000000..dd94b3a7aed --- /dev/null +++ b/libjava/classpath/native/jni/classpath/jnilink.h @@ -0,0 +1,82 @@ +/* JNILINK 1.1: JNI version. + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#ifndef __JNILINK_H__ +#define __JNILINK_H__ + +#include <jni.h> + +typedef void *linkedClass; + +#define LINK_LinkClass(env,c,name) ((c)==NULL ? LINK_ReallyLinkClass((env),&(c),(name)) : (c)) +#define LINK_LinkKnownClass(env,c,newClass) ((c)==NULL ? LINK_ReallyLinkKnownClass((env),&(c),(newClass)) : (c)) +#define LINK_LinkMethod(env,m,c,name,sig) ((m)==NULL ? LINK_RelinkMethod((env),&(m),(c),(name),(sig)) : (m)) +#define LINK_LinkStaticMethod(env,m,c,name,sig) ((m)==NULL ? LINK_RelinkStaticMethod((env),&(m),(c),(name),(sig)) : (m)) +#define LINK_LinkField(env,f,c,name,sig) ((m)==NULL ? LINK_RelinkField((env),&(f),(c),(name),(sig)) : (f)) +#define LINK_LinkStaticField(env,f,c,name,sig) ((m)==NULL ? LINK_RelinkStaticField((env),&(f),(c),(name),(sig)) : (f)) + +#define LINK_LinkConstructor(env,m,c,sig) ((m)==NULL ? LINK_RelinkMethod((env),&(m),(c),"<init>",(sig)) : (m)) + +JNIEXPORT jclass JNICALL +LINK_ReallyLinkClass (JNIEnv * env, linkedClass * c, const char *name); +JNIEXPORT jclass JNICALL +LINK_ReallyLinkKnownClass (JNIEnv * env, linkedClass * c, jclass newClass); +JNIEXPORT jclass JNICALL +LINK_RelinkClass (JNIEnv * env, linkedClass * c, const char *name); +JNIEXPORT jclass JNICALL +LINK_RelinkKnownClass (JNIEnv * env, linkedClass * c, jclass newClass); +JNIEXPORT jmethodID JNICALL +LINK_RelinkMethod (JNIEnv * env, jmethodID * m, linkedClass c, + const char *name, const char *sig); +JNIEXPORT jmethodID JNICALL +LINK_RelinkStaticMethod (JNIEnv * env, jmethodID * m, linkedClass c, + const char *name, const char *sig); +JNIEXPORT jfieldID JNICALL +LINK_RelinkField (JNIEnv * env, jfieldID * f, linkedClass c, + const char *name, const char *sig); +JNIEXPORT jfieldID JNICALL +LINK_RelinkStaticField (JNIEnv * env, jfieldID * f, linkedClass c, + const char *name, const char *sig); + +/* These are for when the class referencing the symbols is unloaded; it +destroys any object references + * the linker might have kept around. + */ +JNIEXPORT void JNICALL LINK_UnlinkClass (JNIEnv * env, linkedClass * c); + +#endif diff --git a/libjava/classpath/native/jni/classpath/native_state.c b/libjava/classpath/native/jni/classpath/native_state.c new file mode 100644 index 00000000000..3c11b8343de --- /dev/null +++ b/libjava/classpath/native/jni/classpath/native_state.c @@ -0,0 +1,248 @@ +/* Magical NSA API -- Associate a C ptr with an instance of an object + Copyright (C) 1998, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include <stdlib.h> +#include <jni.h> +#include "native_state.h" + +#define DEFAULT_TABLE_SIZE 97 + +struct state_table * +cp_gtk_init_state_table_with_size (JNIEnv * env, jclass clazz, jint size) +{ + struct state_table *table; + jfieldID hash; + jclass clazz_g; + + hash = (*env)->GetFieldID (env, clazz, "native_state", "I"); + if (hash == NULL) + return NULL; + + clazz_g = (*env)->NewGlobalRef (env, clazz); + if (clazz_g == NULL) + return NULL; + + table = (struct state_table *) malloc (sizeof (struct state_table)); + table->size = size; + table->head = (struct state_node **) calloc (sizeof (struct state_node *), + table->size); + table->hash = hash; + table->clazz = clazz_g; + + return table; +} + +struct state_table * +cp_gtk_init_state_table (JNIEnv * env, jclass clazz) +{ + return cp_gtk_init_state_table_with_size (env, clazz, DEFAULT_TABLE_SIZE); +} + +static void * +remove_node (struct state_node **head, jint obj_id) +{ + struct state_node *back_ptr = NULL; + struct state_node *node = *head; + + while (node != NULL) + { + if (node->key == obj_id) + { + void *return_value; + if (back_ptr == NULL) + *head = node->next; + else + back_ptr->next = node->next; + return_value = node->c_state; + free (node); + return return_value; + } + back_ptr = node; + node = node->next; + } + + return NULL; +} + +static void * +get_node (struct state_node **head, jint obj_id) +{ + struct state_node *back_ptr = NULL; + struct state_node *node = *head; + + while (node != NULL) + { + if (node->key == obj_id) + { + /* Move the node we found to the front of the list. */ + if (back_ptr != NULL) + { + back_ptr->next = node->next; + node->next = *head; + *head = node; + } + + /* Return the match. */ + return node->c_state; + } + + back_ptr = node; + node = node->next; + } + + return NULL; +} + +static void +add_node (struct state_node **head, jint obj_id, void *state) +{ + struct state_node *node = *head; + struct state_node *back_ptr = NULL; + + struct state_node *new_node; + + if (node != NULL) + { + while (node->next != NULL && obj_id != node->key) + { + back_ptr = node; + node = node->next; + } + + if (node->key == obj_id) + { + /* If we're updating a node, move it to the front of the + list. */ + if (back_ptr != NULL) + { + back_ptr->next = node->next; + node->next = *head; + *head = node; + } + node->c_state = state; + return; + } + } + + new_node = (struct state_node *) malloc (sizeof (struct state_node)); + new_node->key = obj_id; + new_node->c_state = state; + new_node->next = *head; + *head = new_node; +} + +void +cp_gtk_set_state_oid (JNIEnv * env, jobject lock, struct state_table *table, + jint obj_id, void *state) +{ + jint hash; + + hash = obj_id % table->size; + + (*env)->MonitorEnter (env, lock); + add_node (&table->head[hash], obj_id, state); + (*env)->MonitorExit (env, lock); +} + +void * +cp_gtk_get_state_oid (JNIEnv * env, jobject lock, struct state_table *table, + jint obj_id) +{ + jint hash; + void *return_value; + + hash = obj_id % table->size; + + (*env)->MonitorEnter (env, lock); + return_value = get_node (&table->head[hash], obj_id); + (*env)->MonitorExit (env, lock); + + return return_value; +} + +void * +cp_gtk_remove_state_oid (JNIEnv * env, jobject lock, struct state_table *table, + jint obj_id) +{ + jint hash; + void *return_value; + + hash = obj_id % table->size; + + (*env)->MonitorEnter (env, lock); + return_value = remove_node (&table->head[hash], obj_id); + (*env)->MonitorExit (env, lock); + + return return_value; +} + +int +cp_gtk_set_state (JNIEnv * env, jobject obj, struct state_table *table, void *state) +{ + jint obj_id; + obj_id = (*env)->GetIntField (env, obj, table->hash); + + if ((*env)->ExceptionOccurred (env) != NULL) + return -1; + + cp_gtk_set_state_oid (env, table->clazz, table, obj_id, state); + return 0; +} + +void * +cp_gtk_get_state (JNIEnv * env, jobject obj, struct state_table *table) +{ + jint obj_id; + obj_id = (*env)->GetIntField (env, obj, table->hash); + + if ((*env)->ExceptionOccurred (env) != NULL) + return NULL; + + return cp_gtk_get_state_oid (env, table->clazz, table, obj_id); +} + +void * +cp_gtk_remove_state_slot (JNIEnv * env, jobject obj, struct state_table *table) +{ + jint obj_id; + obj_id = (*env)->GetIntField (env, obj, table->hash); + + if ((*env)->ExceptionOccurred (env) != NULL) + return NULL; + + return cp_gtk_remove_state_oid (env, table->clazz, table, obj_id); +} diff --git a/libjava/classpath/native/jni/classpath/native_state.h b/libjava/classpath/native/jni/classpath/native_state.h new file mode 100644 index 00000000000..641e588827d --- /dev/null +++ b/libjava/classpath/native/jni/classpath/native_state.h @@ -0,0 +1,71 @@ +/* Magical NSA API -- Associate a C ptr with an instance of an object + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef JCL_NATIVE_STATE +#define JCL_NATIVE_STATE + +#include <jni.h> + +struct state_table +{ + jint size; /* number of slots, should be prime */ + jfieldID hash; /* field containing System.identityHashCode(this) */ + jclass clazz; /* lock aquired for reading/writing nodes */ + struct state_node **head; +}; + +struct state_node +{ + jint key; + void *c_state; + struct state_node *next; +}; + +struct state_table *cp_gtk_init_state_table_with_size (JNIEnv *, jclass, jint); +struct state_table *cp_gtk_init_state_table (JNIEnv *, jclass); + +/* lowlevel api */ +void cp_gtk_set_state_oid (JNIEnv *, jobject, struct state_table *, jint, void *); +void *cp_gtk_get_state_oid (JNIEnv *, jobject, struct state_table *, jint); +void *cp_gtk_remove_state_oid (JNIEnv *, jobject, struct state_table *, jint); + +/* highlevel api */ +int cp_gtk_set_state (JNIEnv *, jobject, struct state_table *, void *); +void *cp_gtk_get_state (JNIEnv *, jobject, struct state_table *); +void *cp_gtk_remove_state_slot (JNIEnv *, jobject, struct state_table *); + +#endif diff --git a/libjava/classpath/native/jni/classpath/primlib.c b/libjava/classpath/native/jni/classpath/primlib.c new file mode 100644 index 00000000000..e6773ba5353 --- /dev/null +++ b/libjava/classpath/native/jni/classpath/primlib.c @@ -0,0 +1,724 @@ +/* primlib.c + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include <jnilink.h> +#include <primlib.h> +#include <jcl.h> + +static jclass nativeWrapClass[PRIMLIB_NUMTYPES] = + { NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL +}; + +static jclass nativeTypeClass[PRIMLIB_NUMTYPES] = + { NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL +}; + +static jmethodID nativeWrapClassConstructor[PRIMLIB_NUMTYPES] = + { NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL +}; + +static jmethodID nativeWrapClassAccessor[PRIMLIB_NUMTYPES] = + { NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const char *nativeWrapClassName[PRIMLIB_NUMTYPES] = { + NULL, + NULL, + "java/lang/Boolean", + "java/lang/Byte", + "java/lang/Character", + "java/lang/Short", + "java/lang/Integer", + "java/lang/Long", + "java/lang/Float", + "java/lang/Double", + "java/lang/Void", + NULL +}; + +static const char *nativeWrapClassConstructorSig[PRIMLIB_NUMTYPES] = { + NULL, + NULL, + "(Z)V", + "(B)V", + "(C)V", + "(S)V", + "(I)V", + "(J)V", + "(F)V", + "(D)V", + "()V", + NULL +}; + +static const char *nativeWrapClassAccessorName[PRIMLIB_NUMTYPES] = { + NULL, + NULL, + "booleanValue", + "byteValue", + "charValue", + "shortValue", + "intValue", + "longValue", + "floatValue", + "doubleValue", + NULL, + NULL +}; + +static const char *nativeWrapClassAccessorSig[PRIMLIB_NUMTYPES] = { + NULL, + NULL, + "()Z", + "()B", + "()C", + "()S", + "()I", + "()J", + "()F", + "()D", + NULL, + NULL +}; + + +JNIEXPORT jclass JNICALL +PRIMLIB_GetNativeWrapClass (JNIEnv * env, int reflectType) +{ + return LINK_LinkClass (env, nativeWrapClass[reflectType], + nativeWrapClassName[reflectType]); +} + +static jclass +ActuallyGetNativeTypeClass (JNIEnv * env, int reflectType) +{ + jclass wrapClass; + jfieldID typeField; + + wrapClass = PRIMLIB_GetNativeWrapClass (env, reflectType); + if (wrapClass == NULL) + return NULL; + typeField = + (*env)->GetStaticFieldID (env, wrapClass, "TYPE", "Ljava/lang/Class"); + if (typeField == NULL) + return NULL; + return (*env)->GetStaticObjectField (env, wrapClass, typeField); +} + +JNIEXPORT jclass JNICALL +PRIMLIB_GetNativeTypeClass (JNIEnv * env, int reflectType) +{ + return LINK_LinkKnownClass (env, nativeTypeClass[reflectType], + ActuallyGetNativeTypeClass (env, reflectType)); +} + +JNIEXPORT jmethodID JNICALL +PRIMLIB_GetNativeWrapClassConstructor (JNIEnv * env, int reflectType) +{ + PRIMLIB_GetNativeWrapClass (env, reflectType); + return LINK_LinkConstructor (env, nativeWrapClassConstructor[reflectType], + nativeWrapClass[reflectType], + nativeWrapClassConstructorSig[reflectType]); +} + +JNIEXPORT jmethodID JNICALL +PRIMLIB_GetNativeWrapClassAccessor (JNIEnv * env, int reflectType) +{ + PRIMLIB_GetNativeWrapClass (env, reflectType); + return LINK_LinkMethod (env, nativeWrapClassAccessor[reflectType], + nativeWrapClass[reflectType], + nativeWrapClassAccessorName[reflectType], + nativeWrapClassAccessorSig[reflectType]); +} + + + +JNIEXPORT jobject JNICALL +PRIMLIB_WrapBoolean (JNIEnv * env, jboolean b) +{ + jmethodID construct = + PRIMLIB_GetNativeWrapClassConstructor (env, PRIMLIB_BOOLEAN); + JCL_RETHROW_EXCEPTION (env); + return (*env)->NewObject (env, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BOOLEAN), + construct, b); +} + +JNIEXPORT jobject JNICALL +PRIMLIB_WrapByte (JNIEnv * env, jbyte b) +{ + jmethodID construct = + PRIMLIB_GetNativeWrapClassConstructor (env, PRIMLIB_BYTE); + JCL_RETHROW_EXCEPTION (env); + return (*env)->NewObject (env, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BYTE), + construct, b); +} + +JNIEXPORT jobject JNICALL +PRIMLIB_WrapChar (JNIEnv * env, jchar c) +{ + jmethodID construct = + PRIMLIB_GetNativeWrapClassConstructor (env, PRIMLIB_CHAR); + JCL_RETHROW_EXCEPTION (env); + return (*env)->NewObject (env, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_CHAR), + construct, c); +} + +JNIEXPORT jobject JNICALL +PRIMLIB_WrapShort (JNIEnv * env, jshort s) +{ + jmethodID construct = + PRIMLIB_GetNativeWrapClassConstructor (env, PRIMLIB_SHORT); + JCL_RETHROW_EXCEPTION (env); + return (*env)->NewObject (env, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_SHORT), + construct, s); +} + +JNIEXPORT jobject JNICALL +PRIMLIB_WrapInt (JNIEnv * env, jint i) +{ + jmethodID construct = + PRIMLIB_GetNativeWrapClassConstructor (env, PRIMLIB_INT); + JCL_RETHROW_EXCEPTION (env); + return (*env)->NewObject (env, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_INT), + construct, i); +} + +JNIEXPORT jobject JNICALL +PRIMLIB_WrapLong (JNIEnv * env, jlong l) +{ + jmethodID construct = + PRIMLIB_GetNativeWrapClassConstructor (env, PRIMLIB_LONG); + JCL_RETHROW_EXCEPTION (env); + return (*env)->NewObject (env, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_LONG), + construct, l); +} + +JNIEXPORT jobject JNICALL +PRIMLIB_WrapFloat (JNIEnv * env, jfloat f) +{ + jmethodID construct = + PRIMLIB_GetNativeWrapClassConstructor (env, PRIMLIB_FLOAT); + JCL_RETHROW_EXCEPTION (env); + return (*env)->NewObject (env, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_FLOAT), + construct, f); +} + +JNIEXPORT jobject JNICALL +PRIMLIB_WrapDouble (JNIEnv * env, jdouble d) +{ + jmethodID construct = + PRIMLIB_GetNativeWrapClassConstructor (env, PRIMLIB_DOUBLE); + JCL_RETHROW_EXCEPTION (env); + return (*env)->NewObject (env, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_DOUBLE), + construct, d); +} + + +JNIEXPORT jboolean JNICALL +PRIMLIB_UnwrapBoolean (JNIEnv * env, jobject obj) +{ + if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BOOLEAN))) + { + return PRIMLIB_GetBooleanObjectValue (env, obj); + } + else + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Argument not of correct type."); + return JNI_FALSE; + } +} + +JNIEXPORT jbyte JNICALL +PRIMLIB_UnwrapByte (JNIEnv * env, jobject obj) +{ + if ((*env)-> + IsInstanceOf (env, obj, PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BYTE))) + { + return PRIMLIB_GetByteObjectValue (env, obj); + } + else + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Argument not of correct type."); + return 0; + } +} + +JNIEXPORT jshort JNICALL +PRIMLIB_UnwrapShort (JNIEnv * env, jobject obj) +{ + if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_SHORT))) + { + return PRIMLIB_GetShortObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BYTE))) + { + return (jshort) PRIMLIB_GetByteObjectValue (env, obj); + } + else + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Argument not of correct type."); + return 0; + } +} + +JNIEXPORT jchar JNICALL +PRIMLIB_UnwrapChar (JNIEnv * env, jobject obj) +{ + if ((*env)-> + IsInstanceOf (env, obj, PRIMLIB_GetNativeWrapClass (env, PRIMLIB_CHAR))) + { + return PRIMLIB_GetCharObjectValue (env, obj); + } + else + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Argument not of correct type."); + return 0; + } +} + +JNIEXPORT jint JNICALL +PRIMLIB_UnwrapInt (JNIEnv * env, jobject obj) +{ + if ((*env)-> + IsInstanceOf (env, obj, PRIMLIB_GetNativeWrapClass (env, PRIMLIB_INT))) + { + return PRIMLIB_GetIntObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_SHORT))) + { + return (jint) PRIMLIB_GetShortObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_CHAR))) + { + return (jint) PRIMLIB_GetCharObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BYTE))) + { + return (jint) PRIMLIB_GetByteObjectValue (env, obj); + } + else + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Argument not of correct type."); + return 0; + } +} + +JNIEXPORT jlong JNICALL +PRIMLIB_UnwrapLong (JNIEnv * env, jobject obj) +{ + if ((*env)-> + IsInstanceOf (env, obj, PRIMLIB_GetNativeWrapClass (env, PRIMLIB_LONG))) + { + return PRIMLIB_GetLongObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_INT))) + { + return (jlong) PRIMLIB_GetIntObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_SHORT))) + { + return (jlong) PRIMLIB_GetShortObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_CHAR))) + { + return (jlong) PRIMLIB_GetCharObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BYTE))) + { + return (jlong) PRIMLIB_GetByteObjectValue (env, obj); + } + else + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Argument not of correct type."); + return 0; + } +} + +JNIEXPORT jfloat JNICALL +PRIMLIB_UnwrapFloat (JNIEnv * env, jobject obj) +{ + if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_FLOAT))) + { + return PRIMLIB_GetFloatObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_LONG))) + { + return (jfloat) PRIMLIB_GetLongObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_INT))) + { + return (jfloat) PRIMLIB_GetIntObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_SHORT))) + { + return (jfloat) PRIMLIB_GetShortObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_CHAR))) + { + return (jfloat) PRIMLIB_GetCharObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BYTE))) + { + return (jfloat) PRIMLIB_GetByteObjectValue (env, obj); + } + else + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Argument not of correct type."); + return 0; + } +} + +JNIEXPORT jdouble JNICALL +PRIMLIB_UnwrapDouble (JNIEnv * env, jobject obj) +{ + if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_DOUBLE))) + { + return PRIMLIB_GetDoubleObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_FLOAT))) + { + return (jdouble) PRIMLIB_GetFloatObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_LONG))) + { + return (jdouble) PRIMLIB_GetLongObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_INT))) + { + return (jdouble) PRIMLIB_GetIntObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_SHORT))) + { + return (jdouble) PRIMLIB_GetShortObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_CHAR))) + { + return (jdouble) PRIMLIB_GetCharObjectValue (env, obj); + } + else if ((*env)-> + IsInstanceOf (env, obj, + PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BYTE))) + { + return (jdouble) PRIMLIB_GetByteObjectValue (env, obj); + } + else + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Argument not of correct type."); + return 0; + } +} + +JNIEXPORT jint JNICALL +PRIMLIB_GetReflectiveWrapperType (JNIEnv * env, jobject obj) +{ + jclass typeClass; + if (obj == NULL) + { + return PRIMLIB_NULL; + } + + typeClass = PRIMLIB_GetNativeWrapClass (env, PRIMLIB_DOUBLE); + if ((*env)->IsInstanceOf (env, obj, typeClass)) + { + return PRIMLIB_DOUBLE; + } + typeClass = PRIMLIB_GetNativeWrapClass (env, PRIMLIB_FLOAT); + if ((*env)->IsInstanceOf (env, obj, typeClass)) + { + return PRIMLIB_FLOAT; + } + typeClass = PRIMLIB_GetNativeWrapClass (env, PRIMLIB_LONG); + if ((*env)->IsInstanceOf (env, obj, typeClass)) + { + return PRIMLIB_LONG; + } + typeClass = PRIMLIB_GetNativeWrapClass (env, PRIMLIB_INT); + if ((*env)->IsInstanceOf (env, obj, typeClass)) + { + return PRIMLIB_INT; + } + typeClass = PRIMLIB_GetNativeWrapClass (env, PRIMLIB_CHAR); + if ((*env)->IsInstanceOf (env, obj, typeClass)) + { + return PRIMLIB_CHAR; + } + typeClass = PRIMLIB_GetNativeWrapClass (env, PRIMLIB_SHORT); + if ((*env)->IsInstanceOf (env, obj, typeClass)) + { + return PRIMLIB_SHORT; + } + typeClass = PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BYTE); + if ((*env)->IsInstanceOf (env, obj, typeClass)) + { + return PRIMLIB_BYTE; + } + typeClass = PRIMLIB_GetNativeWrapClass (env, PRIMLIB_BOOLEAN); + if ((*env)->IsInstanceOf (env, obj, typeClass)) + { + return PRIMLIB_BOOLEAN; + } + typeClass = PRIMLIB_GetNativeWrapClass (env, PRIMLIB_VOID); + if ((*env)->IsInstanceOf (env, obj, typeClass)) + { + return PRIMLIB_VOID; + } + return PRIMLIB_OBJECT; +} + +JNIEXPORT jint JNICALL +PRIMLIB_GetReflectiveType (JNIEnv * env, jclass returnType) +{ + jclass typeClass = PRIMLIB_GetNativeTypeClass (env, PRIMLIB_DOUBLE); + if ((*env)->IsAssignableFrom (env, returnType, typeClass)) + { + return PRIMLIB_DOUBLE; + } + typeClass = PRIMLIB_GetNativeTypeClass (env, PRIMLIB_FLOAT); + if ((*env)->IsAssignableFrom (env, returnType, typeClass)) + { + return PRIMLIB_FLOAT; + } + typeClass = PRIMLIB_GetNativeTypeClass (env, PRIMLIB_LONG); + if ((*env)->IsAssignableFrom (env, returnType, typeClass)) + { + return PRIMLIB_LONG; + } + typeClass = PRIMLIB_GetNativeTypeClass (env, PRIMLIB_INT); + if ((*env)->IsAssignableFrom (env, returnType, typeClass)) + { + return PRIMLIB_INT; + } + typeClass = PRIMLIB_GetNativeTypeClass (env, PRIMLIB_CHAR); + if ((*env)->IsAssignableFrom (env, returnType, typeClass)) + { + return PRIMLIB_CHAR; + } + typeClass = PRIMLIB_GetNativeTypeClass (env, PRIMLIB_SHORT); + if ((*env)->IsAssignableFrom (env, returnType, typeClass)) + { + return PRIMLIB_SHORT; + } + typeClass = PRIMLIB_GetNativeTypeClass (env, PRIMLIB_BYTE); + if ((*env)->IsAssignableFrom (env, returnType, typeClass)) + { + return PRIMLIB_BYTE; + } + typeClass = PRIMLIB_GetNativeTypeClass (env, PRIMLIB_BOOLEAN); + if ((*env)->IsAssignableFrom (env, returnType, typeClass)) + { + return PRIMLIB_BOOLEAN; + } + typeClass = PRIMLIB_GetNativeTypeClass (env, PRIMLIB_VOID); + if ((*env)->IsAssignableFrom (env, returnType, typeClass)) + { + return PRIMLIB_VOID; + } + return PRIMLIB_OBJECT; +} + + +JNIEXPORT jboolean JNICALL +PRIMLIB_GetBooleanObjectValue (JNIEnv * env, jobject obj) +{ + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor (env, PRIMLIB_BOOLEAN); + return (*env)->CallBooleanMethod (env, obj, acc); +} + +JNIEXPORT jbyte JNICALL +PRIMLIB_GetByteObjectValue (JNIEnv * env, jobject obj) +{ + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor (env, PRIMLIB_BYTE); + return (*env)->CallByteMethod (env, obj, acc); +} + +JNIEXPORT jshort JNICALL +PRIMLIB_GetShortObjectValue (JNIEnv * env, jobject obj) +{ + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor (env, PRIMLIB_SHORT); + return (*env)->CallShortMethod (env, obj, acc); +} + +JNIEXPORT jchar JNICALL +PRIMLIB_GetCharObjectValue (JNIEnv * env, jobject obj) +{ + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor (env, PRIMLIB_CHAR); + return (*env)->CallCharMethod (env, obj, acc); +} + +JNIEXPORT jint JNICALL +PRIMLIB_GetIntObjectValue (JNIEnv * env, jobject obj) +{ + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor (env, PRIMLIB_INT); + return (*env)->CallIntMethod (env, obj, acc); +} + +JNIEXPORT jlong JNICALL +PRIMLIB_GetLongObjectValue (JNIEnv * env, jobject obj) +{ + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor (env, PRIMLIB_LONG); + return (*env)->CallLongMethod (env, obj, acc); +} + +JNIEXPORT jfloat JNICALL +PRIMLIB_GetFloatObjectValue (JNIEnv * env, jobject obj) +{ + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor (env, PRIMLIB_FLOAT); + return (*env)->CallFloatMethod (env, obj, acc); +} + +JNIEXPORT jdouble JNICALL +PRIMLIB_GetDoubleObjectValue (JNIEnv * env, jobject obj) +{ + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor (env, PRIMLIB_DOUBLE); + return (*env)->CallDoubleMethod (env, obj, acc); +} + + + +JNIEXPORT jvalue JNICALL +PRIMLIB_UnwrapJValue (JNIEnv * env, jobject obj, jclass classType) +{ + jvalue retval; + jint objType = PRIMLIB_GetReflectiveType (env, classType); + if (objType == PRIMLIB_BOOLEAN) + { + retval.z = PRIMLIB_UnwrapBoolean (env, obj); + } + else if (objType == PRIMLIB_BYTE) + { + retval.b = PRIMLIB_UnwrapByte (env, obj); + } + else if (objType == PRIMLIB_CHAR) + { + retval.c = PRIMLIB_UnwrapChar (env, obj); + } + else if (objType == PRIMLIB_SHORT) + { + retval.s = PRIMLIB_UnwrapShort (env, obj); + } + else if (objType == PRIMLIB_INT) + { + retval.i = PRIMLIB_UnwrapInt (env, obj); + } + else if (objType == PRIMLIB_LONG) + { + retval.j = PRIMLIB_UnwrapLong (env, obj); + } + else if (objType == PRIMLIB_FLOAT) + { + retval.f = PRIMLIB_UnwrapFloat (env, obj); + } + else if (objType == PRIMLIB_DOUBLE) + { + retval.d = PRIMLIB_UnwrapDouble (env, obj); + } + else + { + if (obj != NULL && !(*env)->IsInstanceOf (env, obj, classType)) + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Argument not of correct object type."); + return retval; + } + retval.l = obj; + } + return retval; +} diff --git a/libjava/classpath/native/jni/classpath/primlib.h b/libjava/classpath/native/jni/classpath/primlib.h new file mode 100644 index 00000000000..3cdaaa4a148 --- /dev/null +++ b/libjava/classpath/native/jni/classpath/primlib.h @@ -0,0 +1,119 @@ +/* primlib.h + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef __PRIMLIB_H__ +#define __PRIMLIB_H__ + +#include <jni.h> + +#define PRIMLIB_UNKNOWN 0 +#define PRIMLIB_OBJECT 1 +#define PRIMLIB_BOOLEAN 2 +#define PRIMLIB_BYTE 3 +#define PRIMLIB_CHAR 4 +#define PRIMLIB_SHORT 5 +#define PRIMLIB_INT 6 +#define PRIMLIB_LONG 7 +#define PRIMLIB_FLOAT 8 +#define PRIMLIB_DOUBLE 9 +#define PRIMLIB_VOID 10 +#define PRIMLIB_NULL 11 +#define PRIMLIB_NUMTYPES 12 + +/* Low-level primitive class accessor functions. */ +JNIEXPORT jclass JNICALL PRIMLIB_GetNativeWrapClass (JNIEnv * env, + int reflectType); +JNIEXPORT jclass JNICALL PRIMLIB_GetNativeTypeClass (JNIEnv * env, + int reflectType); +JNIEXPORT jmethodID JNICALL PRIMLIB_GetNativeWrapClassConstructor (JNIEnv * + env, + int + reflectType); +JNIEXPORT jmethodID JNICALL PRIMLIB_GetNativeWrapClassAccessor (JNIEnv * env, + int + reflectType); + +/* Type discovery functions: WrapperType finds out j.l.Boolean/Byte/etc., and + Type finds out j.l.Boolean.TYPE, etc. +*/ +JNIEXPORT jint JNICALL PRIMLIB_GetReflectiveWrapperType (JNIEnv * env, + jobject obj); +JNIEXPORT jint JNICALL PRIMLIB_GetReflectiveType (JNIEnv * env, + jclass returnType); + +/* Constructor functions. */ +JNIEXPORT jobject JNICALL PRIMLIB_WrapBoolean (JNIEnv * env, jboolean b); +JNIEXPORT jobject JNICALL PRIMLIB_WrapByte (JNIEnv * env, jbyte b); +JNIEXPORT jobject JNICALL PRIMLIB_WrapChar (JNIEnv * env, jchar c); +JNIEXPORT jobject JNICALL PRIMLIB_WrapShort (JNIEnv * env, jshort s); +JNIEXPORT jobject JNICALL PRIMLIB_WrapInt (JNIEnv * env, jint i); +JNIEXPORT jobject JNICALL PRIMLIB_WrapLong (JNIEnv * env, jlong l); +JNIEXPORT jobject JNICALL PRIMLIB_WrapFloat (JNIEnv * env, jfloat f); +JNIEXPORT jobject JNICALL PRIMLIB_WrapDouble (JNIEnv * env, jdouble d); + +/* Widening conversion unwrapping functions. */ +JNIEXPORT jboolean JNICALL PRIMLIB_UnwrapBoolean (JNIEnv * env, jobject obj); +JNIEXPORT jbyte JNICALL PRIMLIB_UnwrapByte (JNIEnv * env, jobject obj); +JNIEXPORT jshort JNICALL PRIMLIB_UnwrapShort (JNIEnv * env, jobject obj); +JNIEXPORT jchar JNICALL PRIMLIB_UnwrapChar (JNIEnv * env, jobject obj); +JNIEXPORT jint JNICALL PRIMLIB_UnwrapInt (JNIEnv * env, jobject obj); +JNIEXPORT jlong JNICALL PRIMLIB_UnwrapLong (JNIEnv * env, jobject obj); +JNIEXPORT jfloat JNICALL PRIMLIB_UnwrapFloat (JNIEnv * env, jobject obj); +JNIEXPORT jdouble JNICALL PRIMLIB_UnwrapDouble (JNIEnv * env, jobject obj); + +/* Simple unwrapping functions. Objects *must* be of correct type. */ +JNIEXPORT jboolean JNICALL PRIMLIB_GetBooleanObjectValue (JNIEnv * env, + jobject obj); +JNIEXPORT jbyte JNICALL PRIMLIB_GetByteObjectValue (JNIEnv * env, + jobject obj); +JNIEXPORT jshort JNICALL PRIMLIB_GetShortObjectValue (JNIEnv * env, + jobject obj); +JNIEXPORT jchar JNICALL PRIMLIB_GetCharObjectValue (JNIEnv * env, + jobject obj); +JNIEXPORT jint JNICALL PRIMLIB_GetIntObjectValue (JNIEnv * env, jobject obj); +JNIEXPORT jlong JNICALL PRIMLIB_GetLongObjectValue (JNIEnv * env, + jobject obj); +JNIEXPORT jfloat JNICALL PRIMLIB_GetFloatObjectValue (JNIEnv * env, + jobject obj); +JNIEXPORT jdouble JNICALL PRIMLIB_GetDoubleObjectValue (JNIEnv * env, + jobject obj); + +/* jvalue conversion: Unwrap obj to the type of classType, with widening conversion. */ +JNIEXPORT jvalue JNICALL PRIMLIB_UnwrapJValue (JNIEnv * env, jobject obj, + jclass classType); + +#endif diff --git a/libjava/classpath/native/jni/gtk-peer/.cvsignore b/libjava/classpath/native/jni/gtk-peer/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/gtk-peer/Makefile.am b/libjava/classpath/native/jni/gtk-peer/Makefile.am new file mode 100644 index 00000000000..f4e7bdfcce1 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/Makefile.am @@ -0,0 +1,61 @@ +pkglib_LTLIBRARIES = libgtkpeer.la + +# Gtk/Cairo JNI sources. +if GTK_CAIRO + gtk_cairo_c_source_files = \ + gnu_java_awt_peer_gtk_GdkGraphics2D.c +else + gtk_cairo_c_source_files = +endif + +libgtkpeer_la_SOURCES = $(gtk_cairo_c_source_files) \ + gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c \ + gnu_java_awt_peer_gtk_GdkFontPeer.c \ + gnu_java_awt_peer_gtk_GdkGraphics.c \ + gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c \ + gnu_java_awt_peer_gtk_GdkPixbufDecoder.c \ + gnu_java_awt_peer_gtk_GdkRobotPeer.c \ + gnu_java_awt_peer_gtk_GdkTextLayout.c \ + gnu_java_awt_peer_gtk_GtkButtonPeer.c \ + gnu_java_awt_peer_gtk_GtkCanvasPeer.c \ + gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c \ + gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer.c \ + gnu_java_awt_peer_gtk_GtkCheckboxPeer.c \ + gnu_java_awt_peer_gtk_GtkChoicePeer.c \ + gnu_java_awt_peer_gtk_GtkClipboard.c \ + gnu_java_awt_peer_gtk_GtkComponentPeer.c \ + gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer.c \ + gnu_java_awt_peer_gtk_GtkFileDialogPeer.c \ + gnu_java_awt_peer_gtk_GtkFramePeer.c \ + gnu_java_awt_peer_gtk_GtkGenericPeer.c \ + gnu_java_awt_peer_gtk_GtkImage.c \ + gnu_java_awt_peer_gtk_GtkLabelPeer.c \ + gnu_java_awt_peer_gtk_GtkListPeer.c \ + gnu_java_awt_peer_gtk_GtkMenuBarPeer.c \ + gnu_java_awt_peer_gtk_GtkMenuComponentPeer.c \ + gnu_java_awt_peer_gtk_GtkMenuItemPeer.c \ + gnu_java_awt_peer_gtk_GtkMenuPeer.c \ + gnu_java_awt_peer_gtk_GtkPanelPeer.c \ + gnu_java_awt_peer_gtk_GtkPopupMenuPeer.c \ + gnu_java_awt_peer_gtk_GtkScrollbarPeer.c \ + gnu_java_awt_peer_gtk_GtkScrollPanePeer.c \ + gnu_java_awt_peer_gtk_GtkTextAreaPeer.c \ + gnu_java_awt_peer_gtk_GtkTextFieldPeer.c \ + gnu_java_awt_peer_gtk_GtkToolkit.c \ + gnu_java_awt_peer_gtk_GtkWindowPeer.c \ + gthread-jni.c \ + gdkfont.h \ + gthread-jni.h \ + gtkcairopeer.h \ + gtkpeer.h + +libgtkpeer_la_LIBADD = $(top_builddir)/native/jni/classpath/native_state.lo \ + $(top_builddir)/native/jni/classpath/jcl.lo + +AM_LDFLAGS = @CLASSPATH_MODULE@ @GTK_LIBS@ @CAIRO_LIBS@ @PANGOFT2_LIBS@ @X_LIBS@ -lXtst +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ + +# Just the WARNING_CFLAGS. We cannot use the strict flags since the gtk +# headers contain broken prototypes (by design, see gtkitemfactory.h). +AM_CFLAGS = @WARNING_CFLAGS@ @ERROR_CFLAGS@ \ + @GTK_CFLAGS@ @CAIRO_CFLAGS@ @PANGOFT2_CFLAGS@ diff --git a/libjava/classpath/native/jni/gtk-peer/gdkfont.h b/libjava/classpath/native/jni/gtk-peer/gdkfont.h new file mode 100644 index 00000000000..cf233301547 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gdkfont.h @@ -0,0 +1,142 @@ +#ifndef __GDKFONT_H__ +#define __GDKFONT_H__ + +/* gdkfont.h -- Some global stuff related to fonts and glyphs + Copyright (C) 2003 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath 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, or (at your option) + any later version. + + GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + 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. */ + +#include "gtkpeer.h" + +#include <pango/pango.h> +#include <pango/pango-context.h> +#include <pango/pango-fontmap.h> +#include <pango/pangoft2.h> + +extern struct state_table *cp_gtk_native_font_state_table; +extern struct state_table *native_glyphvector_state_table; +extern struct state_table *cp_gtk_native_text_layout_state_table; + +#define NSA_FONT_INIT(env, clazz) \ + cp_gtk_native_font_state_table = cp_gtk_init_state_table (env, clazz) + +#define NSA_GET_FONT_PTR(env, obj) \ + cp_gtk_get_state (env, obj, cp_gtk_native_font_state_table) + +#define NSA_SET_FONT_PTR(env, obj, ptr) \ + cp_gtk_set_state (env, obj, cp_gtk_native_font_state_table, (void *)ptr) + +#define NSA_DEL_FONT_PTR(env, obj) \ + cp_gtk_remove_state_slot (env, obj, cp_gtk_native_font_state_table) + + +#define NSA_GV_INIT(env, clazz) \ + native_glyphvector_state_table = cp_gtk_init_state_table (env, clazz) + +#define NSA_GET_GV_PTR(env, obj) \ + cp_gtk_get_state (env, obj, native_glyphvector_state_table) + +#define NSA_SET_GV_PTR(env, obj, ptr) \ + cp_gtk_set_state (env, obj, native_glyphvector_state_table, (void *)ptr) + +#define NSA_DEL_GV_PTR(env, obj) \ + cp_gtk_remove_state_slot (env, obj, native_glyphvector_state_table) + + +#define NSA_TEXT_LAYOUT_INIT(env, clazz) \ + cp_gtk_native_text_layout_state_table = cp_gtk_init_state_table (env, clazz) + +#define NSA_GET_TEXT_LAYOUT_PTR(env, obj) \ + cp_gtk_get_state (env, obj, cp_gtk_native_text_layout_state_table) + +#define NSA_SET_TEXT_LAYOUT_PTR(env, obj, ptr) \ + cp_gtk_set_state (env, obj, cp_gtk_native_text_layout_state_table, (void *)ptr) + +#define NSA_DEL_TEXT_LAYOUT_PTR(env, obj) \ + cp_gtk_remove_state_slot (env, obj, cp_gtk_native_text_layout_state_table) + +#define FONT_METRICS_ASCENT 0 +#define FONT_METRICS_MAX_ASCENT 1 +#define FONT_METRICS_DESCENT 2 +#define FONT_METRICS_MAX_DESCENT 3 +#define FONT_METRICS_MAX_ADVANCE 4 +#define NUM_FONT_METRICS 5 + +#define TEXT_METRICS_X_BEARING 0 +#define TEXT_METRICS_Y_BEARING 1 +#define TEXT_METRICS_WIDTH 2 +#define TEXT_METRICS_HEIGHT 3 +#define TEXT_METRICS_X_ADVANCE 4 +#define TEXT_METRICS_Y_ADVANCE 5 +#define NUM_TEXT_METRICS 6 + +#define NUM_GLYPH_METRICS 10 + +#define GLYPH_LOG_X(i) (NUM_GLYPH_METRICS * (i) ) +#define GLYPH_LOG_Y(i) (NUM_GLYPH_METRICS * (i) + 1) +#define GLYPH_LOG_WIDTH(i) (NUM_GLYPH_METRICS * (i) + 2) +#define GLYPH_LOG_HEIGHT(i) (NUM_GLYPH_METRICS * (i) + 3) + +#define GLYPH_INK_X(i) (NUM_GLYPH_METRICS * (i) + 4) +#define GLYPH_INK_Y(i) (NUM_GLYPH_METRICS * (i) + 5) +#define GLYPH_INK_WIDTH(i) (NUM_GLYPH_METRICS * (i) + 6) +#define GLYPH_INK_HEIGHT(i) (NUM_GLYPH_METRICS * (i) + 7) + +#define GLYPH_POS_X(i) (NUM_GLYPH_METRICS * (i) + 8) +#define GLYPH_POS_Y(i) (NUM_GLYPH_METRICS * (i) + 9) + +struct peerfont +{ + PangoFont *font; + PangoFontDescription *desc; + PangoContext *ctx; + PangoLayout *layout; + /* + * The GdkGraphics2D (using cairo) may store a pointer to a + * cairo_font_t here; since we want to work equally well with + * the GdkGraphics class (using GDK) we do not explicitly mention + * cairo types here; it is up to the higher level driver routine + * in GdkClasspathFontPeer.java to decide which backend functions + * to invoke. + */ + void *graphics_resource; +}; + +struct textlayout +{ + PangoLayout *pango_layout; +}; + +#endif /* __GDKFONT_H__ */ diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c new file mode 100644 index 00000000000..595c1a28a6e --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c @@ -0,0 +1,70 @@ +/* Native implementation of functions in GThreadNativeMethodRunner + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h" +#include "gthread-jni.h" + +/* + * Class: GThreadNativeMethodRunner + * Method: nativeRun + * Signature: (J)V + * + * Purpose: Run the C function whose function pointer is + * + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_nativeRun + (JNIEnv *env __attribute__((unused)), + jobject lcl_obj __attribute__((unused)), + jlong funcAddr, jlong funcArg) +{ + /* Convert the function's address back into a pointer to a C function. */ + void *(*funcPtr)(void *) = (void *(*)(void *)) (size_t)funcAddr; + + /* We do not need to worry about the return value from funcPtr(); it's + just thrown away. That is part of the g_threads spec, so no reason + to worry about returning it. */ + (void) funcPtr((void *) (size_t)funcArg); + /* Fall off the end and terminate the thread of control. */ +} + +/* Local Variables: */ +/* c-file-style: "gnu" */ +/* End: */ + + diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c new file mode 100644 index 00000000000..401d62337b3 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c @@ -0,0 +1,418 @@ +/* gnu_java_awt_GdkFont.c + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath 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, or (at your option) + any later version. + + GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + 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. */ + +#include "gdkfont.h" +#include "gnu_java_awt_peer_gtk_GdkFontPeer.h" + +struct state_table *cp_gtk_native_font_state_table; + +enum java_awt_font_style { + java_awt_font_PLAIN = 0, + java_awt_font_BOLD = 1, + java_awt_font_ITALIC = 2 +}; + +enum java_awt_font_baseline { + java_awt_font_ROMAN_BASELINE = 0, + java_awt_font_CENTER_BASELINE = 1, + java_awt_font_HANGING_BASELINE = 2 +}; + +static jmethodID glyphVector_ctor; +static jclass glyphVector_class; +static PangoAttrList *attrs = NULL; + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_initStaticState + (JNIEnv *env, jclass clazz) +{ + NSA_FONT_INIT (env, clazz); + + glyphVector_class = (*env)->FindClass + (env, "gnu/java/awt/peer/gtk/GdkGlyphVector"); + + glyphVector_ctor = (*env)->GetMethodID + (env, glyphVector_class, "<init>", + "([D[ILjava/awt/Font;Ljava/awt/font/FontRenderContext;)V"); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_initState + (JNIEnv *env, jobject self) +{ + struct peerfont *pfont = NULL; + + gdk_threads_enter (); + + g_assert (self != NULL); + pfont = (struct peerfont *) g_malloc0 (sizeof (struct peerfont)); + g_assert (pfont != NULL); + NSA_SET_FONT_PTR (env, self, pfont); + + gdk_threads_leave (); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_dispose + (JNIEnv *env, jobject self) +{ + struct peerfont *pfont = NULL; + + gdk_threads_enter (); + + pfont = (struct peerfont *)NSA_DEL_FONT_PTR (env, self); + g_assert (pfont != NULL); + if (pfont->layout != NULL) + g_object_unref (pfont->font); + if (pfont->font != NULL) + g_object_unref (pfont->font); + if (pfont->ctx != NULL) + g_object_unref (pfont->ctx); + if (pfont->desc != NULL) + pango_font_description_free (pfont->desc); + g_free (pfont); + + gdk_threads_leave (); +} + + +JNIEXPORT jobject JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector + (JNIEnv *env, jobject self, + jstring chars, + jobject font, + jobject fontRenderContext) +{ + struct peerfont *pfont = NULL; + GList *items = NULL; + GList *i = NULL; + gchar *str = NULL; + int len = 0; + int j = 0; + double *native_extents = NULL; + int *native_codes = NULL; + jintArray java_codes = NULL; + jdoubleArray java_extents = NULL; + + gdk_threads_enter (); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self); + g_assert (pfont != NULL); + + len = (*cp_gtk_gdk_env())->GetStringUTFLength (env, chars); + str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL); + g_assert (str != NULL); + + if (attrs == NULL) + attrs = pango_attr_list_new (); + + if (len > 0 && str[len-1] == '\0') + len--; + + items = pango_itemize (pfont->ctx, str, 0, len, attrs, NULL); + + i = g_list_first (items); + + if (i == NULL) + { + gdk_threads_leave (); + + java_extents = (*env)->NewDoubleArray (env, 0); + java_codes = (*env)->NewIntArray (env, 0); + + gdk_threads_enter (); + } + else + { + PangoGlyphString *glyphs; + PangoItem *item = (PangoItem *)i->data; + + pango_context_set_font_description (pfont->ctx, pfont->desc); + pango_context_set_language (pfont->ctx, gtk_get_default_language()); + pango_context_load_font (pfont->ctx, pfont->desc); + + glyphs = pango_glyph_string_new (); + g_assert (glyphs != NULL); + + pango_shape (str + item->offset, item->length, + &(item->analysis), glyphs); + + if (glyphs->num_glyphs > 0) + { + int x = 0; + double scale = ((double) PANGO_SCALE); + + gdk_threads_leave (); + + java_extents = (*env)->NewDoubleArray (env, glyphs->num_glyphs * NUM_GLYPH_METRICS); + java_codes = (*env)->NewIntArray (env, glyphs->num_glyphs); + + gdk_threads_enter (); + + native_extents = (*env)->GetDoubleArrayElements (env, java_extents, NULL); + native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); + + for (j = 0; j < glyphs->num_glyphs; ++j) + { + PangoRectangle ink; + PangoRectangle logical; + PangoGlyphGeometry *geom = &glyphs->glyphs[j].geometry; + + pango_font_get_glyph_extents (pfont->font, + glyphs->glyphs[j].glyph, + &ink, &logical); + + native_codes[j] = glyphs->glyphs[j].glyph; + + native_extents[ GLYPH_LOG_X(j) ] = (logical.x) / scale; + native_extents[ GLYPH_LOG_Y(j) ] = (- logical.y) / scale; + native_extents[ GLYPH_LOG_WIDTH(j) ] = (logical.width) / scale; + native_extents[ GLYPH_LOG_HEIGHT(j) ] = (logical.height) / scale; + + native_extents[ GLYPH_INK_X(j) ] = (ink.x) / scale; + native_extents[ GLYPH_INK_Y(j) ] = (- ink.y) / scale; + native_extents[ GLYPH_INK_WIDTH(j) ] = (ink.width) / scale; + native_extents[ GLYPH_INK_HEIGHT(j) ] = (ink.height) / scale; + + native_extents[ GLYPH_POS_X(j) ] = (x + geom->x_offset) / scale; + native_extents[ GLYPH_POS_Y(j) ] = ( - geom->y_offset) / scale; + + x += geom->width; + } + (*env)->ReleaseDoubleArrayElements (env, java_extents, native_extents, 0); + (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); + } + + pango_glyph_string_free (glyphs); + } + + (*env)->ReleaseStringUTFChars (env, chars, str); + + for (i = g_list_first (items); i != NULL; i = g_list_next (i)) + g_free (i->data); + + g_list_free (items); + + gdk_threads_leave (); + + return (*env)->NewObject (env, + glyphVector_class, + glyphVector_ctor, + java_extents, java_codes, + font, fontRenderContext); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics + (JNIEnv *env, jobject java_font, jdoubleArray java_metrics) +{ + struct peerfont *pfont = NULL; + jdouble *native_metrics = NULL; + PangoFontMetrics *pango_metrics = NULL; + + gdk_threads_enter(); + + pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); + g_assert (pfont != NULL); + + pango_metrics + = pango_context_get_metrics (pfont->ctx, pfont->desc, + gtk_get_default_language ()); + + native_metrics + = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); + + g_assert (native_metrics != NULL); + + native_metrics[FONT_METRICS_ASCENT] + = PANGO_PIXELS (pango_font_metrics_get_ascent (pango_metrics)); + + native_metrics[FONT_METRICS_MAX_ASCENT] + = native_metrics[FONT_METRICS_ASCENT]; + + native_metrics[FONT_METRICS_DESCENT] + = PANGO_PIXELS (pango_font_metrics_get_descent (pango_metrics)); + + if (native_metrics[FONT_METRICS_DESCENT] < 0) + native_metrics[FONT_METRICS_DESCENT] + = - native_metrics[FONT_METRICS_DESCENT]; + + native_metrics[FONT_METRICS_MAX_DESCENT] + = native_metrics[FONT_METRICS_DESCENT]; + + native_metrics[FONT_METRICS_MAX_ADVANCE] + = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width + (pango_metrics)); + + (*env)->ReleaseDoubleArrayElements (env, + java_metrics, + native_metrics, 0); + + pango_font_metrics_unref (pango_metrics); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics + (JNIEnv *env, jobject java_font, jstring str, jdoubleArray java_metrics) +{ + struct peerfont *pfont = NULL; + const char *cstr = NULL; + jdouble *native_metrics = NULL; + PangoRectangle log; + + gdk_threads_enter(); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, java_font); + g_assert (pfont != NULL); + + cstr = (*env)->GetStringUTFChars (env, str, NULL); + g_assert(cstr != NULL); + + pango_layout_set_text (pfont->layout, cstr, -1); + pango_layout_get_extents (pfont->layout, NULL, &log); + + (*env)->ReleaseStringUTFChars (env, str, cstr); + pango_layout_set_text (pfont->layout, "", -1); + + native_metrics = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); + g_assert (native_metrics != NULL); + + native_metrics[TEXT_METRICS_X_BEARING] + = PANGO_PIXELS( ((double)log.x) ); + + native_metrics[TEXT_METRICS_Y_BEARING] + = PANGO_PIXELS( ((double)log.y) ); + + native_metrics[TEXT_METRICS_WIDTH] + = PANGO_PIXELS( ((double)log.width) ); + + native_metrics[TEXT_METRICS_HEIGHT] + = PANGO_PIXELS( ((double)log.height) ); + + native_metrics[TEXT_METRICS_X_ADVANCE] + = PANGO_PIXELS( ((double) (log.x + log.width)) ); + + native_metrics[TEXT_METRICS_Y_ADVANCE] + = PANGO_PIXELS( ((double) (log.y + log.height)) ); + + (*env)->ReleaseDoubleArrayElements (env, java_metrics, native_metrics, 0); + + gdk_threads_leave(); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont + (JNIEnv *env, jobject self, jstring family_name_str, jint style_int, jint size, jboolean useGraphics2D) +{ + struct peerfont *pfont = NULL; + char const *family_name = NULL; + enum java_awt_font_style style; + PangoFT2FontMap *ft2_map = NULL; + + gdk_threads_enter (); + + style = (enum java_awt_font_style) style_int; + + g_assert (self != NULL); + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self); + g_assert (pfont != NULL); + + if (pfont->ctx != NULL) + g_object_unref (pfont->ctx); + if (pfont->font != NULL) + g_object_unref (pfont->font); + if (pfont->desc != NULL) + pango_font_description_free (pfont->desc); + + pfont->desc = pango_font_description_new (); + g_assert (pfont->desc != NULL); + + family_name = (*env)->GetStringUTFChars(env, family_name_str, 0); + g_assert (family_name != NULL); + pango_font_description_set_family (pfont->desc, family_name); + (*env)->ReleaseStringUTFChars(env, family_name_str, family_name); + + + if (style & java_awt_font_BOLD) + pango_font_description_set_weight (pfont->desc, PANGO_WEIGHT_BOLD); + + if (style & java_awt_font_ITALIC) + pango_font_description_set_style (pfont->desc, PANGO_STYLE_ITALIC); + + if (useGraphics2D) + { + pango_font_description_set_size (pfont->desc, size * PANGO_SCALE); + if (pfont->ctx == NULL) + { + ft2_map = PANGO_FT2_FONT_MAP(pango_ft2_font_map_for_display ()); + pfont->ctx = pango_ft2_font_map_create_context (ft2_map); + } + } + else + { + /* GDK uses a slightly different DPI setting. */ + pango_font_description_set_size (pfont->desc, + size * cp_gtk_dpi_conversion_factor); + if (pfont->ctx == NULL) + pfont->ctx = gdk_pango_context_get(); + } + + g_assert (pfont->ctx != NULL); + + if (pfont->font != NULL) + { + g_object_unref (pfont->font); + pfont->font = NULL; + } + + pango_context_set_font_description (pfont->ctx, pfont->desc); + pango_context_set_language (pfont->ctx, gtk_get_default_language()); + pfont->font = pango_context_load_font (pfont->ctx, pfont->desc); + g_assert (pfont->font != NULL); + + if (pfont->layout == NULL) + pfont->layout = pango_layout_new (pfont->ctx); + g_assert (pfont->layout != NULL); + + gdk_threads_leave (); +} + + diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c new file mode 100644 index 00000000000..9b2f16e7145 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c @@ -0,0 +1,642 @@ +/* gdkgraphics.c + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "gtkpeer.h" +#include "gdkfont.h" +#include "gnu_java_awt_peer_gtk_GdkGraphics.h" +#include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> + +static jmethodID initComponentGraphicsID; + +void +cp_gtk_graphics_init_jni (void) +{ + jclass gdkgraphics; + + gdkgraphics = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GdkGraphics"); + + initComponentGraphicsID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gdkgraphics, + "initComponentGraphics", + "()V"); +} + +#define GDK_STABLE_IS_PIXMAP(d) (GDK_IS_PIXMAP(d)) + +static GdkPoint *translate_points (JNIEnv *env, jintArray xpoints, + jintArray ypoints, jint npoints, + jint x_offset, jint y_offset); +static void realize_cb (GtkWidget *widget, jobject jgraphics); + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_copyState + (JNIEnv *env, jobject obj, jobject old) +{ + struct graphics *g = NULL; + struct graphics *g_old = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) g_malloc (sizeof (struct graphics)); + g_old = (struct graphics *) NSA_GET_PTR (env, old); + + *g = *g_old; + + g->gc = gdk_gc_new (g->drawable); + gdk_gc_copy (g->gc, g_old->gc); + + if (GDK_STABLE_IS_PIXMAP (g->drawable)) + gdk_pixmap_ref (g->drawable); + else /* GDK_IS_WINDOW (g->drawable) */ + gdk_window_ref (g->drawable); + + gdk_colormap_ref (g->cm); + + NSA_SET_PTR (env, obj, g); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_initState__II + (JNIEnv *env, jobject obj, jint width, jint height) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) g_malloc (sizeof (struct graphics)); + g->x_offset = g->y_offset = 0; + + g->drawable = (GdkDrawable *) gdk_pixmap_new (NULL, width, height, + gdk_rgb_get_visual ()->depth); + g->cm = gdk_rgb_get_cmap (); + gdk_colormap_ref (g->cm); + g->gc = gdk_gc_new (g->drawable); + + NSA_SET_PTR (env, obj, g); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_initFromImage + (JNIEnv *env, jobject obj, jobject source) +{ + struct graphics *g = NULL; + GdkPixmap *pixmap = NULL; + + gdk_threads_enter (); + + pixmap = cp_gtk_image_get_pixmap (env, source); + g_assert(pixmap != NULL); + gdk_pixmap_ref (pixmap); + + g = (struct graphics *) g_malloc (sizeof (struct graphics)); + g->x_offset = g->y_offset = 0; + + g->drawable = (GdkDrawable *)pixmap; + + g->cm = gdk_drawable_get_colormap (g->drawable); + gdk_colormap_ref (g->cm); + g->gc = gdk_gc_new (g->drawable); + + NSA_SET_PTR (env, obj, g); + + gdk_threads_leave (); +} + +/* copy the native state of the peer (GtkWidget *) to the native state + of the graphics object */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2 + (JNIEnv *env, jobject obj, jobject peer) +{ + struct graphics *g = NULL; + void *ptr = NULL; + GtkWidget *widget = NULL; + GdkColor color; + + gdk_threads_enter (); + + g = (struct graphics *) g_malloc (sizeof (struct graphics)); + ptr = NSA_GET_PTR (env, peer); + g->x_offset = 0; + g->y_offset = 0; + + widget = GTK_WIDGET (ptr); + g->drawable = (GdkDrawable *) widget->window; + + gdk_window_ref (g->drawable); + g->cm = gtk_widget_get_colormap (widget); + gdk_colormap_ref (g->cm); + g->gc = gdk_gc_new (g->drawable); + gdk_gc_copy (g->gc, widget->style->fg_gc[GTK_STATE_NORMAL]); + color = widget->style->fg[GTK_STATE_NORMAL]; + + NSA_SET_PTR (env, obj, g); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_connectSignals + (JNIEnv *env, jobject obj, jobject peer) +{ + void *ptr = NULL; + jobject *gref = NULL; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + ptr = NSA_GET_PTR (env, peer); + + g_signal_connect_after (G_OBJECT (ptr), "realize", + G_CALLBACK (realize_cb), *gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_dispose + (JNIEnv *env, jobject obj) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_DEL_PTR (env, obj); + + /* check if dispose has been called already */ + if (!g) + { + gdk_threads_leave (); + return; + } + + XFlush (GDK_DISPLAY ()); + + gdk_gc_destroy (g->gc); + + if (GDK_STABLE_IS_PIXMAP (g->drawable)) + gdk_pixmap_unref (g->drawable); + else /* GDK_IS_WINDOW (g->drawable) */ + gdk_window_unref (g->drawable); + + gdk_colormap_unref (g->cm); + + g_free (g); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_translateNative + (JNIEnv *env, jobject obj, jint x, jint y) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + g->x_offset += x; + g->y_offset += y; + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_drawString + (JNIEnv *env, jobject obj, jobject font, jstring str, jint x, jint y) +{ + struct peerfont *pfont = NULL; + struct graphics *g = NULL; + const char *cstr = NULL; + int baseline_y = 0; + PangoLayoutIter *iter = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + g_assert (g != NULL); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); + g_assert (pfont != NULL); + + cstr = (*env)->GetStringUTFChars (env, str, NULL); + + pango_layout_set_font_description (pfont->layout, pfont->desc); + pango_layout_set_text (pfont->layout, cstr, -1); + iter = pango_layout_get_iter (pfont->layout); + + baseline_y = pango_layout_iter_get_baseline (iter); + + gdk_draw_layout (g->drawable, g->gc, + x + g->x_offset, + y + g->y_offset - PANGO_PIXELS (baseline_y), + pfont->layout); + + pango_layout_iter_free (iter); + pango_layout_set_text (pfont->layout, "", -1); + + gdk_flush (); + + (*env)->ReleaseStringUTFChars (env, str, cstr); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_drawLine + (JNIEnv *env, jobject obj, jint x, jint y, jint x2, jint y2) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_draw_line (g->drawable, g->gc, + x + g->x_offset, y + g->y_offset, + x2 + g->x_offset, y2 + g->y_offset); + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_fillRect + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_draw_rectangle (g->drawable, g->gc, TRUE, + x + g->x_offset, y + g->y_offset, width, height); + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_drawRect + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_draw_rectangle (g->drawable, g->gc, FALSE, + x + g->x_offset, y + g->y_offset, width, height); + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_copyArea + (JNIEnv *env, jobject obj, jint x, jint y, + jint width, jint height, jint dx, jint dy) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_window_copy_area ((GdkWindow *)g->drawable, + g->gc, + x + g->x_offset + dx, y + g->y_offset + dy, + (GdkWindow *)g->drawable, + x + g->x_offset, y + g->y_offset, + width, height); + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_clearRect + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + struct graphics *g = NULL; + GdkGCValues saved; + GtkWidget *widget = NULL; + union widget_union w; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + if (!g) + { + gdk_threads_leave (); + return; + } + + if (GDK_IS_WINDOW (g->drawable)) + { + w.widget = &widget; + gdk_window_get_user_data (GDK_WINDOW (g->drawable), w.void_widget); + if (widget == NULL || !GTK_IS_EVENT_BOX (widget)) + gdk_window_clear_area ((GdkWindow *) g->drawable, + x + g->x_offset, y + g->y_offset, + width, height); + } + else + { + gdk_gc_get_values (g->gc, &saved); + gdk_gc_set_foreground (g->gc, &(saved.background)); + gdk_draw_rectangle (g->drawable, g->gc, TRUE, + x + g->x_offset, y + g->y_offset, width, height); + gdk_gc_set_foreground (g->gc, &(saved.foreground)); + } + + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_setFunction + (JNIEnv *env, jobject obj, jint func) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_gc_set_function (g->gc, func); + + gdk_threads_leave (); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_setFGColor + (JNIEnv *env, jobject obj, jint red, jint green, jint blue) +{ + GdkColor color; + struct graphics *g = NULL; + + gdk_threads_enter (); + + color.red = red << 8; + color.green = green << 8; + color.blue = blue << 8; + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_color_alloc (g->cm, &color); + gdk_gc_set_foreground (g->gc, &color); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_drawArc + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height, + jint angle1, jint angle2) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_draw_arc (g->drawable, g->gc, FALSE, + x + g->x_offset, y + g->y_offset, + width, height, angle1 << 6, angle2 << 6); + gdk_flush (); + + gdk_threads_leave (); +} + +static GdkPoint * +translate_points (JNIEnv *env, jintArray xpoints, jintArray ypoints, + jint npoints, jint x_offset, jint y_offset) +{ + GdkPoint *points; + jint *x, *y; + int i; + + /* allocate one more point than necessary, in case we need to tack + on an extra due to the semantics of Java polygons. */ + points = g_malloc (sizeof (GdkPoint) * (npoints + 1)); + + x = (*env)->GetIntArrayElements (env, xpoints, NULL); + y = (*env)->GetIntArrayElements (env, ypoints, NULL); + + for (i = 0; i < npoints; i++) + { + points[i].x = x[i] + x_offset; + points[i].y = y[i] + y_offset; + } + + (*env)->ReleaseIntArrayElements (env, xpoints, x, JNI_ABORT); + (*env)->ReleaseIntArrayElements (env, ypoints, y, JNI_ABORT); + + return points; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_drawPolyline + (JNIEnv *env, jobject obj, jintArray xpoints, jintArray ypoints, + jint npoints) +{ + struct graphics *g = NULL; + GdkPoint *points = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + points = translate_points (env, xpoints, ypoints, npoints, + g->x_offset, g->y_offset); + + gdk_draw_lines (g->drawable, g->gc, points, npoints); + gdk_flush (); + + g_free (points); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_drawPolygon + (JNIEnv *env, jobject obj, jintArray xpoints, jintArray ypoints, + jint npoints) +{ + struct graphics *g = NULL; + GdkPoint *points = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + points = translate_points (env, xpoints, ypoints, npoints, + g->x_offset, g->y_offset); + + /* make sure the polygon is closed, per Java semantics. + if it's not, we close it. */ + if (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y) + points[npoints++] = points[0]; + + gdk_draw_lines (g->drawable, g->gc, points, npoints); + gdk_flush (); + + g_free (points); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_fillPolygon + (JNIEnv *env, jobject obj, jintArray xpoints, jintArray ypoints, + jint npoints) +{ + struct graphics *g = NULL; + GdkPoint *points = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + points = translate_points (env, xpoints, ypoints, npoints, + g->x_offset, g->y_offset); + gdk_draw_polygon (g->drawable, g->gc, TRUE, points, npoints); + gdk_flush (); + + g_free (points); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_fillArc + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height, + jint angle1, jint angle2) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_draw_arc (g->drawable, g->gc, TRUE, + x + g->x_offset, y + g->y_offset, + width, height, angle1 << 6, angle2 << 6); + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_drawOval + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_draw_arc (g->drawable, g->gc, FALSE, + x + g->x_offset, y + g->y_offset, + width, height, 0, 23040); + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_fillOval + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + struct graphics *g = NULL; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + gdk_draw_arc (g->drawable, g->gc, TRUE, + x + g->x_offset, y + g->y_offset, + width, height, 0, 23040); + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics_setClipRectangle + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + struct graphics *g = NULL; + GdkRectangle rectangle; + + gdk_threads_enter (); + + g = (struct graphics *) NSA_GET_PTR (env, obj); + + rectangle.x = x + g->x_offset; + rectangle.y = y + g->y_offset; + rectangle.width = width; + rectangle.height = height; + + gdk_gc_set_clip_rectangle (g->gc, &rectangle); + + gdk_threads_leave (); +} + +static void +realize_cb (GtkWidget *widget __attribute__ ((unused)), jobject jgraphics) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), jgraphics, initComponentGraphicsID); + + NSA_DEL_GLOBAL_REF (cp_gtk_gdk_env(), jgraphics); + + gdk_threads_enter (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c new file mode 100644 index 00000000000..b4bd676e7b9 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c @@ -0,0 +1,1881 @@ +/* gnu_java_awt_peer_gtk_GdkGraphics2d.c + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath 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, or (at your option) + any later version. + + GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + 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. */ + +#include "gtkcairopeer.h" +#include "gdkfont.h" +#include "gnu_java_awt_peer_gtk_GdkGraphics2D.h" +#include <gdk/gdktypes.h> +#include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> +#include <X11/extensions/Xrender.h> + +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdk-pixbuf/gdk-pixdata.h> + +#include <cairo-ft.h> +#include <cairo-xlib.h> + +#include <stdio.h> +#include <stdlib.h> + +static jmethodID initComponentGraphics2DID; + +void +cp_gtk_graphics2d_init_jni (void) +{ + jclass gdkgraphics2d; + + gdkgraphics2d = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GdkGraphics2D"); + + initComponentGraphics2DID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gdkgraphics2d, + "initComponentGraphics2D", + "()V"); +} + +static struct state_table *native_graphics2d_state_table; + +#define NSA_G2D_INIT(env, clazz) \ + native_graphics2d_state_table = cp_gtk_init_state_table (env, clazz) + +#define NSA_GET_G2D_PTR(env, obj) \ + cp_gtk_get_state (env, obj, native_graphics2d_state_table) + +#define NSA_SET_G2D_PTR(env, obj, ptr) \ + cp_gtk_set_state (env, obj, native_graphics2d_state_table, (void *)ptr) + +#define NSA_DEL_G2D_PTR(env, obj) \ + cp_gtk_remove_state_slot (env, obj, native_graphics2d_state_table) + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initStaticState + (JNIEnv *env, jclass clazz) +{ + gdk_threads_enter(); + + NSA_G2D_INIT (env, clazz); + + gdk_threads_leave(); +} + +/* these public final constants are part of the java2d public API, so we + write them explicitly here to save fetching them from the constant pool + all the time. */ + +#ifndef min +#define min(x,y) ((x) < (y) ? (x) : (y)) +#endif + +enum java_awt_alpha_composite_rule + { + java_awt_alpha_composite_CLEAR = 1, + java_awt_alpha_composite_SRC = 2, + java_awt_alpha_composite_SRC_OVER = 3, + java_awt_alpha_composite_DST_OVER = 4, + java_awt_alpha_composite_SRC_IN = 5, + java_awt_alpha_composite_DST_IN = 6, + java_awt_alpha_composite_SRC_OUT = 7, + java_awt_alpha_composite_DST_OUT = 8, + java_awt_alpha_composite_DST = 9, + java_awt_alpha_composite_SRC_ATOP = 10, + java_awt_alpha_composite_DST_ATOP = 11, + java_awt_alpha_composite_XOR = 12 + }; + +enum java_awt_basic_stroke_join_rule + { + java_awt_basic_stroke_JOIN_MITER = 0, + java_awt_basic_stroke_JOIN_ROUND = 1, + java_awt_basic_stroke_JOIN_BEVEL = 2 + }; + +enum java_awt_basic_stroke_cap_rule + { + java_awt_basic_stroke_CAP_BUTT = 0, + java_awt_basic_stroke_CAP_ROUND = 1, + java_awt_basic_stroke_CAP_SQUARE = 2 + }; + +enum java_awt_geom_path_iterator_winding_rule + { + java_awt_geom_path_iterator_WIND_EVEN_ODD = 0, + java_awt_geom_path_iterator_WIND_NON_ZERO = 1 + }; + +enum java_awt_rendering_hints_filter + { + java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR = 0, + java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR = 1, + java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED = 2, + java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY = 3, + java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT = 4 + + }; + +static int +peer_is_disposed(JNIEnv *env, jobject obj) +{ + static jfieldID fid = NULL; + jclass cls; + jobject peer; + + return 0; + + if (fid == NULL) + { + cls = (*env)->GetObjectClass(env, obj); + fid = (*env)->GetFieldID(env, cls, "component", + "Lgnu/java/awt/peer/gtk/GtkComponentPeer;"); + } + g_assert(fid != NULL); + peer = (*env)->GetObjectField(env, obj, fid); + if (peer == NULL || NSA_GET_PTR (env, peer) != NULL) + return 0; + else + { + return 1; + } +} + + +static void +grab_current_drawable (GtkWidget *widget, GdkDrawable **draw, GdkWindow **win) +{ + g_assert (widget != NULL); + g_assert (draw != NULL); + g_assert (win != NULL); + + *win = widget->window; + + *draw = *win; + gdk_window_get_internal_paint_info (*win, draw, 0, 0); + g_object_ref (*draw); +} + + +static int +x_server_has_render_extension (void) +{ + int ev = 0, err = 0; + return (int) XRenderQueryExtension (GDK_DISPLAY (), &ev, &err); +} + +static void +init_graphics2d_as_pixbuf (struct graphics2d *gr) +{ + gint width, height; + gint bits_per_sample = 8; + gint total_channels = 4; + gboolean has_alpha = TRUE; + + g_assert (gr != NULL); + g_assert (gr->drawable != NULL); + + if (gr->debug) printf ("initializing graphics2d as pixbuf\n"); + gdk_drawable_get_size (gr->drawable, &width, &height); + gr->drawbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + has_alpha, bits_per_sample, + width, height); + g_assert (gr->drawbuf != NULL); + g_assert (gdk_pixbuf_get_bits_per_sample (gr->drawbuf) == bits_per_sample); + g_assert (gdk_pixbuf_get_n_channels (gr->drawbuf) == total_channels); + + gr->surface = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (gr->drawbuf), + CAIRO_FORMAT_ARGB32, + gdk_pixbuf_get_width (gr->drawbuf), + gdk_pixbuf_get_height (gr->drawbuf), + gdk_pixbuf_get_rowstride (gr->drawbuf)); + g_assert (gr->surface != NULL); + gr->mode = MODE_DRAWABLE_NO_RENDER; + if (gr->cr != NULL) + cairo_destroy (gr->cr); + gr->cr = cairo_create (gr->surface); +} + +static void +init_graphics2d_as_renderable (struct graphics2d *gr) +{ + Drawable draw; + Display * dpy; + Visual * vis; + + g_assert (gr != NULL); + g_assert (gr->drawable != NULL); + + gr->drawbuf = NULL; + + if (gr->debug) printf ("initializing graphics2d as renderable\n"); + draw = gdk_x11_drawable_get_xid (gr->drawable); + + dpy = gdk_x11_drawable_get_xdisplay (gr->drawable); + g_assert (dpy != NULL); + + vis = gdk_x11_visual_get_xvisual (gdk_drawable_get_visual (gr->drawable)); + g_assert (vis != NULL); + + gr->surface = cairo_xlib_surface_create (dpy, draw, vis, gr->width, gr->height); + g_assert (gr->surface != NULL); + gr->mode = MODE_DRAWABLE_WITH_RENDER; + if (gr->cr != NULL) + cairo_destroy (gr->cr); + gr->cr = cairo_create (gr->surface); +} + +static void +begin_drawing_operation (JNIEnv *env, struct graphics2d * gr) +{ + g_assert(cairo_status (gr->cr) == CAIRO_STATUS_SUCCESS); + + switch (gr->mode) + { + case MODE_DRAWABLE_WITH_RENDER: + break; + + case MODE_DRAWABLE_NO_RENDER: + { + + gint drawable_width, drawable_height; + gint pixbuf_width, pixbuf_height; + gint width, height; + + gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); + pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); + pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); + width = min (drawable_width, pixbuf_width); + height = min (drawable_height, pixbuf_height); + + gdk_pixbuf_get_from_drawable (gr->drawbuf, /* destination pixbuf */ + gr->drawable, + NULL, /* colormap */ + 0, 0, 0, 0, + width, height); + + if (gr->debug) printf ("copied (%d, %d) pixels from GDK drawable to pixbuf\n", + width, height); + } + break; + + case MODE_JAVA_ARRAY: + { + jboolean isCopy; + gr->javabuf = (*env)->GetPrimitiveArrayCritical (env, gr->jarray, &isCopy); + gr->isCopy |= isCopy; + if (gr->isCopy) + { + /* Make sure that the pixel buffer copy is already initalized, + i.e. we already failed to get direct access in initState. */ + g_assert (gr->javabuf_copy != NULL); + memcpy (gr->javabuf_copy, gr->javabuf, gr->width * gr->height * 4); + } + } + break; + } +} + +static void +end_drawing_operation (JNIEnv *env, struct graphics2d * gr) +{ + g_assert(cairo_status (gr->cr) == CAIRO_STATUS_SUCCESS); + + switch (gr->mode) + { + case MODE_DRAWABLE_WITH_RENDER: + break; + + case MODE_DRAWABLE_NO_RENDER: + { + + gint drawable_width, drawable_height; + gint pixbuf_width, pixbuf_height; + gint width, height; + + gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); + pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); + pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); + width = min (drawable_width, pixbuf_width); + height = min (drawable_height, pixbuf_height); + + gdk_draw_pixbuf (gr->drawable, NULL, gr->drawbuf, + 0, 0, 0, 0, + width, height, + GDK_RGB_DITHER_NORMAL, 0, 0); + + if (gr->debug) printf ("copied (%d, %d) pixels from pixbuf to GDK drawable\n", + width, height); + } + break; + + case MODE_JAVA_ARRAY: + if (gr->isCopy) + memcpy (gr->javabuf, gr->javabuf_copy, gr->width * gr->height * 4); + (*env)->ReleasePrimitiveArrayCritical (env, gr->jarray, gr->javabuf, JNI_COMMIT); + } +} + + +static void +update_pattern_transform (struct graphics2d *gr) +{ + cairo_matrix_t mat; + + g_assert (gr != NULL); + if (gr->pattern == NULL) + return; + + cairo_get_matrix (gr->cr, &mat); + cairo_pattern_set_matrix (gr->pattern, &mat); +} + +static void +check_for_debug (struct graphics2d *gr) +{ + gr->debug = (gboolean)(getenv("DEBUGJ2D") != NULL); +} + +static void +realize_cb (GtkWidget *widget __attribute__ ((unused)), jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, initComponentGraphics2DID); + + gdk_threads_enter (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState + (JNIEnv *env, jobject obj, jobject old) +{ + struct graphics2d *g = NULL, *g_old = NULL; + + gdk_threads_enter(); + + g = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); + g_assert (g != NULL); + memset (g, 0, sizeof(struct graphics2d)); + + g_old = (struct graphics2d *) NSA_GET_G2D_PTR (env, old); + g_assert (g_old != NULL); + + if (g_old->debug) printf ("copying state from existing graphics2d\n"); + + g->debug = g_old->debug; + g->mode = g_old->mode; + + g->width = g_old->width; + g->height = g_old->height; + + if (g_old->mode == MODE_JAVA_ARRAY) + { + jint size = g->width * g->height * 4; + + g->jarray = (*env)->NewGlobalRef (env, g_old->jarray); + g->javabuf = (*env)->GetIntArrayElements (env, g->jarray, &g->isCopy); + g->isCopy = JNI_TRUE; + g->javabuf_copy = (jint *) g_malloc (size); + memcpy (g->javabuf_copy, g->javabuf, size); + g->surface = cairo_image_surface_create_for_data ((unsigned char *) g->javabuf, + CAIRO_FORMAT_ARGB32, + g->width, + g->height, + g->width * 4); + g_assert (g->surface != NULL); + g->cr = cairo_create (g->surface); + g_assert (g->cr != NULL); + (*env)->ReleaseIntArrayElements (env, g->jarray, g->javabuf, JNI_ABORT); + } + else + { + g->drawable = g_old->drawable; + g_object_ref (g->drawable); + + if (x_server_has_render_extension ()) + init_graphics2d_as_renderable (g); + else + init_graphics2d_as_pixbuf (g); + } + + if (g->pattern) + cairo_pattern_set_filter (g->pattern, CAIRO_FILTER_FAST); + + NSA_SET_G2D_PTR (env, obj, g); + + gdk_threads_leave(); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState___3III +(JNIEnv *env, jobject obj, jintArray jarr, jint width, jint height) +{ + struct graphics2d *gr = NULL; + jint *cairobuf = NULL; + + gdk_threads_enter(); + + gr = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); + g_assert (gr != NULL); + memset (gr, 0, sizeof(struct graphics2d)); + + check_for_debug (gr); + + if (gr->debug) printf ("constructing java-backed image of size (%d,%d)\n", + width, height); + + gr->width = width; + gr->height = height; + gr->jarray = (*env)->NewGlobalRef(env, jarr); + gr->javabuf = (*env)->GetPrimitiveArrayCritical (env, gr->jarray, &gr->isCopy); + if (gr->isCopy) + { + /* We didn't get direct access to the pixel buffer, so we'll have to + maintain a separate copy for Cairo. */ + jint size = gr->width * gr->height * 4; + gr->javabuf_copy = (jint *) g_malloc (size); + memcpy (gr->javabuf_copy, gr->javabuf, size); + cairobuf = gr->javabuf_copy; + } + else + { + /* Have Cairo write directly to the Java array. */ + cairobuf = gr->javabuf; + } + gr->surface = cairo_image_surface_create_for_data ((unsigned char *) cairobuf, + CAIRO_FORMAT_ARGB32, + gr->width, + gr->height, + gr->width * 4); + g_assert (gr->surface != NULL); + gr->cr = cairo_create (gr->surface); + g_assert (gr->cr != NULL); + (*env)->ReleasePrimitiveArrayCritical (env, gr->jarray, gr->javabuf, JNI_COMMIT); + + gr->mode = MODE_JAVA_ARRAY; + + if (gr->debug) printf ("constructed java-backed image of size (%d,%d)\n", + width, height); + + NSA_SET_G2D_PTR (env, obj, gr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II + (JNIEnv *env, jobject obj, jint width, jint height) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + gr = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); + g_assert (gr != NULL); + memset (gr, 0, sizeof(struct graphics2d)); + + check_for_debug (gr); + + if (gr->debug) printf ("constructing offscreen drawable of size (%d,%d)\n", + width, height); + + gr->drawable = (GdkDrawable *) gdk_pixmap_new (NULL, width, height, + gdk_rgb_get_visual ()->depth); + g_assert (gr->drawable != NULL); + + gr->width = width; + gr->height = height; + + if (x_server_has_render_extension ()) + init_graphics2d_as_renderable (gr); + else + init_graphics2d_as_pixbuf (gr); + + if (gr->debug) printf ("constructed offscreen drawable of size (%d,%d)\n", + width, height); + NSA_SET_G2D_PTR (env, obj, gr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable + (JNIEnv *env, jobject self, jobject other, jint x, jint y) +{ + struct graphics2d *src = NULL; + struct graphics2d *dst = NULL; + gint s_height; + gint s_width; + gint d_height; + gint d_width; + gint height; + gint width; + cairo_matrix_t matrix; + cairo_operator_t tmp_op; + + gdk_threads_enter(); + + if (peer_is_disposed(env, self)) + { + gdk_threads_leave(); + return; + } + + src = (struct graphics2d *)NSA_GET_G2D_PTR (env, other); + dst = (struct graphics2d *)NSA_GET_G2D_PTR (env, self); + g_assert (src != NULL); + g_assert (dst != NULL); + + if (src->debug) printf ("copying from offscreen drawable\n"); + + begin_drawing_operation(env, dst); + + /* gdk_flush(); */ + + gdk_drawable_get_size (src->drawable, &s_width, &s_height); + gdk_drawable_get_size (dst->drawable, &d_width, &d_height); + width = min (s_width, d_width); + height = min (s_height, d_height); + + cairo_get_matrix (src->cr, &matrix); + cairo_matrix_translate (&matrix, (double)-x, (double)-y); + if (src->pattern) + cairo_pattern_set_matrix (src->pattern, &matrix); + tmp_op = cairo_get_operator (dst->cr); + cairo_set_operator(dst->cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface (dst->cr, src->surface, 0, 0); + cairo_paint (dst->cr); + cairo_set_operator(dst->cr, tmp_op); + + cairo_matrix_translate (&matrix, (double)x, (double)y); + if (src->pattern) + cairo_pattern_set_matrix (src->pattern, &matrix); + + gdk_flush(); + + end_drawing_operation(env, dst); + + if (src->debug) printf ("copied %d x %d pixels from offscreen drawable\n", width, height); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2 + (JNIEnv *env, jobject obj, jobject peer) +{ + struct graphics2d *gr = NULL; + GtkWidget *widget = NULL; + void *ptr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + ptr = NSA_GET_PTR (env, peer); + g_assert (ptr != NULL); + + gr = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); + g_assert (gr != NULL); + memset (gr, 0, sizeof(struct graphics2d)); + + check_for_debug (gr); + + widget = GTK_WIDGET (ptr); + g_assert (widget != NULL); + + grab_current_drawable (widget, &(gr->drawable), &(gr->win)); + g_assert (gr->drawable != NULL); + + gr->width = widget->allocation.width; + gr->height = widget->allocation.height; + + if (x_server_has_render_extension ()) + init_graphics2d_as_renderable (gr); + else + init_graphics2d_as_pixbuf (gr); + + NSA_SET_G2D_PTR (env, obj, gr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_connectSignals + (JNIEnv *env, jobject obj, jobject peer) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, peer); + + g_signal_connect_after (G_OBJECT (ptr), "realize", + G_CALLBACK (realize_cb), obj); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose + (JNIEnv *env, jobject obj) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + gr = (struct graphics2d *) NSA_DEL_G2D_PTR (env, obj); + + if (gr == NULL) + { + gdk_threads_leave(); + return; /* dispose has been called more than once */ + } + + if (gr->surface) + cairo_surface_destroy (gr->surface); + + cairo_destroy (gr->cr); + + if (gr->drawbuf) + g_object_unref (gr->drawbuf); + + if (gr->drawable) + g_object_unref (gr->drawable); + + if (gr->pattern) + cairo_pattern_destroy (gr->pattern); + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); + + if (gr->pattern_pixels) + g_free (gr->pattern_pixels); + + if (gr->mode == MODE_JAVA_ARRAY) + { + (*env)->DeleteGlobalRef (env, gr->jarray); + if (gr->javabuf_copy) + g_free (gr->javabuf_copy); + } + + if (gr->debug) printf ("disposed of graphics2d\n"); + + g_free (gr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient + (JNIEnv *env, jobject obj, + jdouble x1, jdouble y1, + jdouble x2, jdouble y2, + jint r1, jint g1, jint b1, jint a1, + jint r2, jint g2, jint b2, jint a2, + jboolean cyclic) +{ + struct graphics2d *gr = NULL; + cairo_surface_t *surf = NULL; + cairo_t *cr2 = NULL; + cairo_matrix_t mat; + + gdk_threads_enter(); + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + if (gr->debug) printf ("setGradient (%f,%f) -> (%f,%f); (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n", + x1, y1, + x2, y2, + r1, g1, b1, a1, + r2, g2, b2, a2); + + if (cyclic) + surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 3, 2); + else + surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 2, 2); + g_assert (surf != NULL); + + cr2 = cairo_create (surf); + + cairo_identity_matrix (cr2); + + cairo_set_source_rgba (cr2, r1 / 255.0, g1 / 255.0, b1 / 255.0, a1 / 255.0); + cairo_rectangle (cr2, 0, 0, 1, 2); + cairo_fill (cr2); + + cairo_set_source_rgba (cr2, r2 / 255.0, g2 / 255.0, b2 / 255.0, a2 / 255.0); + cairo_rectangle (cr2, 1, 0, 1, 2); + cairo_fill (cr2); + + if (cyclic) + { + cairo_set_source_rgba (cr2, r1 / 255.0, g1 / 255.0, b1 / 255.0, a1 / 255.0); + cairo_rectangle (cr2, 2, 0, 1, 2); + cairo_fill (cr2); + } + + cairo_matrix_init_identity (&mat); + + /* + consider the vector [x2 - x1, y2 - y1] = [p,q] + + this is a line in space starting at an 'origin' x1, y1. + + it can also be thought of as a "transformed" unit vector in either the + x or y directions. we have just *drawn* our gradient as a unit vector + (well, a 2-3x unit vector) in the x dimension. so what we want to know + is which transformation turns our existing unit vector into [p,q]. + + which means solving for M in + + [p,q] = M[1,0] + + [p,q] = |a b| [1,0] + |c d| + + [p,q] = [a,c], with b = d = 0. + + what does this mean? it means that our gradient is 1-dimensional; as + you move through the x axis of our 2 or 3 pixel gradient from logical + x positions 0 to 1, the transformation of your x coordinate under the + matrix M causes you to accumulate both x and y values in fill + space. the y value of a gradient coordinate is ignored, since the + gradient is one dimensional. which is correct. + + unfortunately we want the opposite transformation, it seems, because of + the way cairo is going to use this transformation. I'm a bit confused by + that, but it seems to work right, so we take reciprocals of values and + negate offsets. oh well. + + */ + { + double a = (x2 - x1 == 0.) ? 0. : ((cyclic ? 3.0 : 2.0) / (x2 - x1)); + double c = (y2 - y1 == 0.) ? 0. : (1. / (y2 - y1)); + double dx = (x1 == 0.) ? 0. : 1. / x1; + double dy = (y1 == 0.) ? 0. : 1. / y1; + cairo_pattern_t *p; + + cairo_matrix_init (&mat, + a, 0., + c, 0., + dx, dy); + + p = cairo_pattern_create_for_surface (surf); + cairo_pattern_set_matrix (p, &mat); + cairo_pattern_set_filter (p, CAIRO_FILTER_BILINEAR); + } + + /* FIXME: repeating gradients (not to mention hold gradients) don't seem to work. */ + /* cairo_surface_set_repeat (surf, cyclic ? 1 : 0); */ + + if (gr->pattern) + cairo_pattern_destroy (gr->pattern); + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); + + if (gr->pattern_pixels) + g_free (gr->pattern_pixels); + + gr->pattern_pixels = NULL; + gr->pattern_surface = surf; + gr->pattern = cairo_pattern_create_for_surface(surf); + + cairo_set_source (gr->cr, gr->pattern); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels + (JNIEnv *env, jobject obj, jintArray jarr, jint w, jint h, jint stride) +{ + struct graphics2d *gr = NULL; + jint *jpixels = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + + if (gr->debug) printf ("setTexturePixels (%d pixels, %dx%d, stride: %d)\n", + (*env)->GetArrayLength (env, jarr), w, h, stride); + + if (gr->pattern) + cairo_pattern_destroy (gr->pattern); + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); + + if (gr->pattern_pixels) + g_free (gr->pattern_pixels); + + gr->pattern = NULL; + gr->pattern_surface = NULL; + gr->pattern_pixels = NULL; + + gr->pattern_pixels = (char *) g_malloc (h * stride * 4); + g_assert (gr->pattern_pixels != NULL); + + jpixels = (*env)->GetIntArrayElements (env, jarr, NULL); + g_assert (jpixels != NULL); + memcpy (gr->pattern_pixels, jpixels, h * stride * 4); + (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0); + + gr->pattern_surface = cairo_image_surface_create_for_data ((unsigned char *)gr->pattern_pixels, + CAIRO_FORMAT_ARGB32, + w, h, stride * 4); + g_assert (gr->pattern_surface != NULL); + cairo_pattern_set_extend (gr->pattern, 1); + gr->pattern = cairo_pattern_create_for_surface (gr->pattern_surface); + g_assert (gr->pattern != NULL); + cairo_set_source (gr->cr, gr->pattern); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels + (JNIEnv *env, jobject obj, jintArray java_pixels, + jint w, jint h, jint stride, jdoubleArray java_matrix) +{ + struct graphics2d *gr = NULL; + jint *native_pixels = NULL; + jdouble *native_matrix = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + + if (gr->debug) printf ("drawPixels (%d pixels, %dx%d, stride: %d)\n", + (*env)->GetArrayLength (env, java_pixels), w, h, stride); + + native_pixels = (*env)->GetIntArrayElements (env, java_pixels, NULL); + native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); + g_assert (native_pixels != NULL); + g_assert (native_matrix != NULL); + g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); + + begin_drawing_operation (env, gr); + + { + cairo_matrix_t mat; + cairo_pattern_t *p; + cairo_surface_t *surf = cairo_image_surface_create_for_data ((unsigned char *)native_pixels, + CAIRO_FORMAT_ARGB32, + w, h, stride * 4); + cairo_matrix_init_identity (&mat); + cairo_matrix_init (&mat, + native_matrix[0], native_matrix[1], + native_matrix[2], native_matrix[3], + native_matrix[4], native_matrix[5]); + + p = cairo_pattern_create_for_surface (surf); + cairo_pattern_set_matrix (p, &mat); + if (gr->pattern) + cairo_pattern_set_filter (p, cairo_pattern_get_filter (gr->pattern)); + cairo_set_source (gr->cr, p); + cairo_paint (gr->cr); + cairo_pattern_destroy (p); + cairo_surface_destroy (surf); + } + + end_drawing_operation (env, gr); + + (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0); + (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); + + gdk_threads_leave(); +} + +/* passthrough methods to cairo */ + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSave + (JNIEnv *env, jobject obj) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_save\n"); + cairo_save (gr->cr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRestore + (JNIEnv *env, jobject obj) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_restore\n"); + cairo_restore (gr->cr); + update_pattern_transform (gr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix + (JNIEnv *env, jobject obj, jdoubleArray java_matrix) +{ + struct graphics2d *gr = NULL; + jdouble *native_matrix = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + + /* cairoSetMatrix was called before this graphics object's component + was realized. */ + if (gr == NULL) + { + gdk_threads_leave (); + return; + } + + native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); + g_assert (native_matrix != NULL); + g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); + + if (gr->debug) printf ("cairo_set_matrix [ %f, %f, %f, %f, %f, %f ]\n", + native_matrix[0], native_matrix[1], + native_matrix[2], native_matrix[3], + native_matrix[4], native_matrix[5]); + + { + cairo_matrix_t mat; + + cairo_matrix_init_identity (&mat); + cairo_matrix_init (&mat, + native_matrix[0], native_matrix[1], + native_matrix[2], native_matrix[3], + native_matrix[4], native_matrix[5]); + cairo_set_matrix (gr->cr, &mat); + } + + (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); + update_pattern_transform (gr); + + gdk_threads_leave(); +} + +static void +install_font_peer(cairo_t *cr, + struct peerfont *pfont, + int debug) +{ + cairo_font_face_t *ft; + FT_Face face = NULL; + + g_assert(cr != NULL); + g_assert(pfont != NULL); + + if (pfont->graphics_resource == NULL) + { + face = pango_ft2_font_get_face (pfont->font); + g_assert (face != NULL); + + ft = cairo_ft_font_face_create_for_ft_face (face, 0); + g_assert (ft != NULL); + + if (debug) printf ("install_font_peer made new cairo font for '%s' at %f\n", + face->family_name, + (pango_font_description_get_size (pfont->desc) / + (double)PANGO_SCALE)); + + cairo_set_font_face (cr, ft); + cairo_font_face_destroy (ft); + cairo_set_font_size (cr, + (pango_font_description_get_size (pfont->desc) / + (double)PANGO_SCALE)); + ft = cairo_get_font_face (cr); + pfont->graphics_resource = ft; + } + else + { + if (debug) printf ("install_font_peer reused existing font resource\n"); + ft = (cairo_font_face_t *) pfont->graphics_resource; + cairo_set_font_face (cr, ft); + } +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_releasePeerGraphicsResource + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject java_font) +{ + struct peerfont *pfont = NULL; + + gdk_threads_enter(); + + g_assert(java_font != NULL); + + pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); + g_assert (pfont != NULL); + if (pfont->graphics_resource != NULL) + { + cairo_font_face_destroy ((cairo_font_face_t *) pfont->graphics_resource); + pfont->graphics_resource = NULL; + } + + gdk_threads_leave(); +} + +static void +paint_glyph_run(JNIEnv *env, + struct graphics2d *gr, + cairo_glyph_t **glyphs, + gint *n_glyphs, + PangoLayoutRun *run) +{ + gint i = 0; + gint x = 0, y = 0; + + g_assert (gr != NULL); + g_assert (glyphs != NULL); + g_assert (n_glyphs != NULL); + g_assert (run != NULL); + + if (run->glyphs != NULL && run->glyphs->num_glyphs > 0) + { + if (*n_glyphs < run->glyphs->num_glyphs) + { + *glyphs = g_realloc(*glyphs, + (sizeof(cairo_glyph_t) + * run->glyphs->num_glyphs)); + *n_glyphs = run->glyphs->num_glyphs; + } + + g_assert (*glyphs != NULL); + + if (gr->debug) printf ("painting %d glyphs: ", run->glyphs->num_glyphs); + + for (i = 0; i < run->glyphs->num_glyphs; ++i) + { + (*glyphs)[i].index = run->glyphs->glyphs[i].glyph; + + (*glyphs)[i].x = + ((double) (x + run->glyphs->glyphs[i].geometry.x_offset)) + / ((double) PANGO_SCALE); + + (*glyphs)[i].y = + ((double) (y + run->glyphs->glyphs[i].geometry.y_offset)) + / ((double) PANGO_SCALE); + + if (gr->debug) printf(" (%ld @ %f,%f)", + (*glyphs)[i].index, + (*glyphs)[i].x, + (*glyphs)[i].y); + + x += run->glyphs->glyphs[i].geometry.width; + } + + if (gr->debug) printf("\n"); + begin_drawing_operation (env, gr); + cairo_show_glyphs (gr->cr, *glyphs, run->glyphs->num_glyphs); + end_drawing_operation (env, gr); + } +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGlyphVector + (JNIEnv *env, jobject self, + jobject font, + jfloat x, jfloat y, jint n, + jintArray java_codes, + jfloatArray java_positions) +{ + + struct graphics2d *gr = NULL; + struct peerfont *pfont = NULL; + cairo_glyph_t *glyphs = NULL; + int *native_codes; + float *native_positions; + jint i = 0; + + gdk_threads_enter (); + + g_assert (self != NULL); + g_assert (java_codes != NULL); + g_assert (java_positions != NULL); + + if (peer_is_disposed(env, self)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *)NSA_GET_G2D_PTR (env, self); + g_assert (gr != NULL); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); + g_assert (pfont != NULL); + + install_font_peer(gr->cr, pfont, gr->debug); + + glyphs = g_malloc( sizeof(cairo_glyph_t) * n); + g_assert (glyphs != NULL); + + native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); + native_positions = (*env)->GetFloatArrayElements (env, java_positions, NULL); + + for (i = 0; i < n; ++i) + { + glyphs[i].index = native_codes[i]; + glyphs[i].x = x + native_positions[ 2*i ]; + glyphs[i].y = y + native_positions[ 2*i + 1]; + } + + (*env)->ReleaseFloatArrayElements (env, java_positions, native_positions, 0); + (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); + + begin_drawing_operation (env, gr); + cairo_show_glyphs (gr->cr, glyphs, n); + end_drawing_operation (env, gr); + + g_free(glyphs); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGdkTextLayout + (JNIEnv *env, jobject self, jobject java_layout, jfloat x, jfloat y) +{ + /* + * FIXME: Some day we expect either cairo or pango will know how to make + * a pango layout paint to a cairo surface. that day is not yet here. + */ + + struct graphics2d *gr = NULL; + struct textlayout *tl = NULL; + PangoLayoutIter *i = NULL; + PangoLayoutRun *run = NULL; + cairo_glyph_t *glyphs = NULL; + gint n_glyphs = 0; + + gdk_threads_enter (); + + g_assert (self != NULL); + g_assert (java_layout != NULL); + + gr = (struct graphics2d *)NSA_GET_G2D_PTR (env, self); + tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, java_layout); + + g_assert (gr != NULL); + g_assert (tl != NULL); + g_assert (tl->pango_layout != NULL); + + if (gr->debug) printf ("painting pango layout\n"); + + if (peer_is_disposed(env, self)) + { + gdk_threads_leave(); + return; + } + + i = pango_layout_get_iter (tl->pango_layout); + g_assert (i != NULL); + + cairo_translate (gr->cr, x, y); + + do + { + run = pango_layout_iter_get_run (i); + if (run != NULL) + paint_glyph_run (env, gr, &glyphs, &n_glyphs, run); + } + while (pango_layout_iter_next_run (i)); + + if (glyphs != NULL) + g_free (glyphs); + + cairo_translate (gr->cr, -x, -y); + + pango_layout_iter_free (i); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator + (JNIEnv *env, jobject obj, jint op) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_set_operator %d\n", op); + switch ((enum java_awt_alpha_composite_rule) op) + { + case java_awt_alpha_composite_CLEAR: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_CLEAR); + break; + + case java_awt_alpha_composite_SRC: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_SOURCE); + break; + + case java_awt_alpha_composite_SRC_OVER: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER); + break; + + case java_awt_alpha_composite_DST_OVER: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OVER); + break; + + case java_awt_alpha_composite_SRC_IN: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN); + break; + + case java_awt_alpha_composite_DST_IN: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_IN); + break; + + case java_awt_alpha_composite_SRC_OUT: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT); + break; + + case java_awt_alpha_composite_DST_OUT: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OUT); + break; + + case java_awt_alpha_composite_DST: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST); + break; + + case java_awt_alpha_composite_SRC_ATOP: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP); + break; + + case java_awt_alpha_composite_DST_ATOP: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_ATOP); + break; + + case java_awt_alpha_composite_XOR: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_XOR); + break; + } + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetRGBAColor + (JNIEnv *env, jobject obj, jdouble r, jdouble g, jdouble b, jdouble a) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + + /* this is a very weird fact: GDK Pixbufs and RENDER drawables consider + colors in opposite pixel order. I have no idea why. thus when you + draw to a PixBuf, you must exchange the R and B components of your + color. */ + + if (gr->debug) printf ("cairo_set_source_rgb (%f, %f, %f)\n", r, g, b); + + if (gr->drawbuf) + cairo_set_source_rgba (gr->cr, b, g, r, a); + else + cairo_set_source_rgba (gr->cr, r, g, b, a); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFillRule + (JNIEnv *env, jobject obj, jint rule) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + if (gr->debug) printf ("cairo_set_fill_rule %d\n", rule); + g_assert (gr != NULL); + switch ((enum java_awt_geom_path_iterator_winding_rule) rule) + { + case java_awt_geom_path_iterator_WIND_NON_ZERO: + cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_WINDING); + break; + case java_awt_geom_path_iterator_WIND_EVEN_ODD: + cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_EVEN_ODD); + break; + } + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineWidth + (JNIEnv *env, jobject obj, jdouble width) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + return; + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_set_line_width %f\n", width); + cairo_set_line_width (gr->cr, width); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineCap + (JNIEnv *env, jobject obj, jint cap) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_set_line_cap %d\n", cap); + switch ((enum java_awt_basic_stroke_cap_rule) cap) + { + case java_awt_basic_stroke_CAP_BUTT: + cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_BUTT); + break; + + case java_awt_basic_stroke_CAP_ROUND: + cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_ROUND); + break; + + case java_awt_basic_stroke_CAP_SQUARE: + cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_SQUARE); + break; + } + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineJoin + (JNIEnv *env, jobject obj, jint join) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_set_line_join %d\n", join); + switch ((enum java_awt_basic_stroke_join_rule) join) + { + case java_awt_basic_stroke_JOIN_MITER: + cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_MITER); + break; + + case java_awt_basic_stroke_JOIN_ROUND: + cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_ROUND); + break; + + case java_awt_basic_stroke_JOIN_BEVEL: + cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_BEVEL); + break; + } + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash + (JNIEnv *env, jobject obj, jdoubleArray dashes, jint ndash, jdouble offset) +{ + struct graphics2d *gr = NULL; + jdouble *dasharr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_set_dash\n"); + dasharr = (*env)->GetDoubleArrayElements (env, dashes, NULL); + g_assert (dasharr != NULL); + cairo_set_dash (gr->cr, dasharr, ndash, offset); + (*env)->ReleaseDoubleArrayElements (env, dashes, dasharr, 0); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMiterLimit + (JNIEnv *env, jobject obj, jdouble miter) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_set_miter_limit %f\n", miter); + cairo_set_miter_limit (gr->cr, miter); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoNewPath + (JNIEnv *env, jobject obj) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + + if (gr == NULL) + { + gdk_threads_leave (); + return; + } + + if (gr->debug) printf ("cairo_new_path\n"); + cairo_new_path (gr->cr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoMoveTo + (JNIEnv *env, jobject obj, jdouble x, jdouble y) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_move_to (%f, %f)\n", x, y); + cairo_move_to (gr->cr, x, y); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoLineTo + (JNIEnv *env, jobject obj, jdouble x, jdouble y) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_line_to (%f, %f)\n", x, y); + cairo_line_to (gr->cr, x, y); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoCurveTo + (JNIEnv *env, jobject obj, jdouble x1, jdouble y1, jdouble x2, jdouble y2, jdouble x3, jdouble y3) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_curve_to (%f, %f), (%f, %f), (%f, %f)\n", x1, y1, x2, y2, x3, y3); + cairo_curve_to (gr->cr, x1, y1, x2, y2, x3, y3); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelMoveTo + (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_rel_move_to (%f, %f)\n", dx, dy); + cairo_rel_move_to (gr->cr, dx, dy); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelLineTo + (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_rel_line_to (%f, %f)\n", dx, dy); + cairo_rel_line_to (gr->cr, dx, dy); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelCurveTo + (JNIEnv *env, jobject obj, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_rel_curve_to (%f, %f), (%f, %f), (%f, %f)\n", dx1, dy1, dx2, dy2, dx3, dy3); + cairo_rel_curve_to (gr->cr, dx1, dy1, dx2, dy2, dx3, dy3); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRectangle + (JNIEnv *env, jobject obj, jdouble x, jdouble y, jdouble width, jdouble height) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + + if (gr == NULL) + { + gdk_threads_leave (); + return; + } + + if (gr->debug) printf ("cairo_rectangle (%f, %f) (%f, %f)\n", x, y, width, height); + cairo_rectangle (gr->cr, x, y, width, height); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClosePath + (JNIEnv *env, jobject obj) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_close_path\n"); + cairo_close_path (gr->cr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoStroke + (JNIEnv *env, jobject obj) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_stroke\n"); + begin_drawing_operation (env, gr); + cairo_stroke (gr->cr); + end_drawing_operation (env, gr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoFill + (JNIEnv *env, jobject obj) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_fill\n"); + begin_drawing_operation (env, gr); + cairo_fill (gr->cr); + end_drawing_operation (env, gr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClip + (JNIEnv *env, jobject obj) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave(); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + + if (gr == NULL) + { + gdk_threads_leave (); + return; + } + + if (gr->debug) printf ("cairo_clip\n"); + begin_drawing_operation (env, gr); + cairo_reset_clip (gr->cr); + cairo_clip (gr->cr); + end_drawing_operation (env, gr); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSurfaceSetFilter + (JNIEnv *env, jobject obj, jint filter) +{ + struct graphics2d *gr = NULL; + + gdk_threads_enter(); + + if (peer_is_disposed(env, obj)) + { + gdk_threads_leave (); + return; + } + + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); + g_assert (gr != NULL); + if (gr->debug) printf ("cairo_surface_set_filter %d\n", filter); + switch ((enum java_awt_rendering_hints_filter) filter) + { + case java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); + break; + case java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BILINEAR); + break; + case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_FAST); + break; + case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); + break; + case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BEST); + break; + } + + gdk_threads_leave(); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c new file mode 100644 index 00000000000..0467c3c7acd --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c @@ -0,0 +1,102 @@ +/* gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c + Copyright (C) 2004 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath 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, or (at your option) + any later version. + + GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + 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. */ + +#include "gdkfont.h" +#include "gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h" + + +static gint +cmp_families (const void *a, const void *b) +{ + const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a); + const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b); + + return g_utf8_collate (a_name, b_name); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetFontFamilies +(JNIEnv *env, jobject self __attribute__((unused)), jobjectArray family_name) +{ + PangoContext *context = NULL; + PangoFontFamily **families = NULL; + int n_families = 0; + int idx = 0; + + gdk_threads_enter (); + + context = gdk_pango_context_get(); + g_assert (context != NULL); + + pango_context_list_families (context, &families, &n_families); + + qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families); + + for (idx = 0; idx < n_families; idx++) + { + const char *name_tmp = pango_font_family_get_name (families[idx]); + jstring name = (*env)->NewStringUTF (env, name_tmp); + (*env)->SetObjectArrayElement (env, family_name, idx, name); + } + g_free (families); + + gdk_threads_leave (); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetNumFontFamilies +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) +{ + PangoContext *context = NULL; + PangoFontFamily **families = NULL; + gint n_families = 0; + gint num = 0; + + gdk_threads_enter (); + + context = gdk_pango_context_get(); + g_assert (context != NULL); + + pango_context_list_families (context, &families, &n_families); + + num = n_families; + g_free (families); + + gdk_threads_leave (); + + return num; +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c new file mode 100644 index 00000000000..648cd6603d1 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c @@ -0,0 +1,515 @@ +/* gdkpixbufdecoder.c + Copyright (C) 1999, 2003, 2004, 2005 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath 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, or (at your option) + any later version. + + GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + 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. */ + +#include <gtkpeer.h> +#include <gdk/gdk.h> +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdk-pixbuf/gdk-pixbuf-loader.h> + +#include <jni.h> +#include <jcl.h> +#include "native_state.h" +#include "gnu_java_awt_peer_gtk_GdkPixbufDecoder.h" + +#include <string.h> +#include <stdlib.h> + +static struct state_table *native_pixbufdecoder_state_table; + +#define NSA_PB_INIT(env, clazz) \ + native_pixbufdecoder_state_table = cp_gtk_init_state_table (env, clazz) + +#define NSA_GET_PB_PTR(env, obj) \ + cp_gtk_get_state (env, obj, native_pixbufdecoder_state_table) + +#define NSA_SET_PB_PTR(env, obj, ptr) \ + cp_gtk_set_state (env, obj, native_pixbufdecoder_state_table, (void *)ptr) + +#define NSA_DEL_PB_PTR(env, obj) \ + cp_gtk_remove_state_slot (env, obj, native_pixbufdecoder_state_table) + +/* Union used for type punning. */ +union env_union +{ + void **void_env; + JNIEnv **jni_env; +}; + +static JavaVM *vm; + +static jmethodID areaPreparedID; +static jmethodID areaUpdatedID; +static jmethodID dataOutputWriteID; +static jmethodID registerFormatID; + +static void +area_prepared_cb (GdkPixbufLoader *loader, + jobject *decoder) +{ + JNIEnv *env = NULL; + union env_union e; + jint width = 0; + jint height = 0; + GdkPixbuf *pixbuf = NULL; + + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + g_assert (pixbuf != NULL); + + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + + g_assert (decoder != NULL); + + e.jni_env = &env; + (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1); + + gdk_threads_leave (); + + (*env)->CallVoidMethod (env, + *decoder, + areaPreparedID, + width, height); + + gdk_threads_enter (); +} + +static void +area_updated_cb (GdkPixbufLoader *loader, + gint x, gint y, + gint width, gint height, + jobject *decoder) +{ + JNIEnv *env; + union env_union e; + jint stride_bytes, stride_pixels, n_channels, n_pixels; + jintArray jpixels; + jint *java_pixels; + guchar *gdk_pixels; + + GdkPixbuf *pixbuf_no_alpha = NULL; + GdkPixbuf *pixbuf = NULL; + +#ifndef WORDS_BIGENDIAN + int i; +#endif + + pixbuf_no_alpha = gdk_pixbuf_loader_get_pixbuf (loader); + if (pixbuf_no_alpha == NULL) + return; + + pixbuf = gdk_pixbuf_add_alpha(pixbuf_no_alpha, FALSE, 0, 0, 0); + g_assert (gdk_pixbuf_get_has_alpha (pixbuf)); + + stride_bytes = gdk_pixbuf_get_rowstride (pixbuf); + n_channels = gdk_pixbuf_get_n_channels (pixbuf); + stride_pixels = stride_bytes / n_channels; + n_pixels = height * stride_pixels; + gdk_pixels = gdk_pixbuf_get_pixels (pixbuf); + + e.jni_env = &env; + (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1); + + gdk_threads_leave (); + + jpixels = (*env)->NewIntArray (env, n_pixels); + + gdk_threads_enter (); + + java_pixels = (*env)->GetIntArrayElements (env, jpixels, NULL); + + memcpy (java_pixels, + gdk_pixels + (y * stride_bytes), + (height * stride_bytes)); + +#ifndef WORDS_BIGENDIAN + /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */ + for (i = 0; i < n_pixels; ++i) + { + java_pixels[i] = SWAPU32 ((unsigned)java_pixels[i]); + } +#endif + + g_object_unref (pixbuf); + + gdk_threads_leave (); + + (*env)->ReleaseIntArrayElements (env, jpixels, java_pixels, 0); + + (*env)->CallVoidMethod (env, + *decoder, + areaUpdatedID, + (jint) x, (jint) y, + (jint) width, (jint) height, + jpixels, + stride_pixels); + + (*env)->DeleteLocalRef(env, jpixels); + + gdk_threads_enter (); +} + +static void +closed_cb (GdkPixbufLoader *loader __attribute__((unused)), jobject *decoder) +{ + JNIEnv *env; + union env_union e; + e.jni_env = &env; + (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1); + + gdk_threads_leave (); + + (*env)->DeleteGlobalRef (env, *decoder); + g_free (decoder); + + gdk_threads_enter (); +} + + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initState + (JNIEnv *env, jobject obj) +{ + GdkPixbufLoader *loader = NULL; + jobject *decoder = NULL; + + gdk_threads_enter (); + + decoder = (jobject *) g_malloc (sizeof (jobject)); + g_assert (decoder != NULL); + *decoder = (*env)->NewGlobalRef (env, obj); + + loader = gdk_pixbuf_loader_new (); + g_assert (loader != NULL); + g_signal_connect (loader, "area-prepared", G_CALLBACK (area_prepared_cb), decoder); + g_signal_connect (loader, "area-updated", G_CALLBACK (area_updated_cb), decoder); + g_signal_connect (loader, "closed", G_CALLBACK (closed_cb), decoder); + + NSA_SET_PB_PTR (env, obj, loader); + + gdk_threads_leave (); +} + +static void +query_formats (JNIEnv *env, jclass clazz) +{ + jobject jformat; + GSList *formats, *f; + GdkPixbufFormat *format; + char **ch, *name; + + jclass formatClass; + jmethodID addExtensionID; + jmethodID addMimeTypeID; + jobject string; + + formatClass = (*env)->FindClass + (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec"); + + g_assert(formatClass != NULL); + + addExtensionID = (*env)->GetMethodID (env, formatClass, + "addExtension", + "(Ljava/lang/String;)V"); + + addMimeTypeID = (*env)->GetMethodID (env, formatClass, + "addMimeType", + "(Ljava/lang/String;)V"); + + formats = gdk_pixbuf_get_formats (); + + for (f = formats; f; f = f->next) + { + format = (GdkPixbufFormat *) f->data; + name = gdk_pixbuf_format_get_name(format); + + string = (*env)->NewStringUTF(env, name); + g_assert(string != NULL); + + jformat = (*env)->CallStaticObjectMethod + (env, clazz, registerFormatID, string, + (jboolean) gdk_pixbuf_format_is_writable(format)); + (*env)->DeleteLocalRef(env, string); + + g_assert(jformat != NULL); + + ch = gdk_pixbuf_format_get_extensions(format); + while (*ch) + { + string = (*env)->NewStringUTF(env, *ch); + g_assert(string != NULL); + (*env)->CallVoidMethod (env, jformat, addExtensionID, string); + (*env)->DeleteLocalRef(env, string); + ++ch; + } + + ch = gdk_pixbuf_format_get_mime_types(format); + while (*ch) + { + string = (*env)->NewStringUTF(env, *ch); + g_assert(string != NULL); + (*env)->CallVoidMethod (env, jformat, addMimeTypeID, string); + (*env)->DeleteLocalRef(env, string); + ++ch; + } + } + + g_slist_free(formats); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState + (JNIEnv *env, jclass clazz) +{ + jclass dataOutputClass; + + (*env)->GetJavaVM(env, &vm); + + areaPreparedID = (*env)->GetMethodID (env, clazz, + "areaPrepared", + "(II)V"); + + areaUpdatedID = (*env)->GetMethodID (env, clazz, + "areaUpdated", + "(IIII[II)V"); + + registerFormatID = (*env)->GetStaticMethodID + (env, clazz, + "registerFormat", + "(Ljava/lang/String;Z)" + "Lgnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec;"); + + + dataOutputClass = (*env)->FindClass(env, "java/io/DataOutput"); + dataOutputWriteID = (*env)->GetMethodID (env, dataOutputClass, + "write", "([B)V"); + + query_formats (env, clazz); + + NSA_PB_INIT (env, clazz); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_finish +(JNIEnv *env, jobject obj, jboolean needs_close) +{ + GdkPixbufLoader *loader = NULL; + + gdk_threads_enter (); + + loader = (GdkPixbufLoader *)NSA_DEL_PB_PTR (env, obj); + if (loader == NULL) + return; + + if (needs_close) + gdk_pixbuf_loader_close (loader, NULL); + g_object_unref (loader); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpDone +(JNIEnv *env, jobject obj) +{ + GError *err = NULL; + GdkPixbufLoader *loader = NULL; + + gdk_threads_enter (); + + loader = (GdkPixbufLoader *)NSA_GET_PB_PTR (env, obj); + g_assert (loader != NULL); + + gdk_pixbuf_loader_close (loader, &err); + + if (err != NULL) + { + JCL_ThrowException (env, "java/io/IOException", err->message); + g_error_free (err); + } + + gdk_threads_leave (); +} + +struct stream_save_request +{ + JNIEnv *env; + jobject *stream; +}; + +static gboolean +save_to_stream(const gchar *buf, + gsize count, + GError **error __attribute__((unused)), + gpointer data) +{ + struct stream_save_request *ssr = (struct stream_save_request *)data; + + jbyteArray jbuf; + jbyte *cbuf; + + gdk_threads_leave (); + + jbuf = (*(ssr->env))->NewByteArray ((ssr->env), count); + cbuf = (*(ssr->env))->GetByteArrayElements ((ssr->env), jbuf, NULL); + memcpy (cbuf, buf, count); + (*(ssr->env))->ReleaseByteArrayElements ((ssr->env), jbuf, cbuf, 0); + (*(ssr->env))->CallVoidMethod ((ssr->env), *(ssr->stream), + dataOutputWriteID, jbuf); + + gdk_threads_enter (); + + return TRUE; +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_streamImage +(JNIEnv *env, jclass clazz __attribute__((unused)), + jintArray jarr, jstring jenctype, jint width, jint height, + jboolean hasAlpha, jobject stream) +{ + GdkPixbuf* pixbuf; + jint *ints; + guchar a, r, g, b, *pix, *p; + GError *err = NULL; + const char *enctype; + int i; + struct stream_save_request ssr; + + gdk_threads_enter (); + + ssr.stream = &stream; + ssr.env = env; + + ints = (*env)->GetIntArrayElements (env, jarr, NULL); + pix = g_malloc(width * height * (hasAlpha ? 4 : 3)); + + enctype = (*env)->GetStringUTFChars (env, jenctype, NULL); + g_assert(enctype != NULL); + + g_assert (pix != NULL); + g_assert (ints != NULL); + + p = pix; + for (i = 0; i < width*height; ++i) + { + /* + * Java encodes pixels as integers in a predictable arithmetic order: + * 0xAARRGGBB. Since these are jints, JNI has already byte-swapped + * them for us if necessary, so they're in "our" endianness, whatever + * that is. It uses 4 bytes per pixel whether or not there's an alpha + * channel. + */ + + a = 0xff & (ints[i] >> 24); + r = 0xff & (ints[i] >> 16); + g = 0xff & (ints[i] >> 8); + b = 0xff & ints[i]; + + /* + * GDK-pixbuf has a very different storage model: + * + * - A different alpha order (alpha after colors). + * - A different packing model (no alpha -> 3-bytes-per-pixel). + * - A different "RGB" order (host memory order, not endian-neutral). + */ + + *p++ = r; + *p++ = g; + *p++ = b; + if (hasAlpha) + *p++ = a; + } + + pixbuf = gdk_pixbuf_new_from_data (pix, + GDK_COLORSPACE_RGB, + (gboolean) hasAlpha, + 8, width, height, + width * (hasAlpha ? 4 : 3), /* rowstride */ + NULL, NULL); + g_assert (pixbuf != NULL); + + g_assert(gdk_pixbuf_save_to_callback (pixbuf, + &save_to_stream, + &ssr, + enctype, + &err, NULL)); + + g_object_unref (pixbuf); + + g_free(pix); + + (*env)->ReleaseStringUTFChars (env, jenctype, enctype); + (*env)->ReleaseIntArrayElements (env, jarr, ints, 0); + + gdk_threads_leave (); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes + (JNIEnv *env, jobject obj, jbyteArray jarr, jint len) +{ + GdkPixbufLoader *loader = NULL; + jbyte *bytes = NULL; + GError *err = NULL; + + gdk_threads_enter (); + + g_assert (len >= 1); + g_assert (jarr != NULL); + + bytes = (*env)->GetByteArrayElements (env, jarr, NULL); + g_assert (bytes != NULL); + loader = (GdkPixbufLoader *)NSA_GET_PB_PTR (env, obj); + g_assert (loader != NULL); + + gdk_pixbuf_loader_write (loader, (const guchar *) bytes, len, &err); + + (*env)->ReleaseByteArrayElements (env, jarr, bytes, 0); + + if (err != NULL) + { + JCL_ThrowException (env, "java/io/IOException", err->message); + g_error_free (err); + } + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c new file mode 100644 index 00000000000..8c0ac6ce35f --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c @@ -0,0 +1,341 @@ +/* gdkrobotpeer.c + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GdkRobotPeer.h" +#include <gdk/gdkx.h> +#include <X11/extensions/XTest.h> + +static int +awt_button_mask_to_num (int buttons) +{ + switch (buttons) + { + case AWT_BUTTON1_MASK: + return 1; + case AWT_BUTTON2_MASK: + return 2; + case AWT_BUTTON3_MASK: + return 3; + } + + return 0; +} + +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_initXTest + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) +{ + GdkDisplay *display; + Display *xdisplay; + int event_basep; + int error_basep; + int majorp; + int minorp; + jboolean result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + result = XTestQueryExtension (xdisplay, + &event_basep, + &error_basep, + &majorp, + &minorp); + + gdk_threads_leave (); + + return result; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mouseMove + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint x, jint y) +{ + GdkDisplay *display; + Display *xdisplay; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + result = XTestFakeMotionEvent (xdisplay, + -1, + x, y, CurrentTime); + + XFlush (xdisplay); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mousePress + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint buttons) +{ + GdkDisplay *display; + Display *xdisplay; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + result = XTestFakeButtonEvent (xdisplay, + awt_button_mask_to_num (buttons), + True, CurrentTime); + + XFlush (xdisplay); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mouseRelease + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint buttons) +{ + GdkDisplay *display; + Display *xdisplay; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + result = XTestFakeButtonEvent (xdisplay, + awt_button_mask_to_num (buttons), + False, CurrentTime); + + XFlush (xdisplay); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mouseWheel + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint wheelAmt) +{ + GdkDisplay *display; + Display *xdisplay; + int i = 0; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + if (wheelAmt < 0) + for (i = 0; i < -wheelAmt; i++) + { + XTestFakeButtonEvent (xdisplay, + 4, + True, CurrentTime); + XTestFakeButtonEvent (xdisplay, + 4, + False, CurrentTime); + } + else + for (i = 0; i < wheelAmt; i++) + { + XTestFakeButtonEvent (xdisplay, + 5, + True, CurrentTime); + XTestFakeButtonEvent (xdisplay, + 5, + False, CurrentTime); + } + + XFlush (xdisplay); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_keyPress + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint keycode) +{ + GdkDisplay *display; + Display *xdisplay; + GdkKeymapKey *keymap_keys = NULL; + gint n_keys = 0; + guint lookup_keyval = 0; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + lookup_keyval = cp_gtk_awt_keycode_to_keysym (keycode, + AWT_KEY_LOCATION_LEFT); + + if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), + lookup_keyval, + &keymap_keys, + &n_keys)) + { + /* No matching keymap entry was found. */ + g_printerr ("No matching keymap entries were found\n"); + gdk_threads_leave (); + return; + } + + /* If n_keys > 1 then there are multiple hardware keycodes that + translate to lookup_keyval. We arbitrarily choose the first + hardware keycode from the list returned by + gdk_keymap_get_entries_for_keyval. */ + result = XTestFakeKeyEvent (xdisplay, + keymap_keys[0].keycode, + True, CurrentTime); + + g_free (keymap_keys); + + XFlush (xdisplay); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_keyRelease + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint keycode) +{ + GdkDisplay *display; + Display *xdisplay; + GdkKeymapKey *keymap_keys = NULL; + gint n_keys = 0; + guint lookup_keyval = 0; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + lookup_keyval = cp_gtk_awt_keycode_to_keysym (keycode, + AWT_KEY_LOCATION_LEFT); + + if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), + lookup_keyval, + &keymap_keys, + &n_keys)) + { + /* No matching keymap entry was found. */ + g_printerr ("No matching keymap entries were found\n"); + gdk_threads_leave (); + return; + } + + /* If n_keys > 1 then there are multiple hardware keycodes that + translate to lookup_keyval. We arbitrarily choose the first + hardware keycode from the list returned by + gdk_keymap_get_entries_for_keyval. */ + result = XTestFakeKeyEvent (xdisplay, + keymap_keys[0].keycode, + False, CurrentTime); + + g_free (keymap_keys); + + XFlush (xdisplay); + + gdk_threads_leave (); +} + +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_nativeGetRGBPixels + (JNIEnv *env, jobject obj __attribute__((unused)), jint x, jint y, + jint width, jint height) +{ + jint stride_bytes, stride_pixels, n_channels, n_pixels; + jintArray jpixels; + jint *java_pixels; + guchar *gdk_pixels; + GdkPixbuf *pixbuf_no_alpha = NULL; + GdkPixbuf *pixbuf = NULL; + +#ifndef WORDS_BIGENDIAN + int i; +#endif + + gdk_threads_enter (); + + pixbuf_no_alpha = gdk_pixbuf_get_from_drawable (NULL, + gdk_get_default_root_window (), + NULL, x, y, 0, 0, + width, height); + + pixbuf = gdk_pixbuf_add_alpha(pixbuf_no_alpha, FALSE, 0, 0, 0); + g_assert (gdk_pixbuf_get_has_alpha (pixbuf)); + + stride_bytes = gdk_pixbuf_get_rowstride (pixbuf); + n_channels = gdk_pixbuf_get_n_channels (pixbuf); + stride_pixels = stride_bytes / n_channels; + n_pixels = height * stride_pixels; + gdk_pixels = gdk_pixbuf_get_pixels (pixbuf); + + gdk_threads_leave (); + + jpixels = (*env)->NewIntArray (env, n_pixels); + + gdk_threads_enter (); + + java_pixels = (*env)->GetIntArrayElements (env, jpixels, NULL); + + memcpy (java_pixels, + gdk_pixels, + (height * stride_bytes)); + +#ifndef WORDS_BIGENDIAN + /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */ + for (i = 0; i < n_pixels; ++i) + { + java_pixels[i] = SWAPU32 ((unsigned)java_pixels[i]); + } +#endif + + g_object_unref (pixbuf); + + (*env)->ReleaseIntArrayElements (env, jpixels, java_pixels, 0); + + gdk_threads_leave (); + + return jpixels; +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c new file mode 100644 index 00000000000..918ecfd0a8e --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c @@ -0,0 +1,192 @@ +/* gnu_java_awt_GdkTextLayout.c + Copyright (C) 2004 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath 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, or (at your option) + any later version. + + GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + 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. */ + + +#include <jni.h> +#include <gtk/gtk.h> +#include "native_state.h" +#include "gdkfont.h" +#include "gnu_java_awt_peer_gtk_GdkTextLayout.h" + +struct state_table *cp_gtk_native_text_layout_state_table; + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkTextLayout_initStaticState + (JNIEnv *env, jclass clazz) +{ + NSA_TEXT_LAYOUT_INIT (env, clazz); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkTextLayout_initState + (JNIEnv *env, jobject self) +{ + struct textlayout *tl; + + gdk_threads_enter (); + + g_assert(self != NULL); + tl = g_malloc0 (sizeof (struct textlayout)); + g_assert(tl != NULL); + tl->pango_layout = pango_layout_new(gdk_pango_context_get()); + g_assert(tl->pango_layout != NULL); + NSA_SET_TEXT_LAYOUT_PTR (env, self, tl); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkTextLayout_setText + (JNIEnv *env, jobject self, jstring text) +{ + struct textlayout *tl; + gchar *str = NULL; + gint len = 0; + + gdk_threads_enter (); + + g_assert(self != NULL); + g_assert(text != NULL); + + tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, self); + g_assert(tl != NULL); + g_assert(tl->pango_layout != NULL); + + len = (*env)->GetStringUTFLength (env, text); + str = (gchar *)(*env)->GetStringUTFChars (env, text, NULL); + g_assert (str != NULL); + + pango_layout_set_text (tl->pango_layout, text, len); + + (*env)->ReleaseStringUTFChars (env, text, str); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkTextLayout_indexToPos + (JNIEnv *env, jobject self, jint idx, jdoubleArray javaPos) +{ + struct textlayout *tl; + PangoRectangle pangoPos; + jdouble *nativePos; + + gdk_threads_enter (); + + g_assert(self != NULL); + g_assert(javaPos != NULL); + + tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, self); + g_assert(tl != NULL); + g_assert(tl->pango_layout != NULL); + + g_assert((*env)->GetArrayLength (env, javaPos) == 4); + + nativePos = (*env)->GetDoubleArrayElements (env, javaPos, NULL); + + pango_layout_index_to_pos (tl->pango_layout, idx, &pangoPos); + + nativePos[0] = (jdouble) pangoPos.x; + nativePos[1] = (jdouble) pangoPos.y; + nativePos[2] = (jdouble) pangoPos.width; + nativePos[3] = (jdouble) pangoPos.height; + + (*env)->ReleaseDoubleArrayElements (env, javaPos, nativePos, 0); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkTextLayout_getExtents + (JNIEnv *env, jobject self, jdoubleArray javaInkExtents, jdoubleArray javaLogExtents) +{ + struct textlayout *tl; + PangoRectangle pangoInkExtents, pangoLogExtents; + jdouble *nativeInkExtents, *nativeLogExtents; + + gdk_threads_enter (); + + g_assert(self != NULL); + g_assert(javaInkExtents != NULL); + g_assert(javaLogExtents != NULL); + + tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, self); + g_assert(tl != NULL); + g_assert(tl->pango_layout != NULL); + + g_assert((*env)->GetArrayLength (env, javaInkExtents) == 4); + g_assert((*env)->GetArrayLength (env, javaLogExtents) == 4); + + nativeInkExtents = (*env)->GetDoubleArrayElements (env, javaInkExtents, NULL); + nativeLogExtents = (*env)->GetDoubleArrayElements (env, javaLogExtents, NULL); + + pango_layout_get_extents (tl->pango_layout, + &pangoInkExtents, &pangoLogExtents); + + nativeInkExtents[0] = (jdouble) pangoInkExtents.x; + nativeInkExtents[1] = (jdouble) pangoInkExtents.y; + nativeInkExtents[2] = (jdouble) pangoInkExtents.width; + nativeInkExtents[3] = (jdouble) pangoInkExtents.height; + + nativeLogExtents[0] = (jdouble) pangoLogExtents.x; + nativeLogExtents[1] = (jdouble) pangoLogExtents.y; + nativeLogExtents[2] = (jdouble) pangoLogExtents.width; + nativeLogExtents[3] = (jdouble) pangoLogExtents.height; + + (*env)->ReleaseDoubleArrayElements (env, javaInkExtents, nativeInkExtents, 0); + (*env)->ReleaseDoubleArrayElements (env, javaLogExtents, nativeLogExtents, 0); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkTextLayout_dispose + (JNIEnv *env, jobject self) +{ + struct textlayout *tl; + + gdk_threads_enter (); + + g_assert(self != NULL); + tl = (struct textlayout *) NSA_DEL_TEXT_LAYOUT_PTR (env, self); + g_assert(tl != NULL); + if (tl->pango_layout != NULL) + g_object_unref (tl->pango_layout); + g_free(tl); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c new file mode 100644 index 00000000000..5e8ab26c3ed --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c @@ -0,0 +1,338 @@ +/* gtkbuttonpeer.c -- Native implementation of GtkButtonPeer + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkButtonPeer.h" + +static jmethodID beginNativeRepaintID; +static jmethodID endNativeRepaintID; + +void +cp_gtk_button_init_jni (void) +{ + jclass gtkbuttonpeer; + + gtkbuttonpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkButtonPeer"); + + beginNativeRepaintID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkbuttonpeer, + "beginNativeRepaint", + "()V"); + + endNativeRepaintID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkbuttonpeer, + "endNativeRepaint", "()V"); +} + +static void block_expose_event_cb (GtkWidget *widget, + jobject peer); + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_create + (JNIEnv *env, jobject obj, jstring label) +{ + const char *c_label; + GtkWidget *eventbox; + GtkWidget *button; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + c_label = (*env)->GetStringUTFChars (env, label, NULL); + + eventbox = gtk_event_box_new (); + button = gtk_button_new_with_label (c_label); + gtk_container_add (GTK_CONTAINER (eventbox), button); + gtk_widget_show (button); + + (*env)->ReleaseStringUTFChars (env, label, c_label); + NSA_SET_PTR (env, obj, eventbox); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr; + jobject *gref; + GtkWidget *button; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + button = gtk_bin_get_child (GTK_BIN (ptr)); + + /* Button signals */ + g_signal_connect_after (G_OBJECT (button), "pressed", + G_CALLBACK (block_expose_event_cb), *gref); + + g_signal_connect_after (G_OBJECT (button), "released", + G_CALLBACK (block_expose_event_cb), *gref); + + /* Component signals */ + cp_gtk_component_connect_signals (G_OBJECT (button), gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkSetLabel + (JNIEnv *env, jobject obj, jstring jtext) +{ + const char *text; + GtkWidget *button; + GtkWidget *label; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + text = (*env)->GetStringUTFChars (env, jtext, NULL); + + button = gtk_bin_get_child (GTK_BIN (ptr)); + label = gtk_bin_get_child (GTK_BIN (button)); + gtk_label_set_text (GTK_LABEL (label), text); + + (*env)->ReleaseStringUTFChars (env, jtext, text); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkWidgetModifyFont + (JNIEnv *env, jobject obj, jstring name, jint style, jint size) +{ + const char *font_name; + void *ptr; + GtkWidget *button; + GtkWidget *label; + PangoFontDescription *font_desc; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, obj); + + font_name = (*env)->GetStringUTFChars (env, name, NULL); + + button = gtk_bin_get_child (GTK_BIN (ptr)); + label = gtk_bin_get_child (GTK_BIN (button)); + + font_desc = pango_font_description_from_string (font_name); + pango_font_description_set_size (font_desc, + size * cp_gtk_dpi_conversion_factor); + + if (style & AWT_STYLE_BOLD) + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + + if (style & AWT_STYLE_ITALIC) + pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); + + gtk_widget_modify_font (GTK_WIDGET(label), font_desc); + + pango_font_description_free (font_desc); + + (*env)->ReleaseStringUTFChars (env, name, font_name); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkWidgetSetBackground + (JNIEnv *env, jobject obj, jint red, jint green, jint blue) +{ + GdkColor normal_color; + GdkColor prelight_color; + GdkColor active_color; + int prelight_red; + int prelight_blue; + int prelight_green; + GtkWidget *button; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + normal_color.red = (red / 255.0) * 65535; + normal_color.green = (green / 255.0) * 65535; + normal_color.blue = (blue / 255.0) * 65535; + + /* This calculation only approximate the active color produced by + Sun's AWT. */ + active_color.red = 0.85 * (red / 255.0) * 65535; + active_color.green = 0.85 * (green / 255.0) * 65535; + active_color.blue = 0.85 * (blue / 255.0) * 65535; + + /* There is no separate prelight color in Motif. */ + prelight_red = 1.15 * (red / 255.0) * 65535; + prelight_green = 1.15 * (green / 255.0) * 65535; + prelight_blue = 1.15 * (blue / 255.0) * 65535; + + prelight_color.red = prelight_red > 65535 ? 65535 : prelight_red; + prelight_color.green = prelight_green > 65535 ? 65535 : prelight_green; + prelight_color.blue = prelight_blue > 65535 ? 65535 : prelight_blue; + + button = gtk_bin_get_child (GTK_BIN (ptr)); + + gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &normal_color); + gtk_widget_modify_bg (button, GTK_STATE_ACTIVE, &active_color); + gtk_widget_modify_bg (button, GTK_STATE_PRELIGHT, &prelight_color); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkWidgetSetForeground + (JNIEnv *env, jobject obj, jint red, jint green, jint blue) +{ + GdkColor color; + GtkWidget *button; + GtkWidget *label; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + color.red = (red / 255.0) * 65535; + color.green = (green / 255.0) * 65535; + color.blue = (blue / 255.0) * 65535; + + button = gtk_bin_get_child (GTK_BIN (ptr)); + label = gtk_bin_get_child (GTK_BIN (button)); + + gtk_widget_modify_fg (label, GTK_STATE_NORMAL, &color); + gtk_widget_modify_fg (label, GTK_STATE_ACTIVE, &color); + gtk_widget_modify_fg (label, GTK_STATE_PRELIGHT, &color); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkActivate + (JNIEnv *env, jobject obj) +{ + GtkWidget *button; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + button = gtk_bin_get_child (GTK_BIN (ptr)); + gtk_widget_activate (GTK_WIDGET (button)); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkWidgetRequestFocus + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkWidget *button; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + button = gtk_bin_get_child (GTK_BIN (ptr)); + gtk_widget_grab_focus (button); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_setNativeBounds + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + GtkWidget *widget, *child; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + widget = GTK_WIDGET (ptr); + + /* We assume that -1 is a width or height and not a request for the + widget's natural size. */ + width = width < 0 ? 0 : width; + height = height < 0 ? 0 : height; + child = gtk_bin_get_child (GTK_BIN (widget)); + + if (!(width == 0 && height == 0)) + { + /* Set the event box's size request... */ + gtk_widget_set_size_request (widget, width, height); + /* ...and the button's size request... */ + gtk_widget_set_size_request (child, width, height); + /* ...and the label's size request. */ + gtk_widget_set_size_request (gtk_bin_get_child (GTK_BIN (child)), width, + height); + if (widget->parent != NULL) + gtk_fixed_move (GTK_FIXED (widget->parent), widget, x, y); + } + + gdk_threads_leave (); +} + +static void +block_expose_event_cb (GtkWidget *widget, jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + beginNativeRepaintID); + + gdk_threads_enter (); + + gdk_window_process_updates (widget->window, TRUE); + + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + endNativeRepaintID); + + gdk_threads_enter (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCanvasPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCanvasPeer.c new file mode 100644 index 00000000000..52922ddb82e --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCanvasPeer.c @@ -0,0 +1,58 @@ +/* gtkcanvaspeer.c -- Native implementation of GtkCanvasPeer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkCanvasPeer.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCanvasPeer_create + (JNIEnv *env, jobject obj) +{ + gpointer widget; + + gdk_threads_enter (); + + /* Create global reference and save it for future use */ + NSA_SET_GLOBAL_REF (env, obj); + + widget = gtk_type_new (gtk_drawing_area_get_type ()); + + NSA_SET_PTR (env, obj, widget); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c new file mode 100644 index 00000000000..4f28750921b --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c @@ -0,0 +1,77 @@ +/* gtkcheckboxgrouppeer.c -- Native implementation of GtkCheckboxGroupPeer + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer_dispose + (JNIEnv *env, jobject obj) +{ + /* The actual underlying widget is owned by a different class. So + we just clean up the hash table here. */ + NSA_DEL_PTR (env, obj); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer_remove + (JNIEnv *env, jobject obj, jobject checkbox) +{ + GtkRadioButton *button; + void *ptr; + GSList *list; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, checkbox); + button = GTK_RADIO_BUTTON (ptr); + + /* Update the group to point to some other widget in the group. We + have to do this because Gtk doesn't have a separate object to + represent a radio button's group. */ + for (list = gtk_radio_button_group (button); list != NULL; + list = list->next) + { + if (list->data != button) + break; + } + + NSA_SET_PTR (env, obj, list ? list->data : NULL); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer.c new file mode 100644 index 00000000000..77836cedd1e --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer.c @@ -0,0 +1,78 @@ +/* gtkmenuitempeer.c -- Native implementation of GtkMenuItemPeer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer_create + (JNIEnv *env, jobject obj, jstring label) +{ + GtkWidget *widget; + const char *str; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + str = (*env)->GetStringUTFChars (env, label, NULL); + + widget = gtk_check_menu_item_new_with_label (str); + gtk_widget_show (widget); + + (*env)->ReleaseStringUTFChars (env, label, str); + + NSA_SET_PTR (env, obj, widget); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer_setState + (JNIEnv *env, jobject obj, jboolean state) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (ptr), state); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c new file mode 100644 index 00000000000..cf883dd3307 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c @@ -0,0 +1,240 @@ +/* gtkcheckboxpeer.c -- Native implementation of GtkCheckboxPeer + Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkCheckboxPeer.h" +#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h" + +static jmethodID postItemEventID; + +void +cp_gtk_checkbox_init_jni (void) +{ + jclass gtkcheckboxpeer; + + gtkcheckboxpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkCheckboxPeer"); + + postItemEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcheckboxpeer, + "postItemEvent", + "(Ljava/lang/Object;I)V"); +} + +static void item_toggled_cb (GtkToggleButton *item, jobject peer); + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_create + (JNIEnv *env, jobject obj, jobject group) +{ + GtkWidget *button; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + if (group == NULL) + button = gtk_check_button_new_with_label (""); + else + { + void *native_group = NSA_GET_PTR (env, group); + button = gtk_radio_button_new_with_label_from_widget (native_group, ""); + if (native_group == NULL) + { + /* Set the native group so we can use the correct value the + next time around. FIXME: this doesn't work! */ + NSA_SET_PTR (env, group, button); + } + } + + NSA_SET_PTR (env, obj, button); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr = NULL; + jobject *gref = NULL; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + /* Checkbox signals */ + g_signal_connect (G_OBJECT (ptr), "toggled", + G_CALLBACK (item_toggled_cb), *gref); + + /* Component signals */ + cp_gtk_component_connect_signals (G_OBJECT (ptr), gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_nativeSetCheckboxGroup + (JNIEnv *env, jobject obj, jobject group) +{ + GtkRadioButton *button; + void *native_group, *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + /* FIXME: we can't yet switch between a checkbutton and a + radiobutton. However, AWT requires this. For now we just + crash. */ + + button = GTK_RADIO_BUTTON (ptr); + + native_group = NSA_GET_PTR (env, group); + if (native_group == NULL) + gtk_radio_button_set_group (button, NULL); + else + gtk_radio_button_set_group (button, + gtk_radio_button_group + (GTK_RADIO_BUTTON (native_group))); + + /* If the native group wasn't set on the new CheckboxGroup, then set + it now so that the right thing will happen with the next + radiobutton. The native state for a CheckboxGroup is a pointer + to one of the widgets in the group. We are careful to keep this + always pointing at a live widget; whenever a widget is destroyed + (or otherwise removed from the group), the CheckboxGroup peer is + notified. */ + if (native_group == NULL) + NSA_SET_PTR (env, group, native_group); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkToggleButtonSetActive + (JNIEnv *env, jobject obj, jboolean is_active) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptr), is_active); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkWidgetModifyFont + (JNIEnv *env, jobject obj, jstring name, jint style, jint size) +{ + const char *font_name; + void *ptr; + GtkWidget *button; + GtkWidget *label; + PangoFontDescription *font_desc; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, obj); + + button = GTK_WIDGET (ptr); + label = gtk_bin_get_child (GTK_BIN(button)); + + if (!label) + return; + + font_name = (*env)->GetStringUTFChars (env, name, NULL); + + font_desc = pango_font_description_from_string (font_name); + pango_font_description_set_size (font_desc, + size * cp_gtk_dpi_conversion_factor); + + if (style & AWT_STYLE_BOLD) + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + + if (style & AWT_STYLE_ITALIC) + pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); + + gtk_widget_modify_font (GTK_WIDGET(label), font_desc); + + pango_font_description_free (font_desc); + + (*env)->ReleaseStringUTFChars (env, name, font_name); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkButtonSetLabel + (JNIEnv *env, jobject obj, jstring label) +{ + const char *c_label; + GtkWidget *label_widget; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + c_label = (*env)->GetStringUTFChars (env, label, NULL); + + label_widget = gtk_bin_get_child (GTK_BIN (ptr)); + gtk_label_set_text (GTK_LABEL (label_widget), c_label); + + (*env)->ReleaseStringUTFChars (env, label, c_label); + + gdk_threads_leave (); +} + +static void +item_toggled_cb (GtkToggleButton *item, jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postItemEventID, + peer, + item->active ? + (jint) AWT_ITEM_SELECTED : + (jint) AWT_ITEM_DESELECTED); + + gdk_threads_enter (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c new file mode 100644 index 00000000000..ed9df543332 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c @@ -0,0 +1,248 @@ +/* gtkchoicepeer.c -- Native implementation of GtkChoicePeer + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkChoicePeer.h" + +static jmethodID postChoiceItemEventID; + +void +cp_gtk_choice_init_jni (void) +{ + jclass gtkchoicepeer; + + gtkchoicepeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkChoicePeer"); + + postChoiceItemEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkchoicepeer, + "postChoiceItemEvent", + "(Ljava/lang/String;I)V"); +} + +static void selection_changed_cb (GtkComboBox *combobox, jobject peer); + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkChoicePeer_create + (JNIEnv *env, jobject obj) +{ + GtkWidget *combobox; + jobject *gref; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + combobox = gtk_combo_box_new_text (); + + NSA_SET_PTR (env, obj, combobox); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkChoicePeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr = NULL; + jobject *gref = NULL; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + /* Choice signals */ + g_signal_connect (G_OBJECT (ptr), "changed", + G_CALLBACK (selection_changed_cb), *gref); + + /* Component signals */ + cp_gtk_component_connect_signals (G_OBJECT (ptr), gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkChoicePeer_append + (JNIEnv *env, jobject obj, jobjectArray items) +{ + gpointer ptr; + jsize count, i; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + count = (*env)->GetArrayLength (env, items); + + for (i = 0; i < count; i++) + { + jobject item; + const char *label; + + item = (*env)->GetObjectArrayElement (env, items, i); + label = (*env)->GetStringUTFChars (env, item, NULL); + + gtk_combo_box_append_text (GTK_COMBO_BOX (ptr), label); + + (*env)->ReleaseStringUTFChars (env, item, label); + } + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeAdd + (JNIEnv *env, jobject obj, jstring item, jint index) +{ + void *ptr; + const char *label; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + label = (*env)->GetStringUTFChars (env, item, 0); + + gtk_combo_box_insert_text (GTK_COMBO_BOX (ptr), index, label); + + (*env)->ReleaseStringUTFChars (env, item, label); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemove + (JNIEnv *env, jobject obj, jint index) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_combo_box_remove_text (GTK_COMBO_BOX (ptr), index); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemoveAll + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkTreeModel *model; + gint count, i; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (ptr)); + count = gtk_tree_model_iter_n_children (model, NULL); + + /* First, unselect everything, to avoid problems when removing items. */ + gtk_combo_box_set_active (GTK_COMBO_BOX (ptr), -1); + + for (i = count - 1; i >= 0; i--) { + gtk_combo_box_remove_text (GTK_COMBO_BOX (ptr), i); + } + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkChoicePeer_select + (JNIEnv *env, jobject obj, jint index) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_combo_box_set_active (GTK_COMBO_BOX (ptr), index); + + gdk_threads_leave (); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeGetSelected + (JNIEnv *env, jobject obj) +{ + void *ptr; + int index; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + index = gtk_combo_box_get_active (GTK_COMBO_BOX (ptr)); + + gdk_threads_leave (); + + return index; +} + +static void selection_changed_cb (GtkComboBox *combobox, jobject peer) +{ + jstring label; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *selected; + gint index; + + index = gtk_combo_box_get_active(combobox); + + if (index >= 0) + { + model = gtk_combo_box_get_model (combobox); + gtk_combo_box_get_active_iter (combobox, &iter); + gtk_tree_model_get (model, &iter, 0, &selected, -1); + label = (*cp_gtk_gdk_env())->NewStringUTF (cp_gtk_gdk_env(), selected); + + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postChoiceItemEventID, + label, + (jint) AWT_ITEM_SELECTED); + + gdk_threads_enter (); + } +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c new file mode 100644 index 00000000000..dea9d4cc7c2 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c @@ -0,0 +1,204 @@ +/* gtkclipboard.c + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkClipboard.h" + +static jmethodID stringSelectionReceivedID; +static jmethodID stringSelectionHandlerID; +static jmethodID selectionClearID; + +static void selection_received_cb (GtkWidget *, GtkSelectionData *, + guint, gpointer); +static void selection_get_cb (GtkWidget *, GtkSelectionData *, guint, + guint, gpointer); +static gint selection_clear_cb (GtkWidget *, GdkEventSelection *); + +static GtkWidget *clipboard; +static jobject cb_obj; + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkClipboard_initNativeState (JNIEnv *env, + jobject obj) +{ + gdk_threads_enter (); + + if (!stringSelectionReceivedID) + { + jclass gtkclipboard; + + gtkclipboard = (*env)->FindClass (env, + "gnu/java/awt/peer/gtk/GtkClipboard"); + stringSelectionReceivedID = (*env)->GetMethodID (env, gtkclipboard, + "stringSelectionReceived", + "(Ljava/lang/String;)V"); + stringSelectionHandlerID = (*env)->GetMethodID (env, gtkclipboard, + "stringSelectionHandler", + "()Ljava/lang/String;"); + selectionClearID = (*env)->GetMethodID (env, gtkclipboard, + "selectionClear", "()V"); + } + + cb_obj = (*env)->NewGlobalRef (env, obj); + + clipboard = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + g_signal_connect (G_OBJECT(clipboard), "selection_received", + G_CALLBACK (selection_received_cb), NULL); + + g_signal_connect (G_OBJECT(clipboard), "selection_clear_event", + G_CALLBACK (selection_clear_cb), NULL); + + gtk_selection_add_target (clipboard, GDK_SELECTION_PRIMARY, + GDK_TARGET_STRING, 0); + + g_signal_connect (G_OBJECT(clipboard), "selection_get", + G_CALLBACK (selection_get_cb), NULL); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkClipboard_requestStringConversion + (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused))) +{ + gdk_threads_enter (); + + gtk_selection_convert (clipboard, GDK_SELECTION_PRIMARY, + GDK_TARGET_STRING, GDK_CURRENT_TIME); + + gdk_threads_leave (); +} + +static void +selection_received_cb (GtkWidget *widget __attribute__((unused)), + GtkSelectionData *selection_data __attribute__((unused)), + guint time __attribute__((unused)), + gpointer data __attribute__((unused))) +{ + /* Check to see if retrieval succeeded */ + if (selection_data->length < 0 + || selection_data->type != GDK_SELECTION_TYPE_STRING) + { + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), cb_obj, stringSelectionReceivedID, + NULL); + + gdk_threads_enter (); + } + else + { + char *str = (char *) selection_data->data; + + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), cb_obj, stringSelectionReceivedID, + (*cp_gtk_gdk_env())->NewStringUTF (cp_gtk_gdk_env(), str)); + + gdk_threads_enter (); + } + + return; +} + +static void +selection_get_cb (GtkWidget *widget __attribute__((unused)), + GtkSelectionData *selection_data, + guint info __attribute__((unused)), + guint time __attribute__((unused)), + gpointer data __attribute__((unused))) +{ + jstring jstr; + const char *utf; + jsize utflen; + + gdk_threads_leave (); + + jstr = (*cp_gtk_gdk_env())->CallObjectMethod (cp_gtk_gdk_env(), cb_obj, + stringSelectionHandlerID); + + gdk_threads_enter (); + + if (!jstr) + { + gtk_selection_data_set (selection_data, + GDK_TARGET_STRING, 8, NULL, 0); + return; + } + + utflen = (*cp_gtk_gdk_env())->GetStringUTFLength (cp_gtk_gdk_env(), jstr); + utf = (*cp_gtk_gdk_env())->GetStringUTFChars (cp_gtk_gdk_env(), jstr, NULL); + + gtk_selection_data_set (selection_data, GDK_TARGET_STRING, 8, + (const unsigned char*)utf, utflen); + + (*cp_gtk_gdk_env())->ReleaseStringUTFChars (cp_gtk_gdk_env(), jstr, utf); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkClipboard_selectionGet + (JNIEnv *env, jclass clazz __attribute__((unused))) +{ + GdkWindow *owner; + + gdk_threads_enter (); + + /* if we already own the clipboard, we need to tell the old data object + that we're no longer going to be using him */ + owner = gdk_selection_owner_get (GDK_SELECTION_PRIMARY); + if (owner && owner == clipboard->window) + (*env)->CallVoidMethod (env, cb_obj, selectionClearID); + + gtk_selection_owner_set (clipboard, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); + + gdk_threads_leave (); +} + +static gint +selection_clear_cb (GtkWidget *widget __attribute__((unused)), + GdkEventSelection *event __attribute__((unused))) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), cb_obj, selectionClearID); + + gdk_threads_enter (); + + return TRUE; +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c new file mode 100644 index 00000000000..bd9dde39283 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c @@ -0,0 +1,1161 @@ +/* gtkcomponentpeer.c -- Native implementation of GtkComponentPeer + Copyright (C) 1998, 1999, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h" + +#include <gtk/gtkprivate.h> + +#define AWT_DEFAULT_CURSOR 0 +#define AWT_CROSSHAIR_CURSOR 1 +#define AWT_TEXT_CURSOR 2 +#define AWT_WAIT_CURSOR 3 +#define AWT_SW_RESIZE_CURSOR 4 +#define AWT_SE_RESIZE_CURSOR 5 +#define AWT_NW_RESIZE_CURSOR 6 +#define AWT_NE_RESIZE_CURSOR 7 +#define AWT_N_RESIZE_CURSOR 8 +#define AWT_S_RESIZE_CURSOR 9 +#define AWT_W_RESIZE_CURSOR 10 +#define AWT_E_RESIZE_CURSOR 11 +#define AWT_HAND_CURSOR 12 +#define AWT_MOVE_CURSOR 13 + +#define AWT_BUTTON1_DOWN_MASK (1 << 10) +#define AWT_BUTTON2_DOWN_MASK (1 << 11) +#define AWT_BUTTON3_DOWN_MASK (1 << 12) + +/* FIXME: use gtk-double-click-time, gtk-double-click-distance */ +#define MULTI_CLICK_TIME 250 +/* as opposed to a MULTI_PASS_TIME :) */ + +#define AWT_MOUSE_CLICKED 500 +#define AWT_MOUSE_PRESSED 501 +#define AWT_MOUSE_RELEASED 502 +#define AWT_MOUSE_MOVED 503 +#define AWT_MOUSE_ENTERED 504 +#define AWT_MOUSE_EXITED 505 +#define AWT_MOUSE_DRAGGED 506 + +#define AWT_FOCUS_GAINED 1004 +#define AWT_FOCUS_LOST 1005 + +static GtkWidget *find_fg_color_widget (GtkWidget *widget); +static GtkWidget *find_bg_color_widget (GtkWidget *widget); + +static jmethodID postMouseEventID; +static jmethodID setCursorID; +static jmethodID postExposeEventID; +static jmethodID postFocusEventID; + +void +cp_gtk_component_init_jni (void) + { + jclass gtkcomponentpeer; + + gtkcomponentpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkComponentPeer"); + + postMouseEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer, + "postMouseEvent", "(IJIIIIZ)V"); + + setCursorID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer, + "setCursor", "()V"); + + postExposeEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer, + "postExposeEvent", "(IIII)V"); + + postFocusEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer, + "postFocusEvent", "(IZ)V"); +} + +static gboolean component_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + jobject peer); +static gboolean component_button_release_cb (GtkWidget *widget, + GdkEventButton *event, + jobject peer); +static gboolean component_motion_notify_cb (GtkWidget *widget, + GdkEventMotion *event, + jobject peer); +static gboolean component_enter_notify_cb (GtkWidget *widget, + GdkEventCrossing *event, + jobject peer); +static gboolean component_leave_notify_cb (GtkWidget *widget, + GdkEventCrossing *event, + jobject peer); +static gboolean component_expose_cb (GtkWidget *widget, + GdkEventExpose *event, + jobject peer); +static gboolean component_focus_in_cb (GtkWidget *widget, + GdkEventFocus *event, + jobject peer); +static gboolean component_focus_out_cb (GtkWidget *widget, + GdkEventFocus *event, + jobject peer); + +static jint +button_to_awt_mods (int button) +{ + switch (button) + { + case 1: + return AWT_BUTTON1_MASK; + case 2: + return AWT_BUTTON2_MASK; + case 3: + return AWT_BUTTON3_MASK; + } + + return 0; +} + +static jint +state_to_awt_mods (guint state) +{ + jint result = 0; + + if (state & GDK_SHIFT_MASK) + result |= AWT_SHIFT_DOWN_MASK; + if (state & GDK_CONTROL_MASK) + result |= AWT_CTRL_DOWN_MASK; + if (state & GDK_MOD1_MASK) + result |= AWT_ALT_DOWN_MASK; + + return result; +} + +static jint +state_to_awt_mods_with_button_states (guint state) +{ + jint result = 0; + + if (state & GDK_SHIFT_MASK) + result |= AWT_SHIFT_DOWN_MASK; + if (state & GDK_CONTROL_MASK) + result |= AWT_CTRL_DOWN_MASK; + if (state & GDK_MOD1_MASK) + result |= AWT_ALT_DOWN_MASK; + if (state & GDK_BUTTON1_MASK) + result |= AWT_BUTTON1_DOWN_MASK; + if (state & GDK_BUTTON2_MASK) + result |= AWT_BUTTON2_DOWN_MASK; + if (state & GDK_BUTTON3_MASK) + result |= AWT_BUTTON3_DOWN_MASK; + + return result; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursor + (JNIEnv *env, jobject obj, jint type) +{ + void *ptr; + GtkWidget *widget; + GdkCursorType gdk_cursor_type; + GdkCursor *gdk_cursor; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + switch (type) + { + case AWT_CROSSHAIR_CURSOR: + gdk_cursor_type = GDK_CROSSHAIR; + break; + case AWT_TEXT_CURSOR: + gdk_cursor_type = GDK_XTERM; + break; + case AWT_WAIT_CURSOR: + gdk_cursor_type = GDK_WATCH; + break; + case AWT_SW_RESIZE_CURSOR: + gdk_cursor_type = GDK_BOTTOM_LEFT_CORNER; + break; + case AWT_SE_RESIZE_CURSOR: + gdk_cursor_type = GDK_BOTTOM_RIGHT_CORNER; + break; + case AWT_NW_RESIZE_CURSOR: + gdk_cursor_type = GDK_TOP_LEFT_CORNER; + break; + case AWT_NE_RESIZE_CURSOR: + gdk_cursor_type = GDK_TOP_RIGHT_CORNER; + break; + case AWT_N_RESIZE_CURSOR: + gdk_cursor_type = GDK_TOP_SIDE; + break; + case AWT_S_RESIZE_CURSOR: + gdk_cursor_type = GDK_BOTTOM_SIDE; + break; + case AWT_W_RESIZE_CURSOR: + gdk_cursor_type = GDK_LEFT_SIDE; + break; + case AWT_E_RESIZE_CURSOR: + gdk_cursor_type = GDK_RIGHT_SIDE; + break; + case AWT_HAND_CURSOR: + gdk_cursor_type = GDK_HAND2; + break; + case AWT_MOVE_CURSOR: + gdk_cursor_type = GDK_FLEUR; + break; + default: + gdk_cursor_type = GDK_LEFT_PTR; + } + + widget = GTK_WIDGET(ptr); + + gdk_cursor = gdk_cursor_new (gdk_cursor_type); + gdk_window_set_cursor (widget->window, gdk_cursor); + gdk_cursor_destroy (gdk_cursor); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetParent + (JNIEnv *env, jobject obj, jobject parent) +{ + void *ptr; + void *parent_ptr; + GtkWidget *widget; + GtkWidget *parent_widget; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + parent_ptr = NSA_GET_PTR (env, parent); + + widget = GTK_WIDGET (ptr); + parent_widget = GTK_WIDGET (parent_ptr); + + if (widget->parent == NULL) + { + if (GTK_IS_WINDOW (parent_widget)) + { + GList *children = gtk_container_children + (GTK_CONTAINER (parent_widget)); + + if (GTK_IS_MENU_BAR (children->data)) + gtk_fixed_put (GTK_FIXED (children->next->data), widget, 0, 0); + else + gtk_fixed_put (GTK_FIXED (children->data), widget, 0, 0); + } + else + if (GTK_IS_SCROLLED_WINDOW (parent_widget)) + { + gtk_scrolled_window_add_with_viewport + (GTK_SCROLLED_WINDOW (parent_widget), widget); + gtk_viewport_set_shadow_type (GTK_VIEWPORT (widget->parent), + GTK_SHADOW_NONE); + + } + else + { + if (widget->parent == NULL) + gtk_fixed_put (GTK_FIXED (parent_widget), widget, 0, 0); + } + } + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetSensitive + (JNIEnv *env, jobject obj, jboolean sensitive) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_widget_set_sensitive (GTK_WIDGET (ptr), sensitive); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus + (JNIEnv *env, jobject obj) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_widget_grab_focus (GTK_WIDGET (ptr)); + + gdk_threads_leave (); +} + +/* + * Translate a Java KeyEvent object into a GdkEventKey event, then + * pass it to the GTK main loop for processing. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetDispatchKeyEvent + (JNIEnv *env, jobject obj, jint id, jlong when, jint mods, + jint keyCode, jint keyLocation) +{ + void *ptr; + GdkEvent *event = NULL; + GdkKeymapKey *keymap_keys = NULL; + gint n_keys = 0; + guint lookup_keyval = 0; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + if (id == AWT_KEY_PRESSED) + event = gdk_event_new (GDK_KEY_PRESS); + else if (id == AWT_KEY_RELEASED) + event = gdk_event_new (GDK_KEY_RELEASE); + else + { + gdk_threads_leave (); + /* Don't send AWT KEY_TYPED events to GTK. */ + return; + } + + if (GTK_IS_BUTTON (ptr)) + event->key.window = GTK_BUTTON (ptr)->event_window; + else if (GTK_IS_SCROLLED_WINDOW (ptr)) + event->key.window = GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child)->window; + else + event->key.window = GTK_WIDGET (ptr)->window; + + event->key.send_event = 0; + event->key.time = (guint32) when; + + if (mods & AWT_SHIFT_DOWN_MASK) + event->key.state |= GDK_SHIFT_MASK; + if (mods & AWT_CTRL_DOWN_MASK) + event->key.state |= GDK_CONTROL_MASK; + if (mods & AWT_ALT_DOWN_MASK) + event->key.state |= GDK_MOD1_MASK; + + /* This hack is needed because the AWT has no notion of num lock. + It infers numlock state from the only Java virtual keys that are + affected by it. */ + if (keyCode == VK_NUMPAD9 + || keyCode == VK_NUMPAD8 + || keyCode == VK_NUMPAD7 + || keyCode == VK_NUMPAD6 + || keyCode == VK_NUMPAD5 + || keyCode == VK_NUMPAD4 + || keyCode == VK_NUMPAD3 + || keyCode == VK_NUMPAD2 + || keyCode == VK_NUMPAD1 + || keyCode == VK_NUMPAD0 + || keyCode == VK_DECIMAL) + event->key.state |= GDK_MOD2_MASK; + + /* These values don't need to be filled in since GTK doesn't use + them. */ + event->key.length = 0; + event->key.string = NULL; + + lookup_keyval = cp_gtk_awt_keycode_to_keysym (keyCode, keyLocation); + + if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), + lookup_keyval, + &keymap_keys, + &n_keys)) + { + /* No matching keymap entry was found. */ + g_printerr ("No matching keymap entries were found\n"); + gdk_threads_leave (); + return; + } + + /* Note: if n_keys > 1 then there are multiple hardware keycodes + that translate to lookup_keyval. We arbitrarily choose the first + hardware keycode from the list returned by + gdk_keymap_get_entries_for_keyval. */ + + event->key.hardware_keycode = keymap_keys[0].keycode; + event->key.group = keymap_keys[0].group; + + g_free (keymap_keys); + + if (!gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (), + event->key.hardware_keycode, + event->key.state, + event->key.group, + &event->key.keyval, + NULL, NULL, NULL)) + { + /* No matching keyval was found. */ + g_printerr ("No matching keyval was found\n"); + gdk_threads_leave (); + return; + } + + /* keyevent = (GdkEventKey *) event; */ + /* g_printerr ("generated event: sent: %d time: %d state: %d keyval: %d length: %d string: %s hardware_keycode: %d group: %d\n", keyevent->send_event, keyevent->time, keyevent->state, keyevent->keyval, keyevent->length, keyevent->string, keyevent->hardware_keycode, keyevent->group); */ + + /* We already received the original key event on the window itself, + so we don't want to resend it. */ + if (!GTK_IS_WINDOW (ptr)) + { + if (GTK_IS_SCROLLED_WINDOW (ptr)) + gtk_widget_event (GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child), event); + else + gtk_widget_event (GTK_WIDGET (ptr), event); + } + + gdk_threads_leave (); +} + +/* + * Find the origin of a widget's window. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetLocationOnScreen + (JNIEnv * env, jobject obj, jintArray jpoint) +{ + void *ptr; + jint *point; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + point = (*env)->GetIntArrayElements (env, jpoint, 0); + + gdk_window_get_origin (GTK_WIDGET (ptr)->window, point, point+1); + + if (!GTK_IS_CONTAINER (ptr)) + { + *point += GTK_WIDGET(ptr)->allocation.x; + *(point+1) += GTK_WIDGET(ptr)->allocation.y; + } + + (*env)->ReleaseIntArrayElements(env, jpoint, point, 0); + + gdk_threads_leave (); +} + +/* + * Find this widget's current size. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetDimensions + (JNIEnv *env, jobject obj, jintArray jdims) +{ + void *ptr; + jint *dims; + GtkRequisition requisition; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + dims = (*env)->GetIntArrayElements (env, jdims, 0); + dims[0] = dims[1] = 0; + + gtk_widget_size_request (GTK_WIDGET (ptr), &requisition); + + dims[0] = requisition.width; + dims[1] = requisition.height; + + (*env)->ReleaseIntArrayElements (env, jdims, dims, 0); + + gdk_threads_leave (); +} + +/* + * Find this widget's preferred size. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetPreferredDimensions + (JNIEnv *env, jobject obj, jintArray jdims) +{ + void *ptr; + jint *dims; + GtkRequisition current_req; + GtkRequisition natural_req; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + dims = (*env)->GetIntArrayElements (env, jdims, 0); + dims[0] = dims[1] = 0; + + /* Widgets that extend GtkWindow such as GtkFileChooserDialog may have + a default size. These values seem more useful then the natural + requisition values, particularly for GtkFileChooserDialog. */ + if (GTK_IS_WINDOW (ptr)) + { + gint width, height; + gtk_window_get_default_size (GTK_WINDOW (ptr), &width, &height); + + dims[0] = width; + dims[1] = height; + } + else + { + /* Save the widget's current size request. */ + gtk_widget_size_request (GTK_WIDGET (ptr), ¤t_req); + + /* Get the widget's "natural" size request. */ + gtk_widget_set_size_request (GTK_WIDGET (ptr), -1, -1); + gtk_widget_size_request (GTK_WIDGET (ptr), &natural_req); + + /* Reset the widget's size request. */ + gtk_widget_set_size_request (GTK_WIDGET (ptr), + current_req.width, current_req.height); + + dims[0] = natural_req.width; + dims[1] = natural_req.height; + } + + (*env)->ReleaseIntArrayElements (env, jdims, dims, 0); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeBounds + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + GtkWidget *widget; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + widget = GTK_WIDGET (ptr); + + /* We assume that -1 is a width or height and not a request for the + widget's natural size. */ + width = width < 0 ? 0 : width; + height = height < 0 ? 0 : height; + + if (GTK_IS_VIEWPORT (widget->parent)) + gtk_widget_set_size_request (widget, width, height); + else + { + if (!(width == 0 && height == 0)) + { + gtk_widget_set_size_request (widget, width, height); + if (widget->parent != NULL) + gtk_fixed_move (GTK_FIXED (widget->parent), widget, x, y); + } + } + + gdk_threads_leave (); +} + +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetBackground + (JNIEnv *env, jobject obj) +{ + void *ptr; + jintArray array; + int *rgb; + GdkColor bg; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + bg = GTK_WIDGET (ptr)->style->bg[GTK_STATE_NORMAL]; + + gdk_threads_leave (); + + array = (*env)->NewIntArray (env, 3); + + gdk_threads_enter (); + + rgb = (*env)->GetIntArrayElements (env, array, NULL); + /* convert color data from 16 bit values down to 8 bit values */ + rgb[0] = bg.red >> 8; + rgb[1] = bg.green >> 8; + rgb[2] = bg.blue >> 8; + (*env)->ReleaseIntArrayElements (env, array, rgb, 0); + + gdk_threads_leave (); + + return array; +} + +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetForeground + (JNIEnv *env, jobject obj) +{ + void *ptr; + jintArray array; + jint *rgb; + GdkColor fg; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + fg = GTK_WIDGET (ptr)->style->fg[GTK_STATE_NORMAL]; + + gdk_threads_leave (); + + array = (*env)->NewIntArray (env, 3); + + gdk_threads_enter (); + + rgb = (*env)->GetIntArrayElements (env, array, NULL); + /* convert color data from 16 bit values down to 8 bit values */ + rgb[0] = fg.red >> 8; + rgb[1] = fg.green >> 8; + rgb[2] = fg.blue >> 8; + (*env)->ReleaseIntArrayElements (env, array, rgb, 0); + + gdk_threads_leave (); + + return array; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetBackground + (JNIEnv *env, jobject obj, jint red, jint green, jint blue) +{ + GdkColor normal_color; + GdkColor active_color; + GtkWidget *widget; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + normal_color.red = (red / 255.0) * 65535; + normal_color.green = (green / 255.0) * 65535; + normal_color.blue = (blue / 255.0) * 65535; + + /* This calculation only approximates the active colors produced by + Sun's AWT. */ + active_color.red = 0.85 * (red / 255.0) * 65535; + active_color.green = 0.85 * (green / 255.0) * 65535; + active_color.blue = 0.85 * (blue / 255.0) * 65535; + + widget = find_bg_color_widget (GTK_WIDGET (ptr)); + + gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &normal_color); + gtk_widget_modify_bg (widget, GTK_STATE_ACTIVE, &active_color); + gtk_widget_modify_bg (widget, GTK_STATE_PRELIGHT, &normal_color); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetForeground + (JNIEnv *env, jobject obj, jint red, jint green, jint blue) +{ + GdkColor color; + GtkWidget *widget; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + color.red = (red / 255.0) * 65535; + color.green = (green / 255.0) * 65535; + color.blue = (blue / 255.0) * 65535; + + widget = find_fg_color_widget (GTK_WIDGET (ptr)); + + gtk_widget_modify_fg (widget, GTK_STATE_NORMAL, &color); + gtk_widget_modify_fg (widget, GTK_STATE_ACTIVE, &color); + gtk_widget_modify_fg (widget, GTK_STATE_PRELIGHT, &color); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_show + (JNIEnv *env, jobject obj) +{ + void *ptr; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, obj); + + gtk_widget_show (GTK_WIDGET (ptr)); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_hide + (JNIEnv *env, jobject obj) +{ + void *ptr; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, obj); + + gtk_widget_hide (GTK_WIDGET (ptr)); + + gdk_threads_leave(); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isEnabled + (JNIEnv *env, jobject obj) +{ + void *ptr; + jboolean ret_val; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + ret_val = GTK_WIDGET_IS_SENSITIVE (GTK_WIDGET (ptr)); + + gdk_threads_leave (); + + return ret_val; +} + +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isRealized + (JNIEnv *env, jobject obj) +{ + void *ptr; + jboolean ret_val; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + if (ptr == NULL) + return FALSE; + + ret_val = GTK_WIDGET_REALIZED (GTK_WIDGET (ptr)); + + gdk_threads_leave (); + + return ret_val; +} + +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_modalHasGrab + (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused))) +{ + GtkWidget *widget; + jboolean retval; + + gdk_threads_enter (); + + widget = gtk_grab_get_current (); + retval = (widget && GTK_IS_WINDOW (widget) && GTK_WINDOW (widget)->modal); + + gdk_threads_leave (); + + return retval; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr; + jobject *gref; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + cp_gtk_component_connect_signals (ptr, gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeEventMask + (JNIEnv *env, jobject obj) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_widget_add_events (GTK_WIDGET (ptr), + GDK_POINTER_MOTION_MASK + | GDK_BUTTON_MOTION_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_KEY_PRESS_MASK + | GDK_KEY_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_STRUCTURE_MASK + | GDK_KEY_PRESS_MASK + | GDK_FOCUS_CHANGE_MASK); + + gdk_threads_leave (); +} + +/* FIXME: these functions should be implemented by overridding the + appropriate GtkComponentPeer methods. */ +static GtkWidget * +find_fg_color_widget (GtkWidget *widget) +{ + GtkWidget *fg_color_widget; + + if (GTK_IS_EVENT_BOX (widget) + || (GTK_IS_BUTTON (widget) + && !GTK_IS_OPTION_MENU (widget))) + fg_color_widget = gtk_bin_get_child (GTK_BIN(widget)); + else + fg_color_widget = widget; + + return fg_color_widget; +} + +static GtkWidget * +find_bg_color_widget (GtkWidget *widget) +{ + GtkWidget *bg_color_widget; + + bg_color_widget = widget; + + return bg_color_widget; +} + +void +cp_gtk_component_connect_expose_signals (GObject *ptr, jobject *gref) +{ + g_signal_connect (G_OBJECT (ptr), "expose-event", + G_CALLBACK (component_expose_cb), *gref); +} + +void +cp_gtk_component_connect_focus_signals (GObject *ptr, jobject *gref) +{ + g_signal_connect (G_OBJECT (ptr), "focus-in-event", + G_CALLBACK (component_focus_in_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "focus-out-event", + G_CALLBACK (component_focus_out_cb), *gref); +} + +void +cp_gtk_component_connect_mouse_signals (GObject *ptr, jobject *gref) +{ + g_signal_connect (G_OBJECT (ptr), "button-press-event", + G_CALLBACK (component_button_press_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "button-release-event", + G_CALLBACK (component_button_release_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "enter-notify-event", + G_CALLBACK (component_enter_notify_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "leave-notify-event", + G_CALLBACK (component_leave_notify_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "motion-notify-event", + G_CALLBACK (component_motion_notify_cb), *gref); +} + +void +cp_gtk_component_connect_signals (GObject *ptr, jobject *gref) +{ + cp_gtk_component_connect_expose_signals (ptr, gref); + cp_gtk_component_connect_focus_signals (ptr, gref); + cp_gtk_component_connect_mouse_signals (ptr, gref); +} + +/* These variables are used to keep track of click counts. The AWT + allows more than a triple click to occur but GTK doesn't report + more-than-triple clicks. */ +static jint click_count = 1; +static guint32 button_click_time = 0; +static GdkWindow *button_window = NULL; +static guint button_number = -1; +static int hasBeenDragged; + +static gboolean +component_button_press_cb (GtkWidget *widget __attribute__((unused)), + GdkEventButton *event, + jobject peer) +{ + /* Ignore double and triple click events. */ + if (event->type == GDK_2BUTTON_PRESS + || event->type == GDK_3BUTTON_PRESS) + return FALSE; + + if ((event->time < (button_click_time + MULTI_CLICK_TIME)) + && (event->window == button_window) + && (event->button == button_number)) + click_count++; + else + click_count = 1; + + button_click_time = event->time; + button_window = event->window; + button_number = event->button; + + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postMouseEventID, + AWT_MOUSE_PRESSED, + (jlong)event->time, + state_to_awt_mods (event->state) + | button_to_awt_mods (event->button), + (jint)event->x, + (jint)event->y, + click_count, + (event->button == 3) ? JNI_TRUE : + JNI_FALSE); + + gdk_threads_enter (); + + hasBeenDragged = FALSE; + + return FALSE; +} + +static gboolean +component_button_release_cb (GtkWidget *widget __attribute__((unused)), + GdkEventButton *event, + jobject peer) +{ + int width, height; + + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postMouseEventID, + AWT_MOUSE_RELEASED, + (jlong)event->time, + state_to_awt_mods (event->state) + | button_to_awt_mods (event->button), + (jint)event->x, + (jint)event->y, + click_count, + JNI_FALSE); + + gdk_threads_enter (); + + /* Generate an AWT click event only if the release occured in the + window it was pressed in, and the mouse has not been dragged since + the last time it was pressed. */ + gdk_window_get_size (event->window, &width, &height); + if (! hasBeenDragged + && event->x >= 0 + && event->y >= 0 + && event->x <= width + && event->y <= height) + { + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postMouseEventID, + AWT_MOUSE_CLICKED, + (jlong)event->time, + state_to_awt_mods (event->state) + | button_to_awt_mods (event->button), + (jint)event->x, + (jint)event->y, + click_count, + JNI_FALSE); + + gdk_threads_enter (); + } + return FALSE; +} + +static gboolean +component_motion_notify_cb (GtkWidget *widget __attribute__((unused)), + GdkEventMotion *event, + jobject peer) +{ + if (event->state & (GDK_BUTTON1_MASK + | GDK_BUTTON2_MASK + | GDK_BUTTON3_MASK + | GDK_BUTTON4_MASK + | GDK_BUTTON5_MASK)) + { + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postMouseEventID, + AWT_MOUSE_DRAGGED, + (jlong)event->time, + state_to_awt_mods_with_button_states (event->state), + (jint)event->x, + (jint)event->y, + 0, + JNI_FALSE); + + gdk_threads_enter (); + + hasBeenDragged = TRUE; + } + else + { + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postMouseEventID, + AWT_MOUSE_MOVED, + (jlong)event->time, + state_to_awt_mods (event->state), + (jint)event->x, + (jint)event->y, + 0, + JNI_FALSE); + + gdk_threads_enter (); + } + return FALSE; +} + +static gboolean +component_enter_notify_cb (GtkWidget *widget __attribute__((unused)), + GdkEventCrossing *event, + jobject peer) +{ + /* We are not interested in enter events that are due to + grab/ungrab and not to actually crossing boundaries */ + if (event->mode == GDK_CROSSING_NORMAL) + { + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postMouseEventID, + AWT_MOUSE_ENTERED, + (jlong)event->time, + state_to_awt_mods_with_button_states (event->state), + (jint)event->x, + (jint)event->y, + 0, + JNI_FALSE); + + gdk_threads_enter (); + } + return FALSE; +} + +static gboolean +component_leave_notify_cb (GtkWidget *widget __attribute__((unused)), + GdkEventCrossing *event, + jobject peer) +{ + /* We are not interested in leave events that are due to + grab/ungrab and not to actually crossing boundaries */ + if (event->mode == GDK_CROSSING_NORMAL) + { + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postMouseEventID, + AWT_MOUSE_EXITED, + (jlong)event->time, + state_to_awt_mods_with_button_states (event->state), + (jint)event->x, + (jint)event->y, + 0, + JNI_FALSE); + + gdk_threads_enter (); + } + return FALSE; +} + +static gboolean +component_expose_cb (GtkWidget *widget __attribute__((unused)), + GdkEventExpose *event, + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postExposeEventID, + (jint)event->area.x, + (jint)event->area.y, + (jint)event->area.width, + (jint)event->area.height); + + gdk_threads_enter (); + + return FALSE; +} + +static gboolean +component_focus_in_cb (GtkWidget *widget __attribute((unused)), + GdkEventFocus *event __attribute((unused)), + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postFocusEventID, + AWT_FOCUS_GAINED, + JNI_FALSE); + + gdk_threads_enter (); + + return FALSE; +} + +static gboolean +component_focus_out_cb (GtkWidget *widget __attribute((unused)), + GdkEventFocus *event __attribute((unused)), + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postFocusEventID, + AWT_FOCUS_LOST, + JNI_FALSE); + + gdk_threads_enter (); + + return FALSE; +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer.c new file mode 100644 index 00000000000..563a0257eca --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer.c @@ -0,0 +1,82 @@ +/* gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer.c -- Native + implementation of GtkEmbeddedWindowPeer + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer_create + (JNIEnv *env, jobject obj, jlong socket_id) +{ + GtkWidget *window; + GtkWidget *fixed; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + window = gtk_plug_new ((GdkNativeWindow) socket_id); + + fixed = gtk_fixed_new (); + gtk_container_add (GTK_CONTAINER (window), fixed); + + gtk_widget_show (fixed); + + NSA_SET_PTR (env, obj, window); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer_construct + (JNIEnv *env, jobject obj, jlong socket_id) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + if (GTK_WIDGET_REALIZED (GTK_WIDGET (ptr))) + g_printerr ("ERROR: GtkPlug is already realized\n"); + + gtk_plug_construct (GTK_PLUG (ptr), (GdkNativeWindow) socket_id); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c new file mode 100644 index 00000000000..48478d3b9bb --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c @@ -0,0 +1,281 @@ +/* gtkfiledialogpeer.c -- Native implementation of GtkFileDialogPeer + Copyright (C) 1998, 1999, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h" +#include "gnu_java_awt_peer_gtk_GtkFileDialogPeer.h" + +static void handle_response_cb (GtkDialog *dialog, + gint responseId, + jobject peer_obj); + +/* + * Make a new file selection dialog + */ + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_create + (JNIEnv *env, jobject obj, jobject parent) +{ + void *parentp; + gpointer widget; + + gdk_threads_enter (); + + /* Create global reference and save it for future use */ + NSA_SET_GLOBAL_REF (env, obj); + + parentp = NSA_GET_PTR(env, parent); + + /* FIXME: we should be using the default gnome-vfs backend but it is + not currently thread-safe. See: + http://bugzilla.gnome.org/show_bug.cgi?id=166852 */ + widget = gtk_file_chooser_dialog_new_with_backend + ("Open File", + GTK_WINDOW(parentp), + GTK_FILE_CHOOSER_ACTION_OPEN, + "gtk+", + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + /* GtkFileSelect is not modal by default */ + gtk_window_set_modal (GTK_WINDOW (widget), TRUE); + + /* We must add this window to the group so input in the others are + disable while it is being shown */ + gtk_window_group_add_window (cp_gtk_global_window_group, + GTK_WINDOW (widget)); + + NSA_SET_PTR (env, obj, widget); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr = NULL; + jobject *gref = NULL; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + /* FileDialog signals */ + g_signal_connect (G_OBJECT (ptr), "response", + G_CALLBACK (handle_response_cb), *gref); + + /* Component signals */ + cp_gtk_component_connect_signals (G_OBJECT (ptr), gref); + + gdk_threads_leave (); +} + +JNIEXPORT jstring JNICALL +Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeGetDirectory + (JNIEnv *env, jobject obj) +{ + void *ptr; + const char *str; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + str = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER(ptr)); + + gdk_threads_leave (); + + return (*env)->NewStringUTF(env, str); +} + + +/* This function interfaces with the Java callback method of the same name. + This function extracts the filename from the GtkFileFilterInfo object, + and passes it to the Java method. The Java method will call the filter's + accept() method and will give back the return value. */ +static gboolean filenameFilterCallback (const GtkFileFilterInfo *filter_info, + gpointer obj) +{ + jclass cx; + jmethodID id; + jstring *filename; + gboolean accepted; + + cx = (*cp_gtk_gdk_env())->GetObjectClass (cp_gtk_gdk_env(), (jobject) obj); + id = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), cx, "filenameFilterCallback", + "(Ljava/lang/String;)Z"); + + filename = (*cp_gtk_gdk_env())->NewStringUTF(cp_gtk_gdk_env(), filter_info->filename); + + gdk_threads_leave(); + + accepted = (*cp_gtk_gdk_env())->CallBooleanMethod(cp_gtk_gdk_env(), obj, id, filename); + + gdk_threads_enter(); + + return accepted; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetFilenameFilter + (JNIEnv *env, jobject obj, jobject filter_obj __attribute__((unused))) +{ + void *ptr; + GtkFileFilter *filter; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + filter = gtk_file_filter_new(); + gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, + filenameFilterCallback, obj, NULL); + + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(ptr), filter); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetDirectory + (JNIEnv *env, jobject obj, jstring directory) +{ + void *ptr; + const char *str; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + str = (*env)->GetStringUTFChars (env, directory, 0); + + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(ptr), str); + + (*env)->ReleaseStringUTFChars (env, directory, str); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetFile + (JNIEnv *env, jobject obj, jstring filename) +{ + void *ptr; + const char *str; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + str = (*env)->GetStringUTFChars (env, filename, 0); + + gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (ptr), str); + + (*env)->ReleaseStringUTFChars (env, filename, str); + + gdk_threads_leave (); +} + +static void +handle_response_cb (GtkDialog *dialog __attribute__((unused)), + gint responseId, + jobject peer_obj) +{ + static int isDisposeIDSet = 0; + static int isIDSet = 0; + static jmethodID gtkSetFilenameID; + static jmethodID hideID; + static jmethodID disposeID; + void *ptr; + G_CONST_RETURN gchar *fileName; + jstring str_fileName = NULL; + + /* We only need this for the case when the user closed the window, + or clicked ok or cancel. */ + if (responseId != GTK_RESPONSE_DELETE_EVENT + && responseId != GTK_RESPONSE_ACCEPT + && responseId != GTK_RESPONSE_CANCEL) + return; + + ptr = NSA_GET_PTR (cp_gtk_gdk_env(), peer_obj); + + if (responseId == GTK_RESPONSE_DELETE_EVENT) + { + if (!isDisposeIDSet) + { + jclass cx = (*cp_gtk_gdk_env())->GetObjectClass (cp_gtk_gdk_env(), peer_obj); + disposeID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), cx, "gtkDisposeFileDialog", "()V"); + isDisposeIDSet = 1; + } + + /* We can dispose of the dialog now (and unblock show) */ + gdk_threads_leave (); + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer_obj, disposeID); + gdk_threads_enter (); + + return; + } + + if (responseId == GTK_RESPONSE_ACCEPT) { + fileName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (GTK_WIDGET (ptr))); + str_fileName = (*cp_gtk_gdk_env())->NewStringUTF (cp_gtk_gdk_env(), fileName); + } + + if (!isIDSet) + { + jclass cx = (*cp_gtk_gdk_env())->GetObjectClass (cp_gtk_gdk_env(), peer_obj); + hideID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), cx, "gtkHideFileDialog", "()V"); + gtkSetFilenameID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), cx, + "gtkSetFilename", "(Ljava/lang/String;)V"); + isIDSet = 1; + } + + /* Set the Java object field 'file' with this value. */ + gdk_threads_leave (); + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer_obj, gtkSetFilenameID, str_fileName); + + /* We can hide the dialog now (and unblock show) */ + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer_obj, hideID); + + gdk_threads_enter (); +} + diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c new file mode 100644 index 00000000000..41dfcea67b2 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c @@ -0,0 +1,180 @@ +/* gtkframepeer.c -- Native implementation of GtkFramePeer + Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath 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, or (at your option) + any later version. + + GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + 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. */ + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkFramePeer.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_removeMenuBarPeer + (JNIEnv *env, jobject obj) +{ + void *ptr; + void *mptr; + void *fixed; + GList* children; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + fixed = gtk_container_get_children (GTK_CONTAINER (ptr))->data; + children = gtk_container_get_children (GTK_CONTAINER (fixed)); + + while (children != NULL && !GTK_IS_MENU_SHELL (children->data)) + { + children = children->next; + } + + /* If there's a menu bar, remove it. */ + if (children != NULL) + { + mptr = children->data; + + /* This will actually destroy the MenuBar. By removing it from + its parent, the reference count for the MenuBar widget will + decrement to 0. The widget will be automatically destroyed by + GTK. */ + gtk_container_remove (GTK_CONTAINER (fixed), GTK_WIDGET (mptr)); + } + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarPeer + (JNIEnv *env, jobject obj, jobject menubar) +{ + void *ptr; + void *mptr; + void *fixed; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + mptr = NSA_GET_PTR (env, menubar); + + fixed = gtk_container_get_children (GTK_CONTAINER (ptr))->data; + gtk_fixed_put (GTK_FIXED (fixed), mptr, 0, 0); + gtk_widget_show (mptr); + + gdk_threads_leave (); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_getMenuBarHeight + (JNIEnv *env, jobject obj __attribute__((unused)), jobject menubar) +{ + GtkWidget *ptr; + GtkRequisition requisition; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, menubar); + + gtk_widget_size_request (ptr, &requisition); + + gdk_threads_leave (); + + return requisition.height; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarWidth + (JNIEnv *env, jobject obj __attribute__((unused)), jobject menubar, jint width) +{ + GtkWidget *ptr; + GtkRequisition natural_req; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, menubar); + + /* Get the menubar's natural size request. */ + gtk_widget_set_size_request (GTK_WIDGET (ptr), -1, -1); + gtk_widget_size_request (GTK_WIDGET (ptr), &natural_req); + + /* Set the menubar's size request to width by natural_req.height. */ + gtk_widget_set_size_request (GTK_WIDGET (ptr), + width, natural_req.height); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_gtkFixedSetVisible + (JNIEnv *env, jobject obj, jboolean visible) +{ + void *ptr; + void *fixed; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + fixed = gtk_container_get_children (GTK_CONTAINER (ptr))->data; + + if (visible) + gtk_widget_show (GTK_WIDGET (fixed)); + else + gtk_widget_hide (GTK_WIDGET (fixed)); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImage + (JNIEnv *env, jobject obj, jobject gtkimage) +{ + void *ptr; + GdkPixbuf *pixbuf = NULL; + + gdk_threads_enter (); + + pixbuf = cp_gtk_image_get_pixbuf (env, gtkimage); + g_assert (pixbuf != NULL); + + ptr = NSA_GET_PTR (env, obj); + + gtk_window_set_icon (GTK_WINDOW (ptr), pixbuf); + + /* if the GtkImage is offscreen, this is a temporary pixbuf which should + be thrown out. */ + if(cp_gtk_image_is_offscreen (env, gtkimage) == JNI_TRUE) + gdk_pixbuf_unref (pixbuf); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c new file mode 100644 index 00000000000..0fae1da42b4 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c @@ -0,0 +1,101 @@ +/* gtkgenericpeer.c -- Native implementation of GtkGenericPeer + Copyright (C) 1998, 1999, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkGenericPeer.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkGenericPeer_dispose + (JNIEnv *env, jobject obj) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + /* For now the native state for any object must be a widget. + However, a subclass could override dispose() if required. */ + gtk_widget_destroy (GTK_WIDGET (ptr)); + + /* Remove entries from state tables */ + NSA_DEL_GLOBAL_REF (env, obj); + NSA_DEL_PTR (env, obj); + + gdk_threads_leave (); + + /* + * Wake up the main thread, to make sure it re-checks the window + * destruction condition. + */ + + g_main_context_wakeup (NULL); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkGenericPeer_gtkWidgetModifyFont + (JNIEnv *env, jobject obj, jstring name, jint style, jint size) +{ + const char *font_name; + void *ptr; + PangoFontDescription *font_desc; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, obj); + + font_name = (*env)->GetStringUTFChars (env, name, NULL); + + font_desc = pango_font_description_from_string (font_name); + pango_font_description_set_size (font_desc, + size * cp_gtk_dpi_conversion_factor); + + if (style & AWT_STYLE_BOLD) + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + + if (style & AWT_STYLE_ITALIC) + pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); + + gtk_widget_modify_font (GTK_WIDGET(ptr), font_desc); + + pango_font_description_free (font_desc); + + (*env)->ReleaseStringUTFChars (env, name, font_name); + + gdk_threads_leave(); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c new file mode 100644 index 00000000000..86cad1487c6 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c @@ -0,0 +1,621 @@ +/* gtkimage.c + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkImage.h" +#include <gdk-pixbuf/gdk-pixbuf.h> + +/* The constant fields in java.awt.Image */ +#define SCALE_DEFAULT 1 +#define SCALE_FAST 2 +#define SCALE_SMOOTH 4 +#define SCALE_REPLICATE 8 +#define SCALE_AREA_AVERAGING 16 + +/* local stuff */ +static GdkInterpType mapHints(jint hints); +static jboolean offScreen (JNIEnv * env, jobject obj); +static void *getData (JNIEnv * env, jobject obj); +static void createRawData (JNIEnv * env, jobject obj, void *ptr); +static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height); + +/** + * Loads a pixmap from a file. + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_GtkImage_loadPixbuf + (JNIEnv *env, jobject obj, jstring name) +{ + const char *filename; + int width, height; + GdkPixbuf *pixbuf; + + gdk_threads_enter (); + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + + if (filename == NULL) + { + gdk_threads_leave (); + return JNI_FALSE; + } + + pixbuf = gdk_pixbuf_new_from_file (filename, NULL); + if (pixbuf == NULL) + { + (*env)->ReleaseStringUTFChars (env, name, filename); + gdk_threads_leave (); + return JNI_FALSE; + } + + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + + createRawData (env, obj, pixbuf); + setWidthHeight(env, obj, width, height); + (*env)->ReleaseStringUTFChars (env, name, filename); + + gdk_threads_leave (); + + return JNI_TRUE; +} + +/** + * Returns a copy of the pixel data as a java array. + */ +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_GtkImage_getPixels(JNIEnv *env, jobject obj) +{ + GdkPixbuf *pixbuf; + int width, height, rowstride; + guchar *pixeldata; + jintArray result_array; + jint *result_array_iter, *dst; + int i,j; + + gdk_threads_enter (); + + pixbuf = cp_gtk_image_get_pixbuf (env, obj); + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + + /* Must release the GDK lock before allocating memory through the + JVM, since some JVMs use the same lock for allocations and + finalization. Deadlock can occur on those JVMs. */ + gdk_threads_leave (); + + result_array = (*env)->NewIntArray (env, (width * height)); + + gdk_threads_enter (); + + dst = result_array_iter = + (*env)->GetIntArrayElements (env, result_array, NULL); + + + pixeldata = gdk_pixbuf_get_pixels (pixbuf); + + g_assert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8); + + if (gdk_pixbuf_get_has_alpha (pixbuf)) + { + for(i = 0 ; i < height; i++) + { + memcpy(dst, (void *)pixeldata, width * 4); + dst += width; + pixeldata += rowstride; + } + } else { + for(i = 0; i < height; i++) + { + for(j = 0; j < width; j++) + dst[j] = 0xFF000000 | + (pixeldata[j*3 + 2] & 0xFF) << 16 | + (pixeldata[j*3 + 1] & 0xFF) << 8 | + (pixeldata[j*3] & 0xFF); + dst += width; + pixeldata += rowstride; + } + } + + if (offScreen (env, obj) == JNI_TRUE) + gdk_pixbuf_unref (pixbuf); + + (*env)->ReleaseIntArrayElements (env, result_array, result_array_iter, 0); + + gdk_threads_leave (); + + return result_array; +} + +/** + * Returns a copy of the pixel data as a java array. + * (GdkPixbuf only) + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv *env, jobject obj, + jintArray pixels) +{ + GdkPixbuf *pixbuf = (GdkPixbuf *)getData (env, obj); + int width, height, rowstride; + guchar *pixeldata; + jint *src_array_iter, *src; + int i; + + gdk_threads_enter (); + + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + + src = src_array_iter = + (*env)->GetIntArrayElements (env, pixels, NULL); + + pixeldata = gdk_pixbuf_get_pixels (pixbuf); + for(i = 0 ; i < height; i++) + { + memcpy((void *)pixeldata, (void *)src, width * 4); + src += width; + pixeldata += rowstride; + } + + (*env)->ReleaseIntArrayElements (env, pixels, src_array_iter, 0); + + gdk_threads_leave (); +} + +/** + * Allocates a Gtk Pixbuf or Pixmap. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkImage_createPixmap(JNIEnv *env, jobject obj) +{ + int width, height; + jclass cls; + jfieldID field; + + gdk_threads_enter (); + + cls = (*env)->GetObjectClass (env, obj); + field = (*env)->GetFieldID (env, cls, "width", "I"); + g_assert (field != 0); + width = (*env)->GetIntField (env, obj, field); + + field = (*env)->GetFieldID (env, cls, "height", "I"); + g_assert (field != 0); + height = (*env)->GetIntField (env, obj, field); + + if (offScreen (env, obj) == JNI_FALSE) + createRawData (env, obj, gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + 8, + width, + height)); + else + createRawData (env, obj, gdk_pixmap_new (NULL, width, height, + gdk_rgb_get_visual ()->depth)); + + gdk_threads_leave (); +} + +/** + * Frees the Gtk Pixmap. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkImage_freePixmap(JNIEnv *env, jobject obj) +{ + gdk_threads_enter (); + if (offScreen (env, obj) == JNI_FALSE) + gdk_pixbuf_unref ((GdkPixbuf *)getData (env, obj)); + else + gdk_pixmap_unref ((GdkPixmap *)getData (env, obj)); + + gdk_threads_leave (); +} + +/** + * Sets this pixmap to a scaled version of the source pixmap. + * width and height of the destination GtkImage must be set. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixmap(JNIEnv *env, + jobject destination, + jobject source, + jint hints) +{ + GdkPixbuf* dst; + int width, height; + jclass cls; + jfieldID field; + + GdkPixbuf *pixbuf; + + gdk_threads_enter (); + + cls = (*env)->GetObjectClass (env, destination); + field = (*env)->GetFieldID (env, cls, "width", "I"); + g_assert (field != 0); + width = (*env)->GetIntField (env, destination, field); + + field = (*env)->GetFieldID (env, cls, "height", "I"); + g_assert (field != 0); + height = (*env)->GetIntField (env, destination, field); + + pixbuf = cp_gtk_image_get_pixbuf (env, source); + + dst = gdk_pixbuf_scale_simple(pixbuf, + width, height, + mapHints(hints)); + + if (offScreen (env, source) == JNI_TRUE) + gdk_pixbuf_unref (pixbuf); + + createRawData (env, destination, (void *)dst); + + gdk_threads_leave (); +} + +/** + * Draws the pixbuf at x, y, scaled to width and height and + * optionally composited with a given background color. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaled + (JNIEnv *env, jobject obj, jobject gc_obj, + jint bg_red, jint bg_green, jint bg_blue, + jint x, jint y, jint width, jint height, jboolean composite) +{ + GdkPixbuf* dst; + struct graphics *g; + guint32 bgColor; + + gdk_threads_enter (); + + bgColor = ((bg_red & 0xFF) << 16) | + ((bg_green & 0xFF) << 8) | (bg_blue & 0xFF); + + g = (struct graphics *) NSA_GET_PTR (env, gc_obj); + + if (!g || !GDK_IS_DRAWABLE (g->drawable)) + { + gdk_threads_leave (); + return; + } + + if (offScreen (env, obj) == JNI_FALSE) + { + GdkPixbuf* pixbuf = (GdkPixbuf *)getData (env, obj); + + /* Scale and composite the image */ + if (composite == JNI_TRUE) + dst = gdk_pixbuf_composite_color_simple (pixbuf, + width, + height, + GDK_INTERP_BILINEAR, + 255, + width, + bgColor, + bgColor); + else + dst = gdk_pixbuf_scale_simple(pixbuf, + width, height, + GDK_INTERP_BILINEAR); + + gdk_draw_pixbuf (g->drawable, + g->gc, + dst, + 0, 0, + x + g->x_offset, y + g->y_offset, + width, height, + GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_pixbuf_unref (dst); + + } else { + /* Get a pixmap */ + GdkPixmap* pixmap = (GdkPixmap *)getData (env, obj); + gdk_draw_drawable (g->drawable, + g->gc, + pixmap, + 0, 0, /* src x,y */ + x + g->x_offset, y + g->y_offset, + width, height); + } + + gdk_threads_leave (); +} + +/** + * Draws the pixbuf at x, y, scaled to width and height and + * optionally composited and/or flipped with a given background color. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaledFlipped +(JNIEnv *env, jobject obj, jobject gc_obj, + jint bg_red, jint bg_green, jint bg_blue, + jboolean flipx, jboolean flipy, + jint srcx, jint srcy, jint srcwidth, jint srcheight, + jint dstx, jint dsty, jint dstwidth, jint dstheight, + jboolean composite) +{ + GdkPixbuf *pixbuf; + GdkPixbuf *tmp, *dst; + struct graphics *g; + guint32 bgColor; + + gdk_threads_enter (); + + bgColor = ((bg_red & 0xFF) << 16) | + ((bg_green & 0xFF) << 8) | (bg_blue & 0xFF); + + g = (struct graphics *) NSA_GET_PTR (env, gc_obj); + + if (!g || !GDK_IS_DRAWABLE (g->drawable)) + { + gdk_threads_leave (); + return; + } + + if (offScreen (env, obj) == JNI_FALSE) + { + pixbuf = (GdkPixbuf *)getData (env, obj); + + /* Get the source area */ + tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + 8, + srcwidth, + srcheight); + + gdk_pixbuf_copy_area (pixbuf, + srcx, srcy, + srcwidth, srcheight, + tmp, + 0, 0); /* dst x , dst y */ + } else { + /* Get a pixbuf from the pixmap */ + GdkDrawable *pixmap = (GdkDrawable *)getData(env, obj); + tmp = gdk_pixbuf_get_from_drawable (NULL, + pixmap, + gdk_drawable_get_colormap( pixmap ), + srcx, srcy, + 0, 0, /* dst x , dst y */ + srcwidth, srcheight); + } + + /* FIXME: This #if should be discarded once I feel comfortable about + GTK 2.6 dependence */ +#if GTK_MINOR_VERSION > 4 + /* Flip it if necessary. */ + if (flipx == JNI_TRUE) + { + GdkPixbuf *tmp2 = gdk_pixbuf_flip (tmp, TRUE); + gdk_pixbuf_unref (tmp); + tmp = tmp2; + } + if (flipy == JNI_TRUE) + { + GdkPixbuf *tmp2 = gdk_pixbuf_flip (tmp, FALSE); + gdk_pixbuf_unref (tmp); + tmp = tmp2; + } +#endif + + /* Scale and composite the image */ + if (composite == JNI_TRUE) + dst = gdk_pixbuf_composite_color_simple (tmp, + dstwidth, + dstheight, + GDK_INTERP_BILINEAR, + 255, + dstwidth, + bgColor, + bgColor); + else + dst = gdk_pixbuf_scale_simple(tmp, + dstwidth, dstheight, + GDK_INTERP_BILINEAR); + gdk_pixbuf_unref (tmp); + + gdk_draw_pixbuf (g->drawable, + g->gc, + dst, + 0, 0, + dstx + g->x_offset, dsty + g->y_offset, + dstwidth, dstheight, + GDK_RGB_DITHER_NORMAL, 0, 0); + + gdk_pixbuf_unref (dst); + + gdk_threads_leave (); +} + +/** + * Used by GtkFramePeer + */ +GdkPixbuf *cp_gtk_image_get_pixbuf (JNIEnv *env, jobject obj) +{ + int width, height; + GdkPixbuf *pixbuf; + GdkPixmap* pixmap; + jclass cls; + jfieldID field; + + if (offScreen (env, obj) == JNI_FALSE) + return (GdkPixbuf *)getData (env, obj); + + cls = (*env)->GetObjectClass (env, obj); + field = (*env)->GetFieldID (env, cls, "width", "I"); + g_assert (field != 0); + width = (*env)->GetIntField (env, obj, field); + + field = (*env)->GetFieldID (env, cls, "height", "I"); + g_assert (field != 0); + height = (*env)->GetIntField (env, obj, field); + + /* Get a pixmap */ + pixmap = (GdkPixmap *)getData (env, obj); + pixbuf = gdk_pixbuf_get_from_drawable (NULL, + pixmap, + gdk_drawable_get_colormap( pixmap ), + 0, 0, /* src x , src y */ + 0, 0, /* dst x , dst y */ + width, height); + return pixbuf; +} + +/** + * Used by GdkGraphics + */ +GdkPixmap *cp_gtk_image_get_pixmap (JNIEnv *env, jobject obj) +{ + if (offScreen (env, obj) == JNI_FALSE) + return NULL; + return (GdkPixmap *)getData (env, obj); +} + +jboolean cp_gtk_image_is_offscreen (JNIEnv *env, jobject obj) +{ + return offScreen(env, obj); +} + +/** + * Maps java.awt.Image scaling hints to the native GDK ones. + */ +static GdkInterpType mapHints(jint hints) +{ + switch ( hints ) + { + /* For FAST, we use the nearest-neighbor. Fastest and lowest quality. */ + case SCALE_FAST: + case SCALE_REPLICATE: + return GDK_INTERP_NEAREST; + + /* Hyperbolic for smooth. Slowest too. */ + case SCALE_SMOOTH: + return GDK_INTERP_HYPER; + + /* the inbetweenish method */ + case SCALE_AREA_AVERAGING: + return GDK_INTERP_TILES; + + /* default to bilinear */ + } + return GDK_INTERP_BILINEAR; +} + +/* Sets the width and height fields of a GtkImage object. */ +static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height) +{ + jclass cls; + jfieldID field; + + cls = (*env)->GetObjectClass (env, obj); + g_assert (cls != 0); + field = (*env)->GetFieldID (env, cls, "width", "I"); + g_assert (field != 0); + (*env)->SetIntField (env, obj, field, (jint)width); + + field = (*env)->GetFieldID (env, cls, "height", "I"); + g_assert (field != 0); + (*env)->SetIntField (env, obj, field, (jint)height); +} + +/* Returns the value of the offScreen field. */ +static jboolean offScreen (JNIEnv *env, jobject obj) +{ + jclass cls; + jfieldID field; + + cls = (*env)->GetObjectClass (env, obj); + field = (*env)->GetFieldID (env, cls, "offScreen", "Z"); + g_assert (field != 0); + return (*env)->GetBooleanField (env, obj, field); +} + +/* Store and get the pixbuf pointer */ +static void +createRawData (JNIEnv * env, jobject obj, void *ptr) +{ + jclass cls; + jmethodID method; + jobject data; + jfieldID data_fid; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "pixmap", + "Lgnu/classpath/RawData;"); + g_assert (data_fid != 0); + +#if SIZEOF_VOID_P == 8 + cls = (*env)->FindClass (env, "gnu/classpath/RawData64"); + method = (*env)->GetMethodID (env, cls, "<init>", "(J)V"); + data = (*env)->NewObject (env, cls, method, (jlong) ptr); +#else + cls = (*env)->FindClass (env, "gnu/classpath/RawData32"); + method = (*env)->GetMethodID (env, cls, "<init>", "(I)V"); + data = (*env)->NewObject (env, cls, method, (jint) ptr); +#endif + + (*env)->SetObjectField (env, obj, data_fid, data); +} + +static void * +getData (JNIEnv * env, jobject obj) +{ + jclass cls; + jfieldID field; + jfieldID data_fid; + jobject data; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "pixmap", + "Lgnu/classpath/RawData;"); + g_assert (data_fid != 0); + data = (*env)->GetObjectField (env, obj, data_fid); + +#if SIZEOF_VOID_P == 8 + cls = (*env)->FindClass (env, "gnu/classpath/RawData64"); + field = (*env)->GetFieldID (env, cls, "data", "J"); + return (void *) (*env)->GetLongField (env, data, field); +#else + cls = (*env)->FindClass (env, "gnu/classpath/RawData32"); + field = (*env)->GetFieldID (env, cls, "data", "I"); + return (void *) (*env)->GetIntField (env, data, field); +#endif +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLabelPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLabelPeer.c new file mode 100644 index 00000000000..7968ca77371 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLabelPeer.c @@ -0,0 +1,183 @@ +/* gtklabelpeer.c -- Native implementation of GtkLabelPeer + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkLabelPeer.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkLabelPeer_create + (JNIEnv *env, jobject obj, jstring text, jfloat xalign) +{ + GtkWidget *label; + GtkWidget *eventbox; + const char *str; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + str = (*env)->GetStringUTFChars (env, text, 0); + + eventbox = gtk_event_box_new (); + label = gtk_label_new (str); + gtk_misc_set_alignment (GTK_MISC (label), xalign, 0.5); + gtk_container_add (GTK_CONTAINER (eventbox), label); + gtk_widget_show (label); + + (*env)->ReleaseStringUTFChars (env, text, str); + + NSA_SET_PTR (env, obj, eventbox); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkLabelPeer_gtkWidgetModifyFont + (JNIEnv *env, jobject obj, jstring name, jint style, jint size) +{ + const char *font_name; + void *ptr; + GtkWidget *label; + PangoFontDescription *font_desc; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + font_name = (*env)->GetStringUTFChars (env, name, NULL); + + label = gtk_bin_get_child (GTK_BIN (ptr)); + + if (!label) + { + gdk_threads_leave (); + return; + } + + font_desc = pango_font_description_from_string (font_name); + pango_font_description_set_size (font_desc, + size * cp_gtk_dpi_conversion_factor); + + if (style & AWT_STYLE_BOLD) + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + + if (style & AWT_STYLE_ITALIC) + pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); + + gtk_widget_modify_font (GTK_WIDGET (label), font_desc); + + pango_font_description_free (font_desc); + + (*env)->ReleaseStringUTFChars (env, name, font_name); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkLabelPeer_setText + (JNIEnv *env, jobject obj, jstring text) +{ + const char *str; + void *ptr; + GtkWidget *label; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + str = (*env)->GetStringUTFChars (env, text, 0); + + label = gtk_bin_get_child (GTK_BIN (ptr)); + + gtk_label_set_label (GTK_LABEL (label), str); + + (*env)->ReleaseStringUTFChars (env, text, str); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkLabelPeer_nativeSetAlignment + (JNIEnv *env, jobject obj, jfloat xalign) +{ + void *ptr; + GtkWidget *label; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + label = gtk_bin_get_child (GTK_BIN(ptr)); + + gtk_misc_set_alignment (GTK_MISC (label), xalign, 0.5); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkLabelPeer_setNativeBounds + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + GtkWidget *widget; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + widget = GTK_WIDGET (ptr); + + /* We assume that -1 is a width or height and not a request for the + widget's natural size. */ + width = width < 0 ? 0 : width; + height = height < 0 ? 0 : height; + + if (!(width == 0 && height == 0)) + { + /* Set the event box's size request... */ + gtk_widget_set_size_request (widget, width, height); + /* ...and the label's size request. */ + gtk_widget_set_size_request (gtk_bin_get_child (GTK_BIN (widget)), + width, height); + + if (widget->parent != NULL) + gtk_fixed_move (GTK_FIXED (widget->parent), widget, x, y); + } + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c new file mode 100644 index 00000000000..d513176bed1 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c @@ -0,0 +1,539 @@ +/* GtkListPeer.c -- implements GtkListPeer's native methods + Copyright (C) 1998, 1999, 2003, 2004 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath 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, or (at your option) + any later version. + + GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + 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. */ + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkListPeer.h" + +static jmethodID postListItemEventID; + +void +cp_gtk_list_init_jni (void) +{ + jclass gtklistpeer; + + gtklistpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkListPeer"); + + postListItemEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtklistpeer, + "postItemEvent", + "(II)V"); +} + +enum + { + COLUMN_STRING, + N_COLUMNS + }; + +static gboolean item_highlighted_cb (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + jobject peer); + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_create + (JNIEnv *env, jobject obj, jint rows) +{ + GtkWidget *sw; + GtkWidget *list; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + GtkListStore *list_store; + GtkTreeIter iter; + GtkRequisition req; + gint i; + + gdk_threads_enter (); + + /* Create global reference and save it for future use */ + NSA_SET_GLOBAL_REF (env, obj); + + list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING); + /* Add the number of rows so that we can calculate the tree view's + size request. */ + for (i = 0; i < rows; i++) + { + gtk_list_store_append (list_store, &iter); + gtk_list_store_set (list_store, &iter, + COLUMN_STRING, "", + -1); + } + list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store)); + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (NULL, + renderer, + "text", + COLUMN_STRING, + NULL); + + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE); + + gtk_widget_size_request (GTK_WIDGET (list), &req); + + gtk_widget_set_size_request (GTK_WIDGET (list), req.width, req.height); + + gtk_container_add (GTK_CONTAINER (sw), list); + + /* Remove the blank rows. */ + gtk_list_store_clear (list_store); + + gtk_widget_show (list); + gtk_widget_show (sw); + + NSA_SET_PTR (env, obj, sw); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr; + jobject *gref; + GtkWidget *list; + GtkTreeSelection *selection; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); + gtk_tree_selection_set_select_function (selection, item_highlighted_cb, + *gref, NULL); + + cp_gtk_component_connect_signals (G_OBJECT (list), gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_gtkWidgetModifyFont + (JNIEnv *env, jobject obj, jstring name, jint style, jint size) +{ + const char *font_name; + void *ptr; + GtkWidget *list; + PangoFontDescription *font_desc; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + + font_name = (*env)->GetStringUTFChars (env, name, NULL); + + font_desc = pango_font_description_from_string (font_name); + pango_font_description_set_size (font_desc, + size * cp_gtk_dpi_conversion_factor); + + if (style & AWT_STYLE_BOLD) + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + + if (style & AWT_STYLE_ITALIC) + pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); + + gtk_widget_modify_font (GTK_WIDGET (list), font_desc); + + pango_font_description_free (font_desc); + + (*env)->ReleaseStringUTFChars (env, name, font_name); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_gtkWidgetRequestFocus + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkWidget *list; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + gtk_widget_grab_focus (list); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_append + (JNIEnv *env, jobject obj, jobjectArray items) +{ + void *ptr; + GtkWidget *list; + GtkTreeIter iter; + GtkTreeModel *list_store; + jint count; + jint i; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + count = (*env)->GetArrayLength (env, items); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + list_store = gtk_tree_view_get_model (GTK_TREE_VIEW (list)); + + for (i = 0; i < count; i++) + { + const char *text; + jobject item; + + item = (*env)->GetObjectArrayElement (env, items, i); + + text = (*env)->GetStringUTFChars (env, item, NULL); + gtk_list_store_append (GTK_LIST_STORE (list_store), &iter); + gtk_list_store_set (GTK_LIST_STORE (list_store), &iter, + COLUMN_STRING, text, + -1); + (*env)->ReleaseStringUTFChars (env, item, text); + } + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_add + (JNIEnv *env, jobject obj, jstring text, jint index) +{ + void *ptr; + const char *str; + GtkWidget *list; + GtkTreeIter iter; + GtkTreeModel *list_store; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + str = (*env)->GetStringUTFChars (env, text, NULL); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + list_store = gtk_tree_view_get_model (GTK_TREE_VIEW (list)); + + if (index == -1) + gtk_list_store_append (GTK_LIST_STORE (list_store), &iter); + else + gtk_list_store_insert (GTK_LIST_STORE (list_store), &iter, index); + + gtk_list_store_set (GTK_LIST_STORE (list_store), &iter, + COLUMN_STRING, str, -1); + + (*env)->ReleaseStringUTFChars (env, text, str); + + gdk_threads_leave (); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_delItems + (JNIEnv *env, jobject obj, jint start, jint end) +{ + void *ptr; + GtkWidget *list; + GtkTreeIter iter; + GtkTreeModel *list_store; + jint i; + jint num_items; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + list_store = gtk_tree_view_get_model (GTK_TREE_VIEW (list)); + + /* Special case: remove all rows. */ + if (end == -1) + gtk_list_store_clear (GTK_LIST_STORE (list_store)); + else + { + i = 0; + num_items = end - start + 1; + gtk_tree_model_iter_nth_child (list_store, &iter, NULL, start); + while (i < num_items) + { + gtk_list_store_remove (GTK_LIST_STORE (list_store), &iter); + i++; + } + } + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_select + (JNIEnv *env, jobject obj, jint index) +{ + void *ptr; + GtkWidget *list; + GtkTreePath *path; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + path = gtk_tree_path_new_from_indices (index, -1); + gtk_tree_view_set_cursor (GTK_TREE_VIEW (list), path, NULL, FALSE); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_deselect + (JNIEnv *env, jobject obj, jint index) +{ + void *ptr; + GtkWidget *list; + GtkTreeSelection *selection; + GtkTreePath *path; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); + path = gtk_tree_path_new_from_indices (index, -1); + gtk_tree_selection_unselect_path (selection, path); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_getSize + (JNIEnv *env, jobject obj, jint rows, jint visible_rows, jintArray jdims) +{ + void *ptr; + jint *dims; + GtkRequisition current_req; + GtkRequisition natural_req; + + gdk_threads_enter (); + + dims = (*env)->GetIntArrayElements (env, jdims, NULL); + dims[0] = dims[1] = 0; + + ptr = NSA_GET_PTR (env, obj); + + /* Save the widget's current size request. */ + gtk_widget_size_request (GTK_WIDGET (ptr), ¤t_req); + + /* Get the widget's "natural" size request. */ + gtk_widget_set_size_request (GTK_WIDGET (ptr), -1, -1); + gtk_widget_size_request (GTK_WIDGET (ptr), &natural_req); + + /* Reset the widget's size request. */ + gtk_widget_set_size_request (GTK_WIDGET (ptr), + current_req.width, current_req.height); + + dims[0] = natural_req.width; + + /* Calculate the final height, by comparing the number of rows + in the list to the number of rows requested by the caller. + FIXME: Is there a GTK method that counts the number of rows + in the list? If so, we don't need to bring visible_rows from + the Java peer. */ + if (rows == visible_rows) + dims[1] = natural_req.height; + else + dims[1] = natural_req.height / visible_rows * rows; + + (*env)->ReleaseIntArrayElements (env, jdims, dims, 0); + + gdk_threads_leave (); +} + + +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_getSelectedIndexes + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkWidget *list; + GtkTreeSelection *selection; + jintArray result_array; + jint *result_array_iter; + GList *current_row; + GList *rows; + gint *indices; + jint count; + jint i; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); + count = gtk_tree_selection_count_selected_rows (selection); + if (count > 0) + { + current_row = rows = gtk_tree_selection_get_selected_rows (selection, NULL); + + gdk_threads_leave (); + + result_array = (*env)->NewIntArray (env, count); + + gdk_threads_enter (); + + result_array_iter = (*env)->GetIntArrayElements (env, result_array, NULL); + + for (i = 0; i < count; i++) + { + indices = gtk_tree_path_get_indices (current_row->data); + result_array_iter[i] = indices ? indices[0] : -1; + current_row = g_list_next (current_row); + } + + if (rows) + { + g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL); + g_list_free (rows); + } + + (*env)->ReleaseIntArrayElements (env, result_array, result_array_iter, 0); + } + else + result_array = NULL; + + gdk_threads_leave (); + + return result_array; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_makeVisible + (JNIEnv *env, jobject obj, jint index) +{ + void *ptr; + GtkWidget *list; + GtkTreePath *path; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + path = gtk_tree_path_new_from_indices (index, -1); + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (list), path, + NULL, FALSE, 0.0, 0.0); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_setMultipleMode + (JNIEnv *env, jobject obj, jboolean mode) +{ + void *ptr; + GtkWidget *list; + GtkTreeSelection *selection; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_bin_get_child (GTK_BIN (ptr)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); + gtk_tree_selection_set_mode (selection, + mode ? GTK_SELECTION_MULTIPLE + : GTK_SELECTION_SINGLE); + + gdk_threads_leave (); +} + +static gboolean +item_highlighted_cb (GtkTreeSelection *selection __attribute__((unused)), + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + jobject peer) +{ + GtkTreeIter iter; + jint row; + gint *indices; + + if (gtk_tree_model_get_iter (model, &iter, path)) + { + indices = gtk_tree_path_get_indices (path); + row = indices ? indices[0] : -1; + + if (!path_currently_selected) + { + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postListItemEventID, + row, + (jint) AWT_ITEM_SELECTED); + + gdk_threads_enter (); + } + else + { + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postListItemEventID, + row, + (jint) AWT_ITEM_DESELECTED); + + gdk_threads_enter (); + } + } + + return TRUE; +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c new file mode 100644 index 00000000000..3e21a04024d --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c @@ -0,0 +1,118 @@ +/* gtkmenubarpeer.c -- Native implementation of GtkMenuBarPeer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkMenuBarPeer.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuBarPeer_create + (JNIEnv *env, jobject obj) +{ + GtkWidget *widget; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + widget = gtk_menu_bar_new (); + gtk_widget_show (widget); + + NSA_SET_PTR (env, obj, widget); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuBarPeer_addMenu + (JNIEnv *env, jobject obj, jobject menupeer) +{ + void *mbar, *menu; + + gdk_threads_enter (); + + mbar = NSA_GET_PTR (env, obj); + menu = NSA_GET_PTR (env, menupeer); + + gtk_menu_shell_append (GTK_MENU_SHELL (mbar), GTK_WIDGET (menu)); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuBarPeer_nativeSetHelpMenu + (JNIEnv *env, jobject obj, jobject menupeer) +{ + static void *helpmenu; + void *mbar, *menu; + GList *list; + + gdk_threads_enter (); + + mbar = NSA_GET_PTR (env, obj); + menu = NSA_GET_PTR (env, menupeer); + + if (helpmenu != NULL) + { + list = gtk_container_children (GTK_CONTAINER (mbar)); + while (list != NULL && list->data != helpmenu) + list = list->next; + if (list != NULL && list->data == helpmenu) + gtk_container_remove (GTK_CONTAINER (mbar), GTK_WIDGET (list->data)); + } + helpmenu = menu; + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuBarPeer_delMenu + (JNIEnv *env, jobject obj, jint index) +{ + void *ptr; + GList *list; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_container_children (GTK_CONTAINER (ptr)); + list = g_list_nth (list, index); + gtk_container_remove (GTK_CONTAINER (ptr), GTK_WIDGET (list->data)); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuComponentPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuComponentPeer.c new file mode 100644 index 00000000000..01b74e46c57 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuComponentPeer.c @@ -0,0 +1,56 @@ +/* gtkmenucomponentpeer.c -- Native implementation of GtkMenuComponentPeer + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkMenuComponentPeer.h" + +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuComponentPeer_dispose + (JNIEnv *env, jobject obj) +{ + /* For MenuComponents and its subclasses, the widgets are + automatically destroyed by Gtk when the parent MenuBar + is removed from the Frame. So we avoid the widget + destruction in GtkGenericPeer dispose() by overriding + it here. */ + + /* However, references to the Java objects still exist in the + state tables, so we still have to remove those. */ + + NSA_DEL_GLOBAL_REF (env, obj); + NSA_DEL_PTR (env, obj); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c new file mode 100644 index 00000000000..2746f1e4a70 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c @@ -0,0 +1,193 @@ +/* gtkmenuitempeer.c -- Native implementation of GtkMenuItemPeer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkMenuItemPeer.h" +#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h" + +static jmethodID postMenuActionEventID; + +void +cp_gtk_menuitem_init_jni (void) +{ + jclass gtkmenuitempeer; + + gtkmenuitempeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkMenuItemPeer"); + + postMenuActionEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), + gtkmenuitempeer, + "postMenuActionEvent", + "()V"); +} + +static void item_activate_cb (GtkMenuItem *item __attribute__((unused)), + jobject peer_obj); + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuItemPeer_create + (JNIEnv *env, jobject obj, jstring label) +{ + GtkWidget *widget; + const char *str; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + str = (*env)->GetStringUTFChars (env, label, NULL); + + /* "-" signals that we need a separator. */ + if (strcmp (str, "-") == 0) + widget = gtk_menu_item_new (); + else + widget = gtk_menu_item_new_with_label (str); + + gtk_widget_show (widget); + + (*env)->ReleaseStringUTFChars (env, label, str); + + NSA_SET_PTR (env, obj, widget); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuItemPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr; + jobject *gref; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + g_signal_connect (G_OBJECT (ptr), "activate", + G_CALLBACK (item_activate_cb), *gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuItemPeer_gtkWidgetModifyFont + (JNIEnv *env, jobject obj, jstring name, jint style, jint size) +{ + const char *font_name; + void *ptr; + GtkWidget *label; + PangoFontDescription *font_desc; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, obj); + + font_name = (*env)->GetStringUTFChars (env, name, NULL); + + label = gtk_bin_get_child (GTK_BIN (ptr)); + + if (label) + { + font_desc = pango_font_description_from_string (font_name); + pango_font_description_set_size (font_desc, + size * cp_gtk_dpi_conversion_factor); + + if (style & AWT_STYLE_BOLD) + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + + if (style & AWT_STYLE_ITALIC) + pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); + + gtk_widget_modify_font (GTK_WIDGET(label), font_desc); + + pango_font_description_free (font_desc); + } + + (*env)->ReleaseStringUTFChars (env, name, font_name); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuItemPeer_setEnabled + (JNIEnv *env, jobject obj, jboolean enabled) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_widget_set_sensitive (GTK_WIDGET (ptr), enabled); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuItemPeer_setLabel + (JNIEnv *env, jobject obj, jstring label) +{ + void *ptr; + const char *str; + GtkAccelLabel *accel_label; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + str = (*env)->GetStringUTFChars (env, label, NULL); + + accel_label = GTK_ACCEL_LABEL (GTK_BIN (ptr)->child); + + gtk_label_set_text (GTK_LABEL (accel_label), str); + gtk_accel_label_refetch (accel_label); + + (*env)->ReleaseStringUTFChars (env, label, str); + + gdk_threads_leave (); +} + +static void +item_activate_cb (GtkMenuItem *item __attribute__((unused)), jobject peer_obj) +{ + gdk_threads_leave (); + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer_obj, + postMenuActionEventID); + gdk_threads_enter (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c new file mode 100644 index 00000000000..16018f001e4 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c @@ -0,0 +1,173 @@ +/* gtkmenupeer.c -- Native implementation of GtkMenuPeer + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkMenuPeer.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuPeer_setupAccelGroup + (JNIEnv *env, jobject obj, jobject parent) +{ + void *ptr1, *ptr2; + + gdk_threads_enter (); + + ptr1 = NSA_GET_PTR (env, obj); + + if (!parent) + { + gtk_menu_set_accel_group (GTK_MENU (GTK_MENU_ITEM (ptr1)->submenu), + gtk_accel_group_new ()); + } + else + { + GtkAccelGroup *parent_accel; + + ptr2 = NSA_GET_PTR (env, parent); + parent_accel = gtk_menu_get_accel_group (GTK_MENU (GTK_MENU_ITEM (ptr2)->submenu)); + + gtk_menu_set_accel_group (GTK_MENU (GTK_MENU_ITEM (ptr1)->submenu), + parent_accel); + } + + gdk_threads_leave (); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuPeer_create + (JNIEnv *env, jobject obj, jstring label) +{ + GtkWidget *menu_title, *menu, *toplevel; + const char *str; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + str = (*env)->GetStringUTFChars (env, label, NULL); + + menu = gtk_menu_new (); + + if (str != NULL) + menu_title = gtk_menu_item_new_with_label (str); + else + menu_title = gtk_menu_item_new(); + + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_title), menu); + + /* Allow this menu to grab the pointer. */ + toplevel = gtk_widget_get_toplevel (menu); + if (GTK_IS_WINDOW (toplevel)) + { + gtk_window_group_add_window (cp_gtk_global_window_group, + GTK_WINDOW(toplevel)); + } + + gtk_widget_show (menu_title); + + NSA_SET_PTR (env, obj, menu_title); + + (*env)->ReleaseStringUTFChars (env, label, str); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuPeer_addTearOff + (JNIEnv *env, jobject obj) +{ + void *ptr1; + GtkWidget *menu, *item; + + gdk_threads_enter (); + + ptr1 = NSA_GET_PTR (env, obj); + + menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (ptr1)); + item = gtk_tearoff_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuPeer_addItem + (JNIEnv *env, jobject obj, jobject menuitempeer, jint key, jboolean shift) +{ + void *ptr1, *ptr2; + GtkWidget *menu; + + gdk_threads_enter (); + + ptr1 = NSA_GET_PTR (env, obj); + ptr2 = NSA_GET_PTR (env, menuitempeer); + + menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(ptr1)); + gtk_menu_shell_append (GTK_MENU_SHELL(menu), GTK_WIDGET (ptr2)); + + if (key) + { + gtk_widget_add_accelerator (GTK_WIDGET (ptr2), "activate", + gtk_menu_get_accel_group (GTK_MENU (menu)), key, + (GDK_CONTROL_MASK + | ((shift) ? GDK_SHIFT_MASK : 0)), + GTK_ACCEL_VISIBLE); + } + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkMenuPeer_delItem + (JNIEnv *env, jobject obj, jint index) +{ + void *ptr; + GList *list; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + list = gtk_container_children (GTK_CONTAINER (ptr)); + list = g_list_nth (list, index); + gtk_container_remove (GTK_CONTAINER (ptr), GTK_WIDGET (list->data)); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPanelPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPanelPeer.c new file mode 100644 index 00000000000..8a130e1a4b3 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPanelPeer.c @@ -0,0 +1,112 @@ +/* gtkpanelpeer.c -- Native implementation of GtkPanelPeer + Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h" +#include "gnu_java_awt_peer_gtk_GtkPanelPeer.h" + +static gboolean panel_focus_in_cb (GtkWidget * widget, + GdkEventFocus *event, + jobject peer); +static gboolean panel_focus_out_cb (GtkWidget * widget, + GdkEventFocus *event, + jobject peer); + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkPanelPeer_create + (JNIEnv *env, jobject obj) +{ + GtkWidget *widget; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + widget = gtk_fixed_new (); + + gtk_fixed_set_has_window (GTK_FIXED (widget), TRUE); + + GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); + + NSA_SET_PTR (env, obj, widget); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkPanelPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr; + jobject *gref; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + /* Panel signals. These callbacks prevent expose events being + delivered to the panel when it is focused. */ + g_signal_connect (G_OBJECT (ptr), "focus-in-event", + G_CALLBACK (panel_focus_in_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "focus-out-event", + G_CALLBACK (panel_focus_out_cb), *gref); + + /* Component signals. Exclude focus signals. */ + cp_gtk_component_connect_expose_signals (ptr, gref); + cp_gtk_component_connect_mouse_signals (ptr, gref); + + gdk_threads_leave (); +} + +static gboolean +panel_focus_in_cb (GtkWidget * widget __attribute__((unused)), + GdkEventFocus *event __attribute__((unused)), + jobject peer __attribute__((unused))) +{ + return TRUE; +} + +static gboolean +panel_focus_out_cb (GtkWidget * widget __attribute__((unused)), + GdkEventFocus *event __attribute__((unused)), + jobject peer __attribute__((unused))) +{ + return TRUE; +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPopupMenuPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPopupMenuPeer.c new file mode 100644 index 00000000000..e684a090f8f --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPopupMenuPeer.c @@ -0,0 +1,105 @@ +/* gtkpopupmenupeer.c -- Native implementation of GtkPopupMenuPeer + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkPopupMenuPeer.h" + +struct pos +{ + gint x; + gint y; +}; + +static void +menu_pos (GtkMenu *menu __attribute__((unused)), + gint *x, gint *y, + gboolean *push_in, + gpointer user_data) +{ + struct pos *p = (struct pos *) user_data; + + *x = p->x; + *y = p->y; + *push_in = TRUE; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkPopupMenuPeer_show + (JNIEnv *env, jobject obj, jint x, jint y, jlong time) +{ + void *ptr; + struct pos *p; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + p = g_malloc (sizeof (struct pos)); + p->x = x; + p->y = y; + + gtk_menu_popup (GTK_MENU (GTK_MENU_ITEM (ptr)->submenu), + NULL, NULL, menu_pos, p, 0, time); + + g_free (p); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkPopupMenuPeer_setupAccelGroup + (JNIEnv *env, jobject obj, jobject parent) +{ + void *ptr1, *ptr2; + GtkMenu *menu; + + gdk_threads_enter (); + + ptr1 = NSA_GET_PTR (env, obj); + ptr2 = NSA_GET_PTR (env, parent); + + menu = GTK_MENU (GTK_MENU_ITEM (ptr1)->submenu); + gtk_menu_set_accel_group (menu, gtk_accel_group_new ()); + /* FIXME: update this to use GTK-2.4 GtkActions. */ +#if 0 + _gtk_accel_group_attach (gtk_menu_get_accel_group (menu), + G_OBJECT (gtk_widget_get_toplevel (ptr2))); +#endif + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollPanePeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollPanePeer.c new file mode 100644 index 00000000000..1445cec5577 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollPanePeer.c @@ -0,0 +1,205 @@ +/* gtkscrollpanepeer.c -- Native implementation of GtkScrollPanePeer + Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkScrollPanePeer.h" + +#define AWT_SCROLLPANE_SCROLLBARS_AS_NEEDED 0 +#define AWT_SCROLLPANE_SCROLLBARS_ALWAYS 1 +#define AWT_SCROLLPANE_SCROLLBARS_NEVER 2 + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollPanePeer_create + (JNIEnv *env, jobject obj, int width, int height) +{ + GtkWidget *sw; + + gdk_threads_enter (); + + /* Create global reference and save it for future use */ + NSA_SET_GLOBAL_REF (env, obj); + + sw = gtk_scrolled_window_new (NULL, NULL); + + gtk_widget_set_size_request (sw, width, height); + + NSA_SET_PTR (env, obj, sw); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollPanePeer_setScrollPosition + (JNIEnv *env, jobject obj, jint x, jint y) +{ + GtkAdjustment *hadj, *vadj; + GtkScrolledWindow *sw; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + sw = GTK_SCROLLED_WINDOW (ptr); + + hadj = gtk_scrolled_window_get_hadjustment (sw); + vadj = gtk_scrolled_window_get_vadjustment (sw); + + gtk_adjustment_set_value (hadj, x); + gtk_adjustment_set_value (vadj, y); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollPanePeer_gtkScrolledWindowSetHScrollIncrement + (JNIEnv *env, jobject obj, jint u) +{ + GtkAdjustment *hadj; + GtkScrolledWindow *sw; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + sw = GTK_SCROLLED_WINDOW(ptr); + + hadj = gtk_scrolled_window_get_hadjustment (sw); + hadj->step_increment = u; + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollPanePeer_gtkScrolledWindowSetVScrollIncrement + (JNIEnv *env, jobject obj, jint u) +{ + GtkAdjustment *vadj; + GtkScrolledWindow *sw; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + sw = GTK_SCROLLED_WINDOW(ptr); + + vadj = gtk_scrolled_window_get_hadjustment (sw); + vadj->step_increment = u; + + gdk_threads_leave (); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollPanePeer_getHScrollbarHeight + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkScrolledWindow *sw; + GtkRequisition requisition; + jint height = 0; + jint spacing = 0; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + sw = GTK_SCROLLED_WINDOW (ptr); + + gtk_widget_size_request (sw->hscrollbar, &requisition); + gtk_widget_style_get (GTK_WIDGET (sw), "scrollbar_spacing", &spacing, NULL); + height = requisition.height + spacing; + + gdk_threads_leave (); + + return height; +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollPanePeer_getVScrollbarWidth + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkScrolledWindow *sw; + GtkRequisition requisition; + jint width = 0; + jint spacing = 0; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + sw = GTK_SCROLLED_WINDOW (ptr); + + gtk_widget_size_request (sw->vscrollbar, &requisition); + gtk_widget_style_get (GTK_WIDGET (sw), "scrollbar_spacing", &spacing, NULL); + width = requisition.width + spacing; + + gdk_threads_leave (); + + return width; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollPanePeer_setPolicy + (JNIEnv *env, jobject obj, jint policy) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + switch (policy) + { + case AWT_SCROLLPANE_SCROLLBARS_AS_NEEDED: + policy = GTK_POLICY_AUTOMATIC; + break; + case AWT_SCROLLPANE_SCROLLBARS_ALWAYS: + policy = GTK_POLICY_ALWAYS; + break; + case AWT_SCROLLPANE_SCROLLBARS_NEVER: + policy = GTK_POLICY_NEVER; + break; + } + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ptr), policy, policy); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollbarPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollbarPeer.c new file mode 100644 index 00000000000..39686271084 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollbarPeer.c @@ -0,0 +1,258 @@ +/* gtkscrollbarpeer.c -- Native implementation of GtkScrollbarPeer + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include <math.h> +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h" +#include "gnu_java_awt_peer_gtk_GtkScrollbarPeer.h" + +#define AWT_ADJUSTMENT_UNIT_INCREMENT 1 +#define AWT_ADJUSTMENT_UNIT_DECREMENT 2 +#define AWT_ADJUSTMENT_BLOCK_DECREMENT 3 +#define AWT_ADJUSTMENT_BLOCK_INCREMENT 4 +#define AWT_ADJUSTMENT_TRACK 5 + +static jmethodID postAdjustmentEventID; + +void +cp_gtk_scrollbar_init_jni (void) +{ + jclass gtkscrollbarpeer; + + gtkscrollbarpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkScrollbarPeer"); + + postAdjustmentEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), + gtkscrollbarpeer, + "postAdjustmentEvent", + "(II)V"); +} + +#if GTK_MINOR_VERSION > 4 +static gboolean slider_moved_cb (GtkRange *range, + GtkScrollType scroll, + gdouble value, + jobject obj); +#else +static void post_change_event_cb (GtkRange *range, + jobject peer); +#endif + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_create + (JNIEnv *env, jobject obj, jint orientation, jint value, + jint min, jint max, jint step_incr, jint page_incr, jint visible_amount) +{ + GtkWidget *scrollbar; + GtkObject *adj; + + /* Create global reference and save it for future use */ + NSA_SET_GLOBAL_REF (env, obj); + + gdk_threads_enter (); + + adj = gtk_adjustment_new ((gdouble) value, + (gdouble) min, + (gdouble) max, + (gdouble) step_incr, + (gdouble) page_incr, + (gdouble) visible_amount); + + scrollbar = orientation + ? gtk_vscrollbar_new (GTK_ADJUSTMENT (adj)) + : gtk_hscrollbar_new (GTK_ADJUSTMENT (adj)); + + GTK_RANGE (scrollbar)->round_digits = 0; + /* These calls seem redundant but they are not. They clamp values + so that the slider's entirety is always between the two + steppers. */ + gtk_range_set_range (GTK_RANGE (scrollbar), (gdouble) min, (gdouble) max); + gtk_range_set_value (GTK_RANGE (scrollbar), (gdouble) value); + + gdk_threads_leave (); + + NSA_SET_PTR (env, obj, scrollbar); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr = NSA_GET_PTR (env, obj); + jobject *gref = NSA_GET_GLOBAL_REF (env, obj); + g_assert (gref); + + gdk_threads_enter (); + + /* Scrollbar signals */ +#if GTK_MINOR_VERSION > 4 + g_signal_connect (G_OBJECT (ptr), "change-value", + G_CALLBACK (slider_moved_cb), *gref); +#else + g_signal_connect (G_OBJECT (ptr), "value-changed", + G_CALLBACK (post_change_event_cb), *gref); +#endif + + /* Component signals */ + cp_gtk_component_connect_signals (G_OBJECT (ptr), gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setLineIncrement + (JNIEnv *env, jobject obj, jint amount) +{ + void *ptr; + GtkAdjustment *adj; + + ptr = NSA_GET_PTR (env, obj); + + gdk_threads_enter (); + + adj = gtk_range_get_adjustment (GTK_RANGE (ptr)); + adj->step_increment = (gdouble) amount; + gtk_adjustment_changed (adj); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setPageIncrement + (JNIEnv *env, jobject obj, jint amount) +{ + void *ptr; + GtkAdjustment *adj; + + ptr = NSA_GET_PTR (env, obj); + + gdk_threads_enter (); + + adj = gtk_range_get_adjustment (GTK_RANGE (ptr)); + adj->page_increment = (gdouble) amount; + gtk_adjustment_changed (adj); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setValues + (JNIEnv *env, jobject obj, jint value, jint visible, jint min, jint max) +{ + void *ptr; + GtkAdjustment *adj; + + ptr = NSA_GET_PTR (env, obj); + + gdk_threads_enter (); + + adj = gtk_range_get_adjustment (GTK_RANGE (ptr)); + adj->page_size = (gdouble) visible; + + gtk_range_set_range (GTK_RANGE (ptr), (gdouble) min, (gdouble) max); + gtk_range_set_value (GTK_RANGE (ptr), (gdouble) value); + + gdk_threads_leave (); +} + +#if GTK_MINOR_VERSION > 4 +static gboolean +slider_moved_cb (GtkRange *range, + GtkScrollType scroll, + gdouble value, + jobject obj) +{ + GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (range)); + + value = CLAMP (value, adj->lower, + (adj->upper - adj->page_size)); + + if (range->round_digits >= 0) + { + gdouble power; + gint i; + + i = range->round_digits; + power = 1; + while (i--) + power *= 10; + + value = floor ((value * power) + 0.5) / power; + } + + switch (scroll) + { + case GTK_SCROLL_STEP_BACKWARD: + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID, + AWT_ADJUSTMENT_UNIT_DECREMENT, + (jint) value); + break; + case GTK_SCROLL_STEP_FORWARD: + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID, + AWT_ADJUSTMENT_UNIT_INCREMENT, + (jint) value); + break; + case GTK_SCROLL_PAGE_BACKWARD: + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID, + AWT_ADJUSTMENT_BLOCK_DECREMENT, + (jint) value); + break; + case GTK_SCROLL_PAGE_FORWARD: + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID, + AWT_ADJUSTMENT_BLOCK_INCREMENT, + (jint) value); + break; + default: + /* GTK_SCROLL_JUMP: */ + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj, postAdjustmentEventID, + AWT_ADJUSTMENT_TRACK, + (jint) value); + break; + } + return FALSE; +} +#else +static void +post_change_event_cb (GtkRange *range, jobject peer) +{ + GtkAdjustment *adj; + adj = gtk_range_get_adjustment (range); + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postAdjustmentEventID, + AWT_ADJUSTMENT_TRACK, (jint) adj->value); +} +#endif diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c new file mode 100644 index 00000000000..9af88a026ee --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c @@ -0,0 +1,522 @@ +/* gtktextareapeer.c -- Native implementation of GtkTextAreaPeer + Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkTextAreaPeer.h" + +#define AWT_TEXTAREA_SCROLLBARS_BOTH 0 +#define AWT_TEXTAREA_SCROLLBARS_VERTICAL_ONLY 1 +#define AWT_TEXTAREA_SCROLLBARS_HORIZONTAL_ONLY 2 + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_create + (JNIEnv *env, jobject obj, + jint textview_width, jint textview_height, jint scroll) +{ + GtkWidget *text, *sw; + + gdk_threads_enter (); + + /* Create global reference and save it for future use */ + NSA_SET_GLOBAL_REF (env, obj); + + text = gtk_text_view_new (); + gtk_widget_set_size_request (text, textview_width, textview_height); + gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW (text), TRUE); + + gtk_widget_show (text); + + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_container_add (GTK_CONTAINER (sw), text); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + /* horizontal scrollbar */ + (scroll == AWT_TEXTAREA_SCROLLBARS_BOTH + || scroll == AWT_TEXTAREA_SCROLLBARS_HORIZONTAL_ONLY) ? + GTK_POLICY_ALWAYS : GTK_POLICY_NEVER, + /* vertical scrollbar */ + (scroll == AWT_TEXTAREA_SCROLLBARS_BOTH + || scroll == AWT_TEXTAREA_SCROLLBARS_VERTICAL_ONLY) ? + GTK_POLICY_ALWAYS : GTK_POLICY_NEVER); + + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text), + (scroll == AWT_TEXTAREA_SCROLLBARS_BOTH + || scroll == AWT_TEXTAREA_SCROLLBARS_HORIZONTAL_ONLY) + ? GTK_WRAP_NONE : GTK_WRAP_WORD); + + NSA_SET_PTR (env, obj, sw); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + GtkWidget *text = NULL; + GtkTextBuffer *buf; + void *ptr; + jobject *gref; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + /* Unwrap the text view from the scrolled window */ + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + + /* TextComponent signals */ + cp_gtk_textcomponent_connect_signals (G_OBJECT (buf), gref); + + /* Component signals */ + cp_gtk_component_connect_signals (G_OBJECT (text), gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_insert + (JNIEnv *env, jobject obj, jstring contents, jint position) +{ + GtkTextBuffer *buf; + GtkTextIter iter; + GtkWidget *text; + void *ptr; + const char *str; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + str = (*env)->GetStringUTFChars (env, contents, NULL); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + gtk_text_buffer_get_iter_at_offset (buf, &iter, position); + gtk_text_buffer_insert (buf, &iter, str, strlen (str)); + + (*env)->ReleaseStringUTFChars (env, contents, str); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_replaceRange + (JNIEnv *env, jobject obj, jstring contents, jint start, jint end) +{ + GtkWidget *text; + GtkTextBuffer *buf; + GtkTextIter iter, startIter, endIter; + void *ptr; + const char *str; + int mystart = start; + int myend = end; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + str = (*env)->GetStringUTFChars (env, contents, NULL); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + + gtk_text_buffer_get_iter_at_offset (buf, &startIter, mystart); + gtk_text_buffer_get_iter_at_offset (buf, &endIter, myend); + gtk_text_buffer_delete (buf, &startIter, &endIter); + + gtk_text_buffer_get_iter_at_offset (buf, &iter, mystart); + gtk_text_buffer_insert(buf, &iter, str, strlen (str)); + + (*env)->ReleaseStringUTFChars (env, contents, str); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_gtkWidgetModifyFont + (JNIEnv *env, jobject obj, jstring name, jint style, jint size) +{ + const char *font_name; + void *ptr; + GtkWidget *text; + PangoFontDescription *font_desc; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, obj); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + font_name = (*env)->GetStringUTFChars (env, name, NULL); + + font_desc = pango_font_description_from_string (font_name); + pango_font_description_set_size (font_desc, + size * cp_gtk_dpi_conversion_factor); + + if (style & AWT_STYLE_BOLD) + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + + if (style & AWT_STYLE_ITALIC) + pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); + + gtk_widget_modify_font (GTK_WIDGET (text), font_desc); + + pango_font_description_free (font_desc); + + (*env)->ReleaseStringUTFChars (env, name, font_name); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_gtkWidgetRequestFocus + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkWidget *text; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + gtk_widget_grab_focus (text); + + gdk_threads_leave (); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getHScrollbarHeight + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkScrolledWindow *sw; + GtkRequisition requisition; + jint height = 0; + jint spacing = 0; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + sw = GTK_SCROLLED_WINDOW (ptr); + + if (sw) + { + gtk_widget_size_request (sw->hscrollbar, &requisition); + gtk_widget_style_get (GTK_WIDGET (sw), "scrollbar_spacing", &spacing, NULL); + height = requisition.height + spacing; + } + + gdk_threads_leave (); + + return height; +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getVScrollbarWidth + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkScrolledWindow *sw; + GtkRequisition requisition; + jint width = 0; + jint spacing = 0; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + sw = GTK_SCROLLED_WINDOW (ptr); + + if (sw) + { + gtk_widget_size_request (sw->vscrollbar, &requisition); + gtk_widget_style_get (GTK_WIDGET (sw), "scrollbar_spacing", &spacing, NULL); + width = requisition.width + spacing; + } + + gdk_threads_leave (); + + return width; +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getCaretPosition + (JNIEnv *env, jobject obj) +{ + void *ptr; + int pos = 0; + GtkWidget *text = NULL; + GtkTextBuffer *buf; + GtkTextMark *mark; + GtkTextIter iter; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + mark = gtk_text_buffer_get_insert (buf); + gtk_text_buffer_get_iter_at_mark (buf, &iter, mark); + pos = gtk_text_iter_get_offset (&iter); + + gdk_threads_leave (); + + return pos; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_setCaretPosition + (JNIEnv *env, jobject obj, jint pos) +{ + void *ptr; + GtkWidget *text = NULL; + GtkTextBuffer *buf; + GtkTextIter iter; + GtkTextMark *oldmark; + GtkTextIter olditer; + int oldpos; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + + /* Save old position. */ + oldmark = gtk_text_buffer_get_insert (buf); + gtk_text_buffer_get_iter_at_mark (buf, &olditer, oldmark); + oldpos = gtk_text_iter_get_offset (&olditer); + + /* Move to new position. */ + gtk_text_buffer_get_iter_at_offset (buf, &iter, pos); + gtk_text_buffer_place_cursor (buf, &iter); + + /* Scroll to new position. Alignment is determined + comparing the new position to the old position. */ + if (oldpos > pos) + gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (text), + &iter, 0, TRUE, 0, 0); + else if (oldpos < pos) + gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (text), + &iter, 0, TRUE, 1, 1); + + gdk_threads_leave (); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getSelectionStart + (JNIEnv *env, jobject obj) +{ + void *ptr; + int pos = 0; + GtkWidget *text = NULL; + GtkTextBuffer *buf; + GtkTextIter start; + GtkTextIter end; + GtkTextMark *mark; + GtkTextIter iter; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + + if (gtk_text_buffer_get_selection_bounds (buf, &start, &end)) + { + pos = gtk_text_iter_get_offset (&start); + } + else + { + mark = gtk_text_buffer_get_insert (buf); + gtk_text_buffer_get_iter_at_mark (buf, &iter, mark); + pos = gtk_text_iter_get_offset (&iter); + } + + gdk_threads_leave (); + + return pos; +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getSelectionEnd + (JNIEnv *env, jobject obj) +{ + void *ptr; + int pos = 0; + GtkWidget *text = NULL; + GtkTextBuffer *buf; + GtkTextIter start; + GtkTextIter end; + GtkTextMark *mark; + GtkTextIter iter; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + + if (gtk_text_buffer_get_selection_bounds (buf, &start, &end)) + { + pos = gtk_text_iter_get_offset (&end); + } + else + { + mark = gtk_text_buffer_get_insert (buf); + gtk_text_buffer_get_iter_at_mark (buf, &iter, mark); + pos = gtk_text_iter_get_offset (&iter); + } + + gdk_threads_leave (); + + return pos; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_select + (JNIEnv *env, jobject obj, jint start, jint end) +{ + void *ptr; + GtkWidget *text = NULL; + GtkTextBuffer *buf; + GtkTextIter iter; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + gtk_text_buffer_get_iter_at_offset (buf, &iter, start); + /* quickly move both 'insert' and 'selection_bound' to the + same position */ + gtk_text_buffer_place_cursor (buf, &iter); + gtk_text_buffer_get_iter_at_offset (buf, &iter, end); + gtk_text_buffer_move_mark_by_name (buf, "selection_bound", &iter); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_setEditable + (JNIEnv *env, jobject obj, jboolean state) +{ + void *ptr; + GtkWidget *text = NULL; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + gtk_text_view_set_editable (GTK_TEXT_VIEW (text), state); + + gdk_threads_leave (); +} + +JNIEXPORT jstring JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getText + (JNIEnv *env, jobject obj) +{ + void *ptr; + char *contents = NULL; + jstring jcontents; + GtkWidget *text = NULL; + GtkTextBuffer *buf; + GtkTextIter start, end; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + gtk_text_buffer_get_start_iter (buf, &start); + gtk_text_buffer_get_end_iter (buf, &end); + contents = gtk_text_buffer_get_text (buf, &start, &end, FALSE); + + jcontents = (*env)->NewStringUTF (env, contents); + g_free (contents); + + gdk_threads_leave (); + + return jcontents; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_setText + (JNIEnv *env, jobject obj, jstring contents) +{ + void *ptr; + const char *str; + GtkWidget *text = NULL; + GtkTextBuffer *buf; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + str = (*env)->GetStringUTFChars (env, contents, NULL); + + text = gtk_bin_get_child (GTK_BIN (ptr)); + + buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)); + gtk_text_buffer_set_text (buf, str, strlen (str)); + + (*env)->ReleaseStringUTFChars (env, contents, str); + + gdk_threads_leave (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c new file mode 100644 index 00000000000..eb658339dab --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c @@ -0,0 +1,423 @@ +/* gtktextfieldpeer.c -- Native implementation of GtkTextFieldPeer + Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkTextFieldPeer.h" + +/* the color used for highlighting when the foreground is black, + since black highlights aren't a Good Idea. */ +#define BB_RED 16962 +#define BB_GREEN 26985 +#define BB_BLUE 31611 + +static jmethodID postTextEventID; + +void +cp_gtk_textcomponent_init_jni (void) +{ + jclass gtkcomponentpeer; + + gtkcomponentpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkComponentPeer"); + + postTextEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer, + "postTextEvent", + "()V"); +} + +static void textcomponent_changed_cb (GtkEditable *editable, jobject peer); + +static jint get_border_width (GtkWidget *entry); + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_create + (JNIEnv *env, jobject obj, jint text_width) +{ + GtkWidget *entry; + + gdk_threads_enter (); + + /* Create global reference and save it for future use */ + NSA_SET_GLOBAL_REF (env, obj); + + entry = gtk_entry_new (); + gtk_widget_set_size_request (entry, + text_width + 2 * get_border_width (entry), -1); + + NSA_SET_PTR (env, obj, entry); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr; + jobject *gref; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + /* TextComponent signals */ + cp_gtk_textcomponent_connect_signals (G_OBJECT (ptr), gref); + + /* Component signals */ + cp_gtk_component_connect_signals (G_OBJECT (ptr), gref); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_gtkWidgetSetBackground + (JNIEnv *env, jobject obj, jint red, jint green, jint blue) +{ + GdkColor color; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + color.red = (red / 255.0) * 65535; + color.green = (green / 255.0) * 65535; + color.blue = (blue / 255.0) * 65535; + + gtk_widget_modify_base (GTK_WIDGET (ptr), GTK_STATE_NORMAL, &color); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_gtkWidgetSetForeground + (JNIEnv *env, jobject obj, jint red, jint green, jint blue) +{ + GdkColor color; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + color.red = (red / 255.0) * 65535; + color.green = (green / 255.0) * 65535; + color.blue = (blue / 255.0) * 65535; + + gtk_widget_modify_text (GTK_WIDGET (ptr), GTK_STATE_NORMAL, &color); + + if ( red == 0 && green == 0 && blue == 0) + { + color.red = BB_RED; + color.green = BB_GREEN; + color.blue = BB_BLUE; + } + gtk_widget_modify_base (GTK_WIDGET (ptr), GTK_STATE_SELECTED, &color); + + gdk_threads_leave (); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_gtkEntryGetBorderWidth + (JNIEnv *env, jobject obj) +{ + void *ptr; + int border_width = 0; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + border_width = get_border_width (GTK_WIDGET (ptr)); + + gdk_threads_leave (); + + return border_width; +} + +/* GTK hard-codes this value. It is the space between a GtkEntry's + frame and its text. */ +#define INNER_BORDER 2 + +static jint +get_border_width (GtkWidget *entry) +{ + gint focus_width; + gboolean interior_focus; + int x_border_width = INNER_BORDER; + + gtk_widget_style_get (entry, + "interior-focus", &interior_focus, + "focus-line-width", &focus_width, + NULL); + + if (GTK_ENTRY (entry)->has_frame) + x_border_width += entry->style->xthickness; + + if (!interior_focus) + x_border_width += focus_width; + + return x_border_width; +} + +#undef INNER_BORDER + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_setEchoChar + (JNIEnv *env, jobject obj, jchar c) +{ + void *ptr; + GtkEntry *entry; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + entry = GTK_ENTRY (ptr); + + if (c != 0) + { + /* FIXME: use gtk_entry_set_invisible_char (GtkEntry *entry, + gunichar ch) here. That means we must convert from jchar + (utf16) to gunichar (ucs4). */ + gtk_entry_set_visibility (entry, FALSE); + } + else + gtk_entry_set_visibility (entry, TRUE); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_gtkWidgetModifyFont + (JNIEnv *env, jobject obj, jstring name, jint style, jint size) +{ + const char *font_name; + void *ptr; + PangoFontDescription *font_desc; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, obj); + + font_name = (*env)->GetStringUTFChars (env, name, NULL); + + font_desc = pango_font_description_from_string (font_name); + pango_font_description_set_size (font_desc, + size * cp_gtk_dpi_conversion_factor); + + if (style & AWT_STYLE_BOLD) + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + + if (style & AWT_STYLE_ITALIC) + pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); + + gtk_widget_modify_font (GTK_WIDGET (ptr), font_desc); + + pango_font_description_free (font_desc); + + (*env)->ReleaseStringUTFChars (env, name, font_name); + + gdk_threads_leave(); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_getCaretPosition + (JNIEnv *env, jobject obj) +{ + void *ptr; + int pos = 0; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + pos = gtk_editable_get_position (GTK_EDITABLE (ptr)); + + gdk_threads_leave (); + + return pos; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_setCaretPosition + (JNIEnv *env, jobject obj, jint pos) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_editable_set_position (GTK_EDITABLE (ptr), pos); + + gdk_threads_leave (); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_getSelectionStart + (JNIEnv *env, jobject obj) +{ + void *ptr; + int pos = 0; + int starti, endi; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (ptr), &starti, &endi)) + pos = starti; + else + pos = gtk_editable_get_position (GTK_EDITABLE (ptr)); + + gdk_threads_leave (); + + return pos; +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_getSelectionEnd + (JNIEnv *env, jobject obj) +{ + void *ptr; + int pos = 0; + int starti, endi; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (ptr), &starti, &endi)) + pos = endi; + else + pos = gtk_editable_get_position (GTK_EDITABLE (ptr)); + + gdk_threads_leave (); + + return pos; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_select + (JNIEnv *env, jobject obj, jint start, jint end) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_editable_select_region (GTK_EDITABLE (ptr), start, end); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_setEditable + (JNIEnv *env, jobject obj, jboolean state) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_editable_set_editable (GTK_EDITABLE (ptr), state); + + gdk_threads_leave (); +} + +JNIEXPORT jstring JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_getText + (JNIEnv *env, jobject obj) +{ + void *ptr; + char *contents = NULL; + jstring jcontents; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + contents = gtk_editable_get_chars (GTK_EDITABLE (ptr), 0, -1); + + jcontents = (*env)->NewStringUTF (env, contents); + + g_free (contents); + + gdk_threads_leave (); + + return jcontents; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_setText + (JNIEnv *env, jobject obj, jstring contents) +{ + void *ptr; + const char *str; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + str = (*env)->GetStringUTFChars (env, contents, NULL); + + gtk_entry_set_text (GTK_ENTRY (ptr), str); + + (*env)->ReleaseStringUTFChars (env, contents, str); + + gdk_threads_leave (); +} + +void +cp_gtk_textcomponent_connect_signals (GObject *ptr, jobject *gref) +{ + g_signal_connect (G_OBJECT(ptr), "changed", + G_CALLBACK (textcomponent_changed_cb), *gref); +} + +static void +textcomponent_changed_cb (GtkEditable *editable __attribute__((unused)), + jobject peer) +{ + gdk_threads_leave (); + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postTextEventID); + gdk_threads_enter (); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c new file mode 100644 index 00000000000..a8e1957ee20 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c @@ -0,0 +1,524 @@ +/* gtktoolkit.c -- Native portion of GtkToolkit + Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkToolkit.h" +#include "gthread-jni.h" +#include "jcl.h" + +#include <sys/time.h> + +#define RC_FILE ".classpath-gtkrc" + +/* From java.awt.SystemColor */ +#define AWT_DESKTOP 0 +#define AWT_ACTIVE_CAPTION 1 +#define AWT_ACTIVE_CAPTION_TEXT 2 +#define AWT_ACTIVE_CAPTION_BORDER 3 +#define AWT_INACTIVE_CAPTION 4 +#define AWT_INACTIVE_CAPTION_TEXT 5 +#define AWT_INACTIVE_CAPTION_BORDER 6 +#define AWT_WINDOW 7 +#define AWT_WINDOW_BORDER 8 +#define AWT_WINDOW_TEXT 9 +#define AWT_MENU 10 +#define AWT_MENU_TEXT 11 +#define AWT_TEXT 12 +#define AWT_TEXT_TEXT 13 +#define AWT_TEXT_HIGHLIGHT 14 +#define AWT_TEXT_HIGHLIGHT_TEXT 15 +#define AWT_TEXT_INACTIVE_TEXT 16 +#define AWT_CONTROL 17 +#define AWT_CONTROL_TEXT 18 +#define AWT_CONTROL_HIGHLIGHT 19 +#define AWT_CONTROL_LT_HIGHLIGHT 20 +#define AWT_CONTROL_SHADOW 21 +#define AWT_CONTROL_DK_SHADOW 22 +#define AWT_SCROLLBAR 23 +#define AWT_INFO 24 +#define AWT_INFO_TEXT 25 +#define AWT_NUM_COLORS 26 + +struct state_table *cp_gtk_native_state_table; +struct state_table *cp_gtk_native_global_ref_table; + +static jclass gtkgenericpeer; +static JavaVM *java_vm; +static jmethodID printCurrentThreadID; + +union env_union +{ + void *void_env; + JNIEnv *jni_env; +}; + +JNIEnv * +cp_gtk_gdk_env() +{ + union env_union tmp; + g_assert((*java_vm)->GetEnv(java_vm, &tmp.void_env, JNI_VERSION_1_2) == JNI_OK); + return tmp.jni_env; +} + + +GtkWindowGroup *cp_gtk_global_window_group; +double cp_gtk_dpi_conversion_factor; + +static void init_glib_threads(JNIEnv *, jint); + +static void init_dpi_conversion_factor (void); +static void dpi_changed_cb (GtkSettings *settings, + GParamSpec *pspec); + +#if GTK_MINOR_VERSION > 4 +static GLogFunc old_glog_func; +static void glog_func (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data); +#endif + +/* + * Call gtk_init. It is very important that this happen before any other + * gtk calls. + * + * The portableNativeSync argument may have the values: + * 1 if the Java property gnu.classpath.awt.gtk.portable.native.sync + * is set to "true". + * 0 if it is set to "false" + * -1 if unset. + */ + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkInit (JNIEnv *env, + jclass clazz __attribute__((unused)), + jint portableNativeSync) +{ + int argc = 1; + char **argv; + char *homedir, *rcpath = NULL; + + gtkgenericpeer = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GtkGenericPeer"); + + printCurrentThreadID = (*env)->GetStaticMethodID (env, gtkgenericpeer, + "printCurrentThread", "()V"); + + NSA_INIT (env, gtkgenericpeer); + + g_assert((*env)->GetJavaVM(env, &java_vm) == 0); + + /* GTK requires a program's argc and argv variables, and requires that they + be valid. Set it up. */ + argv = (char **) g_malloc (sizeof (char *) * 2); + argv[0] = (char *) g_malloc(1); + argv[0][0] = '\0'; + argv[1] = NULL; + + init_glib_threads(env, portableNativeSync); + + /* From GDK 2.0 onwards we have to explicitly call gdk_threads_init */ + gdk_threads_init(); + + gtk_init (&argc, &argv); + + gdk_rgb_init (); + gtk_widget_set_default_colormap (gdk_rgb_get_cmap ()); + gtk_widget_set_default_visual (gdk_rgb_get_visual ()); + + /* Make sure queued calls don't get sent to GTK/GDK while + we're shutting down. */ + atexit (gdk_threads_enter); + + if ((homedir = getenv ("HOME"))) + { + rcpath = (char *) g_malloc (strlen (homedir) + strlen (RC_FILE) + 2); + sprintf (rcpath, "%s/%s", homedir, RC_FILE); + } + + gtk_rc_parse ((rcpath) ? rcpath : RC_FILE); + + g_free (rcpath); + g_free (argv[0]); + g_free (argv); + + /* On errors or warning print a whole stacktrace. */ +#if GTK_MINOR_VERSION > 4 + old_glog_func = g_log_set_default_handler (&glog_func, NULL); +#endif + +#if GTK_CAIRO + cp_gtk_graphics2d_init_jni (); +#endif + cp_gtk_graphics_init_jni (); + cp_gtk_button_init_jni (); + cp_gtk_checkbox_init_jni (); + cp_gtk_choice_init_jni (); + cp_gtk_component_init_jni (); + cp_gtk_list_init_jni (); + cp_gtk_menuitem_init_jni (); + cp_gtk_scrollbar_init_jni (); + cp_gtk_textcomponent_init_jni (); + cp_gtk_window_init_jni (); + + cp_gtk_global_window_group = gtk_window_group_new (); + + init_dpi_conversion_factor (); +} + + +/** Initialize GLIB's threads properly, based on the value of the + gnu.classpath.awt.gtk.portable.native.sync Java system property. If + that's unset, use the PORTABLE_NATIVE_SYNC config.h macro. (TODO: + In some release following 0.10, that config.h macro will go away.) + */ +static void +init_glib_threads(JNIEnv *env, jint portableNativeSync) +{ + if (portableNativeSync < 0) + { +#ifdef PORTABLE_NATIVE_SYNC /* Default value, if not set by the Java system + property */ + portableNativeSync = 1; +#else + portableNativeSync = 0; +#endif + } + + (*env)->GetJavaVM( env, &cp_gtk_the_vm ); + if (!g_thread_supported ()) + { + if (portableNativeSync) + g_thread_init ( &cp_gtk_portable_native_sync_jni_functions ); + else + g_thread_init ( NULL ); + } + else + { + /* Warn if portable native sync is desired but the threading + system is already initialized. In that case we can't + override the threading implementation with our portable + native sync functions. */ + if (portableNativeSync) + g_printerr ("peer warning: portable native sync disabled.\n"); + } + + /* Debugging progress message; uncomment if needed: */ + /* printf("called gthread init\n"); */ +} + +void +cp_gtk_print_current_thread (void) +{ + (*cp_gtk_gdk_env())->CallStaticVoidMethod (cp_gtk_gdk_env(), gtkgenericpeer, printCurrentThreadID); +} + +/* This is a big hack, needed until this pango bug is resolved: + http://bugzilla.gnome.org/show_bug.cgi?id=119081. + See: http://mail.gnome.org/archives/gtk-i18n-list/2003-August/msg00001.html + for details. */ +static void +init_dpi_conversion_factor () +{ + GtkSettings *settings = gtk_settings_get_default (); + GObjectClass *klass; + + klass = G_OBJECT_CLASS (GTK_SETTINGS_GET_CLASS (settings)); + if (g_object_class_find_property (klass, "gtk-xft-dpi")) + { + int int_dpi; + g_object_get (settings, "gtk-xft-dpi", &int_dpi, NULL); + /* If int_dpi == -1 gtk-xft-dpi returns the default value. So we + have to do approximate calculation here. */ + if (int_dpi < 0) + cp_gtk_dpi_conversion_factor = PANGO_SCALE * 72.0 / 96.; + else + cp_gtk_dpi_conversion_factor = + PANGO_SCALE * 72.0 / (int_dpi / PANGO_SCALE); + + g_signal_connect (settings, "notify::gtk-xft-dpi", + G_CALLBACK (dpi_changed_cb), NULL); + } + else + /* Approximate. */ + cp_gtk_dpi_conversion_factor = PANGO_SCALE * 72.0 / 96.; +} + +static void +dpi_changed_cb (GtkSettings *settings, + GParamSpec *pspec __attribute__((unused))) +{ + int int_dpi; + g_object_get (settings, "gtk-xft-dpi", &int_dpi, NULL); + if (int_dpi < 0) + cp_gtk_dpi_conversion_factor = PANGO_SCALE * 72.0 / 96.; + else + cp_gtk_dpi_conversion_factor = + PANGO_SCALE * 72.0 / (int_dpi / PANGO_SCALE); +} + +static int +within_human_latency_tolerance(struct timeval *init) +{ + struct timeval curr; + unsigned long milliseconds_elapsed; + + gettimeofday(&curr, NULL); + + milliseconds_elapsed = (((curr.tv_sec * 1000) + (curr.tv_usec / 1000)) + - ((init->tv_sec * 1000) + (init->tv_usec / 1000))); + + return milliseconds_elapsed < 100; +} + +#if GTK_MINOR_VERSION > 4 +static void +glog_func (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + old_glog_func (log_domain, log_level, message, user_data); + if (log_level & (G_LOG_LEVEL_ERROR + | G_LOG_LEVEL_CRITICAL + | G_LOG_LEVEL_WARNING)) + { + JNIEnv *env = cp_gtk_gdk_env (); + jthrowable *exc = (*env)->ExceptionOccurred(env); + gchar *detail = g_strconcat (log_domain, ": ", message, NULL); + JCL_ThrowException (env, "java/lang/InternalError", detail); + g_free (detail); + (*env)->ExceptionDescribe (env); + if (exc != NULL) + (*env)->Throw (env, exc); + else + (*env)->ExceptionClear (env); + } +} +#endif + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_iterateNativeQueue +(JNIEnv *env, + jobject self __attribute__((unused)), + jobject lockedQueue, + jboolean block) +{ + /* We're holding an EventQueue lock, and we're about to acquire the GDK + * lock before dropping the EventQueue lock. This can deadlock if someone + * holds the GDK lock and wants to acquire the EventQueue lock; however + * all callbacks from GTK happen with the GDK lock released, so this + * would only happen in an odd case such as some JNI helper code + * acquiring the GDK lock and calling back into + * EventQueue.getNextEvent(). + */ + + struct timeval init; + gettimeofday(&init, NULL); + + gdk_threads_enter (); + (*env)->MonitorExit (env, lockedQueue); + + if (block) + { + + /* If we're blocking-when-empty, we want a do .. while loop. */ + do + gtk_main_iteration (); + while (within_human_latency_tolerance (&init) + && gtk_events_pending ()); + } + else + { + /* If we're not blocking-when-empty, we want a while loop. */ + while (within_human_latency_tolerance (&init) + && gtk_events_pending ()) + gtk_main_iteration (); + } + + (*env)->MonitorEnter (env, lockedQueue); + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_wakeNativeQueue + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) +{ + g_main_context_wakeup (NULL); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_nativeQueueEmpty + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) +{ + jboolean empty = FALSE; + + gdk_threads_enter (); + + empty = ! gtk_events_pending(); + + gdk_threads_leave (); + + return empty; +} + + +static jint gdk_color_to_java_color (GdkColor color); + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_beep + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) +{ + gdk_threads_enter (); + + gdk_beep (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_sync + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) +{ + gdk_threads_enter (); + + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenSizeDimensions + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jintArray jdims) +{ + jint *dims = (*env)->GetIntArrayElements (env, jdims, 0); + + gdk_threads_enter (); + + dims[0] = gdk_screen_width (); + dims[1] = gdk_screen_height (); + + gdk_threads_leave (); + + (*env)->ReleaseIntArrayElements(env, jdims, dims, 0); +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenResolution + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) +{ + jint res; + + gdk_threads_enter (); + + res = gdk_screen_width () / (gdk_screen_width_mm () / 25.4); + + gdk_threads_leave (); + + return res; +} + +#define CONVERT(type, state) \ + gdk_color_to_java_color (style->type[GTK_STATE_ ## state]) + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_loadSystemColors + (JNIEnv *env, jobject obj __attribute__((unused)), + jintArray jcolors) +{ + jint *colors; + GtkStyle *style; + + gdk_threads_enter (); + + colors = (*env)->GetIntArrayElements (env, jcolors, 0); + + style = gtk_widget_get_default_style (); + + colors[AWT_DESKTOP] = CONVERT (bg, SELECTED); + colors[AWT_ACTIVE_CAPTION] = CONVERT (bg, SELECTED); + colors[AWT_ACTIVE_CAPTION_TEXT] = CONVERT (text, SELECTED); + colors[AWT_ACTIVE_CAPTION_BORDER] = CONVERT (fg, NORMAL); + colors[AWT_INACTIVE_CAPTION] = CONVERT (base, INSENSITIVE); + colors[AWT_INACTIVE_CAPTION_TEXT] = CONVERT (fg, INSENSITIVE); + colors[AWT_INACTIVE_CAPTION_BORDER] = CONVERT (fg, INSENSITIVE); + colors[AWT_WINDOW] = CONVERT (bg, NORMAL); + colors[AWT_WINDOW_BORDER] = CONVERT (fg, NORMAL); + colors[AWT_WINDOW_TEXT] = CONVERT (fg, NORMAL); + colors[AWT_MENU] = CONVERT (bg, NORMAL); + colors[AWT_MENU_TEXT] = CONVERT (fg, NORMAL); + colors[AWT_TEXT] = CONVERT (bg, NORMAL); + colors[AWT_TEXT_TEXT] = CONVERT (fg, NORMAL); + colors[AWT_TEXT_HIGHLIGHT] = CONVERT (bg, SELECTED); + colors[AWT_TEXT_HIGHLIGHT_TEXT] = CONVERT (fg, SELECTED); + colors[AWT_TEXT_INACTIVE_TEXT] = CONVERT (bg, INSENSITIVE); + colors[AWT_CONTROL] = CONVERT (bg, NORMAL); + colors[AWT_CONTROL_TEXT] = CONVERT (fg, NORMAL); + colors[AWT_CONTROL_HIGHLIGHT] = CONVERT (base, ACTIVE); + colors[AWT_CONTROL_LT_HIGHLIGHT] = CONVERT (bg, PRELIGHT); + colors[AWT_CONTROL_SHADOW] = CONVERT (bg, ACTIVE); + colors[AWT_CONTROL_DK_SHADOW] = CONVERT (fg, INSENSITIVE); + colors[AWT_SCROLLBAR] = CONVERT (base, INSENSITIVE); + colors[AWT_INFO] = CONVERT (bg, NORMAL); + colors[AWT_INFO_TEXT] = CONVERT (fg, NORMAL); + + (*env)->ReleaseIntArrayElements(env, jcolors, colors, 0); + + gdk_threads_leave (); +} + +#undef CONVERT + +static jint +gdk_color_to_java_color (GdkColor gdk_color) +{ + guchar red; + guchar green; + guchar blue; + float factor; + + factor = 255.0 / 65535.0; + + red = (float) gdk_color.red * factor; + green = (float) gdk_color.green * factor; + blue = (float) gdk_color.blue * factor; + + return (jint) (0xff000000 | (red << 16) | (green << 8) | blue); +} diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c new file mode 100644 index 00000000000..650d9b6030e --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c @@ -0,0 +1,2181 @@ +/* gtkwindowpeer.c -- Native implementation of GtkWindowPeer + Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GtkWindowPeer.h" +#include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> +#include <X11/Xatom.h> +#include <gdk/gdkkeysyms.h> + +#define AWT_WINDOW_OPENED 200 +#define AWT_WINDOW_CLOSING 201 +#define AWT_WINDOW_CLOSED 202 +#define AWT_WINDOW_ICONIFIED 203 +#define AWT_WINDOW_DEICONIFIED 204 +#define AWT_WINDOW_ACTIVATED 205 +#define AWT_WINDOW_DEACTIVATED 206 +#define AWT_WINDOW_GAINED_FOCUS 207 +#define AWT_WINDOW_LOST_FOCUS 208 +#define AWT_WINDOW_STATE_CHANGED 209 + +/* Virtual Keys */ +/* This list should be kept in the same order as the VK_ field + declarations in KeyEvent.java. */ +#define VK_ENTER '\n' +#define VK_BACK_SPACE '\b' +#define VK_TAB '\t' +#define VK_CANCEL 3 +#define VK_CLEAR 12 +#define VK_SHIFT 16 +#define VK_CONTROL 17 +#define VK_ALT 18 +#define VK_PAUSE 19 +#define VK_CAPS_LOCK 20 +#define VK_ESCAPE 27 +#define VK_SPACE ' ' +#define VK_PAGE_UP 33 +#define VK_PAGE_DOWN 34 +#define VK_END 35 +#define VK_HOME 36 +#define VK_LEFT 37 +#define VK_UP 38 +#define VK_RIGHT 39 +#define VK_DOWN 40 +#define VK_COMMA ',' +#define VK_MINUS '-' +#define VK_PERIOD '.' +#define VK_SLASH '/' +#define VK_0 '0' +#define VK_1 '1' +#define VK_2 '2' +#define VK_3 '3' +#define VK_4 '4' +#define VK_5 '5' +#define VK_6 '6' +#define VK_7 '7' +#define VK_8 '8' +#define VK_9 '9' +#define VK_SEMICOLON ';' +#define VK_EQUALS '=' +#define VK_A 'A' +#define VK_B 'B' +#define VK_C 'C' +#define VK_D 'D' +#define VK_E 'E' +#define VK_F 'F' +#define VK_G 'G' +#define VK_H 'H' +#define VK_I 'I' +#define VK_J 'J' +#define VK_K 'K' +#define VK_L 'L' +#define VK_M 'M' +#define VK_N 'N' +#define VK_O 'O' +#define VK_P 'P' +#define VK_Q 'Q' +#define VK_R 'R' +#define VK_S 'S' +#define VK_T 'T' +#define VK_U 'U' +#define VK_V 'V' +#define VK_W 'W' +#define VK_X 'X' +#define VK_Y 'Y' +#define VK_Z 'Z' +#define VK_OPEN_BRACKET '[' +#define VK_BACK_SLASH '\\' +#define VK_CLOSE_BRACKET ']' +/* See gtkpeer.h */ +/* #define VK_NUMPAD0 96 */ +/* #define VK_NUMPAD1 97 */ +/* #define VK_NUMPAD2 98 */ +/* #define VK_NUMPAD3 99 */ +/* #define VK_NUMPAD4 100 */ +/* #define VK_NUMPAD5 101 */ +/* #define VK_NUMPAD6 102 */ +/* #define VK_NUMPAD7 103 */ +/* #define VK_NUMPAD8 104 */ +/* #define VK_NUMPAD9 105 */ +#define VK_MULTIPLY 106 +#define VK_ADD 107 +#define VK_SEPARATER 108 +#define VK_SEPARATOR 108 +#define VK_SUBTRACT 109 +/* See gtkpeer.h */ +/* #define VK_DECIMAL 110 */ +#define VK_DIVIDE 111 +#define VK_DELETE 127 +#define VK_NUM_LOCK 144 +#define VK_SCROLL_LOCK 145 +#define VK_F1 112 +#define VK_F2 113 +#define VK_F3 114 +#define VK_F4 115 +#define VK_F5 116 +#define VK_F6 117 +#define VK_F7 118 +#define VK_F8 119 +#define VK_F9 120 +#define VK_F10 121 +#define VK_F11 122 +#define VK_F12 123 +#define VK_F13 61440 +#define VK_F14 61441 +#define VK_F15 61442 +#define VK_F16 61443 +#define VK_F17 61444 +#define VK_F18 61445 +#define VK_F19 61446 +#define VK_F20 61447 +#define VK_F21 61448 +#define VK_F22 61449 +#define VK_F23 61450 +#define VK_F24 61451 +#define VK_PRINTSCREEN 154 +#define VK_INSERT 155 +#define VK_HELP 156 +#define VK_META 157 +#define VK_BACK_QUOTE 192 +#define VK_QUOTE 222 +#define VK_KP_UP 224 +#define VK_KP_DOWN 225 +#define VK_KP_LEFT 226 +#define VK_KP_RIGHT 227 +#define VK_DEAD_GRAVE 128 +#define VK_DEAD_ACUTE 129 +#define VK_DEAD_CIRCUMFLEX 130 +#define VK_DEAD_TILDE 131 +#define VK_DEAD_MACRON 132 +#define VK_DEAD_BREVE 133 +#define VK_DEAD_ABOVEDOT 134 +#define VK_DEAD_DIAERESIS 135 +#define VK_DEAD_ABOVERING 136 +#define VK_DEAD_DOUBLEACUTE 137 +#define VK_DEAD_CARON 138 +#define VK_DEAD_CEDILLA 139 +#define VK_DEAD_OGONEK 140 +#define VK_DEAD_IOTA 141 +#define VK_DEAD_VOICED_SOUND 142 +#define VK_DEAD_SEMIVOICED_SOUND 143 +#define VK_AMPERSAND 150 +#define VK_ASTERISK 151 +#define VK_QUOTEDBL 152 +#define VK_LESS 153 +#define VK_GREATER 160 +#define VK_BRACELEFT 161 +#define VK_BRACERIGHT 162 +#define VK_AT 512 +#define VK_COLON 513 +#define VK_CIRCUMFLEX 514 +#define VK_DOLLAR 515 +#define VK_EURO_SIGN 516 +#define VK_EXCLAMATION_MARK 517 +#define VK_INVERTED_EXCLAMATION_MARK 518 +#define VK_LEFT_PARENTHESIS 519 +#define VK_NUMBER_SIGN 520 +#define VK_PLUS 521 +#define VK_RIGHT_PARENTHESIS 522 +#define VK_UNDERSCORE 523 +#define VK_FINAL 24 +#define VK_CONVERT 28 +#define VK_NONCONVERT 29 +#define VK_ACCEPT 30 +#define VK_MODECHANGE 31 +#define VK_KANA 21 +#define VK_KANJI 25 +#define VK_ALPHANUMERIC 240 +#define VK_KATAKANA 241 +#define VK_HIRAGANA 242 +#define VK_FULL_WIDTH 243 +#define VK_HALF_WIDTH 244 +#define VK_ROMAN_CHARACTERS 245 +#define VK_ALL_CANDIDATES 256 +#define VK_PREVIOUS_CANDIDATE 257 +#define VK_CODE_INPUT 258 +#define VK_JAPANESE_KATAKANA 259 +#define VK_JAPANESE_HIRAGANA 260 +#define VK_JAPANESE_ROMAN 261 +#define VK_KANA_LOCK 262 +#define VK_INPUT_METHOD_ON_OFF 263 +#define VK_CUT 65489 +#define VK_COPY 65485 +#define VK_PASTE 65487 +#define VK_UNDO 65483 +#define VK_AGAIN 65481 +#define VK_FIND 65488 +#define VK_PROPS 65482 +#define VK_STOP 65480 +#define VK_COMPOSE 65312 +#define VK_ALT_GRAPH 65406 +#define VK_UNDEFINED 0 + +#define AWT_KEY_CHAR_UNDEFINED 0 + +#define AWT_FRAME_STATE_NORMAL 0 +#define AWT_FRAME_STATE_ICONIFIED 1 +#define AWT_FRAME_STATE_MAXIMIZED_HORIZ 2 +#define AWT_FRAME_STATE_MAXIMIZED_VERT 4 +#define AWT_FRAME_STATE_MAXIMIZED_BOTH 6 + +static jmethodID postKeyEventID; +static jmethodID postWindowEventID; +static jmethodID postConfigureEventID; +static jmethodID postInsetsChangedEventID; +static jmethodID windowGetWidthID; +static jmethodID windowGetHeightID; +static jmethodID setBoundsCallbackID; + +void +cp_gtk_window_init_jni (void) +{ + jclass window; + jclass gtkwindowpeer; + + window = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), "java/awt/Window"); + + setBoundsCallbackID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), window, + "setBoundsCallback", + "(IIII)V"); + + gtkwindowpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkWindowPeer"); + + postKeyEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer, + "postKeyEvent", "(IJIICI)V"); + + postWindowEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer, + "postWindowEvent", + "(ILjava/awt/Window;I)V"); + + postConfigureEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer, + "postConfigureEvent", "(IIII)V"); + + postInsetsChangedEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer, + "postInsetsChangedEvent", + "(IIII)V"); + + windowGetWidthID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer, + "getWidth", "()I"); + + windowGetHeightID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer, + "getHeight", "()I"); + + gtkwindowpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), + "gnu/java/awt/peer/gtk/GtkWindowPeer"); +} + +/* Get the first keyval in the keymap for this event's keycode. The + first keyval corresponds roughly to Java's notion of a virtual + key. Returns the uppercase version of the first keyval. */ +static guint +get_first_keyval_from_keymap (GdkEventKey *event) +{ + guint keyval; + guint *keyvals; + gint n_entries; + + if (!gdk_keymap_get_entries_for_keycode (NULL, + event->hardware_keycode, + NULL, + &keyvals, + &n_entries)) + { + g_warning ("No keyval found for hardware keycode %d\n", + event->hardware_keycode); + /* Try to recover by using the keyval in the event structure. */ + keyvals = &(event->keyval); + } + keyval = keyvals[0]; + g_free (keyvals); + + return gdk_keyval_to_upper (keyval); +} + +#ifdef __GNUC__ +__inline +#endif +static jint +keysym_to_awt_keycode (GdkEventKey *event) +{ + guint ukeyval; + guint state; + + ukeyval = get_first_keyval_from_keymap (event); + state = event->state; + + /* VK_A through VK_Z */ + if (ukeyval >= GDK_A && ukeyval <= GDK_Z) + return ukeyval; + + /* VK_0 through VK_9 */ + if (ukeyval >= GDK_0 && ukeyval <= GDK_9) + return ukeyval; + + switch (ukeyval) + { + case GDK_Return: + case GDK_KP_Enter: + return VK_ENTER; + case GDK_BackSpace: + return VK_BACK_SPACE; + case GDK_Tab: + return VK_TAB; + case GDK_Cancel: + return VK_CANCEL; + case GDK_Clear: + return VK_CLEAR; + case GDK_Shift_L: + case GDK_Shift_R: + return VK_SHIFT; + case GDK_Control_L: + case GDK_Control_R: + return VK_CONTROL; + case GDK_Alt_L: + case GDK_Alt_R: + return VK_ALT; + case GDK_Pause: + return VK_PAUSE; + case GDK_Caps_Lock: + return VK_CAPS_LOCK; + case GDK_Escape: + return VK_ESCAPE; + case GDK_space: + return VK_SPACE; + case GDK_KP_Page_Up: + /* For keys on the numeric keypad, the JVM produces one of two + virtual keys, depending on the num lock state. */ + if (state & GDK_MOD2_MASK) + return VK_NUMPAD9; + else + return VK_PAGE_UP; + case GDK_Page_Up: + return VK_PAGE_UP; + case GDK_KP_Page_Down: + if (state & GDK_MOD2_MASK) + return VK_NUMPAD3; + else + return VK_PAGE_DOWN; + case GDK_Page_Down: + return VK_PAGE_DOWN; + case GDK_KP_End: + if (state & GDK_MOD2_MASK) + return VK_NUMPAD1; + else + return VK_END; + case GDK_End: + return VK_END; + case GDK_KP_Home: + if (state & GDK_MOD2_MASK) + return VK_NUMPAD7; + else + return VK_HOME; + case GDK_Home: + return VK_HOME; + case GDK_KP_Begin: + if (state & GDK_MOD2_MASK) + return VK_NUMPAD5; + else + return VK_UNDEFINED; + case GDK_Left: + return VK_LEFT; + case GDK_Up: + return VK_UP; + case GDK_Right: + return VK_RIGHT; + case GDK_Down: + return VK_DOWN; + case GDK_comma: + return VK_COMMA; + case GDK_minus: + return VK_MINUS; + case GDK_period: + return VK_PERIOD; + case GDK_slash: + return VK_SLASH; + /* + return VK_0; + return VK_1; + return VK_2; + return VK_3; + return VK_4; + return VK_5; + return VK_6; + return VK_7; + return VK_8; + return VK_9; + */ + case GDK_semicolon: + return VK_SEMICOLON; + case GDK_equal: + return VK_EQUALS; + /* + return VK_A; + return VK_B; + return VK_C; + return VK_D; + return VK_E; + return VK_F; + return VK_G; + return VK_H; + return VK_I; + return VK_J; + return VK_K; + return VK_L; + return VK_M; + return VK_N; + return VK_O; + return VK_P; + return VK_Q; + return VK_R; + return VK_S; + return VK_T; + return VK_U; + return VK_V; + return VK_W; + return VK_X; + return VK_Y; + return VK_Z; + */ + case GDK_bracketleft: + return VK_OPEN_BRACKET; + case GDK_backslash: + return VK_BACK_SLASH; + case GDK_bracketright: + return VK_CLOSE_BRACKET; + case GDK_KP_0: + return VK_NUMPAD0; + case GDK_KP_1: + return VK_NUMPAD1; + case GDK_KP_2: + return VK_NUMPAD2; + case GDK_KP_3: + return VK_NUMPAD3; + case GDK_KP_4: + return VK_NUMPAD4; + case GDK_KP_5: + return VK_NUMPAD5; + case GDK_KP_6: + return VK_NUMPAD6; + case GDK_KP_7: + return VK_NUMPAD7; + case GDK_KP_8: + return VK_NUMPAD8; + case GDK_KP_9: + return VK_NUMPAD9; + case GDK_KP_Multiply: + return VK_MULTIPLY; + case GDK_KP_Add: + return VK_ADD; + /* + return VK_SEPARATER; + */ + case GDK_KP_Separator: + return VK_SEPARATOR; + case GDK_KP_Subtract: + return VK_SUBTRACT; + case GDK_KP_Decimal: + return VK_DECIMAL; + case GDK_KP_Divide: + return VK_DIVIDE; + case GDK_KP_Delete: + if (state & GDK_MOD2_MASK) + return VK_DECIMAL; + else + return VK_DELETE; + case GDK_Delete: + return VK_DELETE; + case GDK_Num_Lock: + return VK_NUM_LOCK; + case GDK_Scroll_Lock: + return VK_SCROLL_LOCK; + case GDK_F1: + return VK_F1; + case GDK_F2: + return VK_F2; + case GDK_F3: + return VK_F3; + case GDK_F4: + return VK_F4; + case GDK_F5: + return VK_F5; + case GDK_F6: + return VK_F6; + case GDK_F7: + return VK_F7; + case GDK_F8: + return VK_F8; + case GDK_F9: + return VK_F9; + case GDK_F10: + return VK_F10; + case GDK_F11: + return VK_F11; + case GDK_F12: + return VK_F12; + case GDK_F13: + return VK_F13; + case GDK_F14: + return VK_F14; + case GDK_F15: + return VK_F15; + case GDK_F16: + return VK_F16; + case GDK_F17: + return VK_F17; + case GDK_F18: + return VK_F18; + case GDK_F19: + return VK_F19; + case GDK_F20: + return VK_F20; + case GDK_F21: + return VK_F21; + case GDK_F22: + return VK_F22; + case GDK_F23: + return VK_F23; + case GDK_F24: + return VK_F24; + case GDK_Print: + return VK_PRINTSCREEN; + case GDK_KP_Insert: + if (state & GDK_MOD2_MASK) + return VK_NUMPAD0; + else + return VK_INSERT; + case GDK_Insert: + return VK_INSERT; + case GDK_Help: + return VK_HELP; + case GDK_Meta_L: + case GDK_Meta_R: + return VK_META; + case GDK_grave: + return VK_BACK_QUOTE; + case GDK_apostrophe: + return VK_QUOTE; + case GDK_KP_Up: + if (state & GDK_MOD2_MASK) + return VK_NUMPAD8; + else + return VK_KP_UP; + case GDK_KP_Down: + if (state & GDK_MOD2_MASK) + return VK_NUMPAD2; + else + return VK_KP_DOWN; + case GDK_KP_Left: + if (state & GDK_MOD2_MASK) + return VK_NUMPAD4; + else + return VK_KP_LEFT; + case GDK_KP_Right: + if (state & GDK_MOD2_MASK) + return VK_NUMPAD6; + else + return VK_KP_RIGHT; + case GDK_dead_grave: + return VK_DEAD_GRAVE; + case GDK_dead_acute: + return VK_DEAD_ACUTE; + case GDK_dead_circumflex: + return VK_DEAD_CIRCUMFLEX; + case GDK_dead_tilde: + return VK_DEAD_TILDE; + case GDK_dead_macron: + return VK_DEAD_MACRON; + case GDK_dead_breve: + return VK_DEAD_BREVE; + case GDK_dead_abovedot: + return VK_DEAD_ABOVEDOT; + case GDK_dead_diaeresis: + return VK_DEAD_DIAERESIS; + case GDK_dead_abovering: + return VK_DEAD_ABOVERING; + case GDK_dead_doubleacute: + return VK_DEAD_DOUBLEACUTE; + case GDK_dead_caron: + return VK_DEAD_CARON; + case GDK_dead_cedilla: + return VK_DEAD_CEDILLA; + case GDK_dead_ogonek: + return VK_DEAD_OGONEK; + case GDK_dead_iota: + return VK_DEAD_IOTA; + case GDK_dead_voiced_sound: + return VK_DEAD_VOICED_SOUND; + case GDK_dead_semivoiced_sound: + return VK_DEAD_SEMIVOICED_SOUND; + case GDK_ampersand: + return VK_AMPERSAND; + case GDK_asterisk: + return VK_ASTERISK; + case GDK_quotedbl: + return VK_QUOTEDBL; + case GDK_less: + return VK_LESS; + case GDK_greater: + return VK_GREATER; + case GDK_braceleft: + return VK_BRACELEFT; + case GDK_braceright: + return VK_BRACERIGHT; + case GDK_at: + return VK_AT; + case GDK_colon: + return VK_COLON; + case GDK_asciicircum: + return VK_CIRCUMFLEX; + case GDK_dollar: + return VK_DOLLAR; + case GDK_EuroSign: + return VK_EURO_SIGN; + case GDK_exclam: + return VK_EXCLAMATION_MARK; + case GDK_exclamdown: + return VK_INVERTED_EXCLAMATION_MARK; + case GDK_parenleft: + return VK_LEFT_PARENTHESIS; + case GDK_numbersign: + return VK_NUMBER_SIGN; + case GDK_plus: + return VK_PLUS; + case GDK_parenright: + return VK_RIGHT_PARENTHESIS; + case GDK_underscore: + return VK_UNDERSCORE; + /* + return VK_FINAL; + return VK_CONVERT; + return VK_NONCONVERT; + return VK_ACCEPT; + */ + case GDK_Mode_switch: + return VK_MODECHANGE; + /* + return VK_KANA; + */ + case GDK_Kanji: + return VK_KANJI; + /* + return VK_ALPHANUMERIC; + */ + case GDK_Katakana: + return VK_KATAKANA; + case GDK_Hiragana: + return VK_HIRAGANA; + /* + return VK_FULL_WIDTH; + return VK_HALF_WIDTH; + return VK_ROMAN_CHARACTERS; + return VK_ALL_CANDIDATES; + */ + case GDK_PreviousCandidate: + return VK_PREVIOUS_CANDIDATE; + case GDK_Codeinput: + return VK_CODE_INPUT; + /* + return VK_JAPANESE_KATAKANA; + return VK_JAPANESE_HIRAGANA; + return VK_JAPANESE_ROMAN; + */ + case GDK_Kana_Lock: + return VK_KANA_LOCK; + /* + return VK_INPUT_METHOD_ON_OFF; + return VK_CUT; + return VK_COPY; + return VK_PASTE; + return VK_UNDO; + return VK_AGAIN; + return VK_FIND; + return VK_PROPS; + return VK_STOP; + return VK_COMPOSE; + return VK_ALT_GRAPH; + */ + default: + return VK_UNDEFINED; + } +} + +static jint +keysym_to_awt_keylocation (GdkEventKey *event) +{ + guint ukeyval; + + ukeyval = get_first_keyval_from_keymap (event); + + /* VK_A through VK_Z */ + if (ukeyval >= GDK_A && ukeyval <= GDK_Z) + return AWT_KEY_LOCATION_STANDARD; + + /* VK_0 through VK_9 */ + if (ukeyval >= GDK_0 && ukeyval <= GDK_9) + return AWT_KEY_LOCATION_STANDARD; + + switch (ukeyval) + { + case GDK_Shift_L: + case GDK_Control_L: + case GDK_Alt_L: + case GDK_Meta_L: + return AWT_KEY_LOCATION_LEFT; + + case GDK_Shift_R: + case GDK_Control_R: + case GDK_Alt_R: + case GDK_Meta_R: + return AWT_KEY_LOCATION_RIGHT; + + case GDK_Return: + case GDK_BackSpace: + case GDK_Tab: + case GDK_Cancel: + case GDK_Clear: + case GDK_Pause: + case GDK_Caps_Lock: + case GDK_Escape: + case GDK_space: + case GDK_Page_Up: + case GDK_Page_Down: + case GDK_End: + case GDK_Home: + case GDK_Left: + case GDK_Up: + case GDK_Right: + case GDK_Down: + case GDK_comma: + case GDK_minus: + case GDK_period: + case GDK_slash: + case GDK_semicolon: + case GDK_equal: + case GDK_bracketleft: + case GDK_backslash: + case GDK_bracketright: + case GDK_Delete: + case GDK_Scroll_Lock: + case GDK_F1: + case GDK_F2: + case GDK_F3: + case GDK_F4: + case GDK_F5: + case GDK_F6: + case GDK_F7: + case GDK_F8: + case GDK_F9: + case GDK_F10: + case GDK_F11: + case GDK_F12: + case GDK_F13: + case GDK_F14: + case GDK_F15: + case GDK_F16: + case GDK_F17: + case GDK_F18: + case GDK_F19: + case GDK_F20: + case GDK_F21: + case GDK_F22: + case GDK_F23: + case GDK_F24: + case GDK_Print: + case GDK_Insert: + case GDK_Help: + case GDK_grave: + case GDK_apostrophe: + case GDK_dead_grave: + case GDK_dead_acute: + case GDK_dead_circumflex: + case GDK_dead_tilde: + case GDK_dead_macron: + case GDK_dead_breve: + case GDK_dead_abovedot: + case GDK_dead_diaeresis: + case GDK_dead_abovering: + case GDK_dead_doubleacute: + case GDK_dead_caron: + case GDK_dead_cedilla: + case GDK_dead_ogonek: + case GDK_dead_iota: + case GDK_dead_voiced_sound: + case GDK_dead_semivoiced_sound: + case GDK_ampersand: + case GDK_asterisk: + case GDK_quotedbl: + case GDK_less: + case GDK_greater: + case GDK_braceleft: + case GDK_braceright: + case GDK_at: + case GDK_colon: + case GDK_asciicircum: + case GDK_dollar: + case GDK_EuroSign: + case GDK_exclam: + case GDK_exclamdown: + case GDK_parenleft: + case GDK_numbersign: + case GDK_plus: + case GDK_parenright: + case GDK_underscore: + case GDK_Mode_switch: + case GDK_Kanji: + case GDK_Katakana: + case GDK_Hiragana: + case GDK_PreviousCandidate: + case GDK_Codeinput: + case GDK_Kana_Lock: + return AWT_KEY_LOCATION_STANDARD; + + case GDK_KP_Enter: + case GDK_KP_Page_Up: + case GDK_KP_Page_Down: + case GDK_KP_End: + case GDK_KP_Home: + case GDK_KP_Begin: + case GDK_KP_0: + case GDK_KP_1: + case GDK_KP_2: + case GDK_KP_3: + case GDK_KP_4: + case GDK_KP_5: + case GDK_KP_6: + case GDK_KP_7: + case GDK_KP_8: + case GDK_KP_9: + case GDK_KP_Multiply: + case GDK_KP_Add: + case GDK_KP_Separator: + case GDK_KP_Subtract: + case GDK_KP_Decimal: + case GDK_KP_Divide: + case GDK_KP_Delete: + case GDK_Num_Lock: + case GDK_KP_Insert: + case GDK_KP_Up: + case GDK_KP_Down: + case GDK_KP_Left: + case GDK_KP_Right: + return AWT_KEY_LOCATION_NUMPAD; + + default: + return AWT_KEY_LOCATION_UNKNOWN; + } +} + +static jchar +keyevent_to_awt_keychar (GdkEventKey *event) +{ + if (event->length > 0) + { + /* Translate GDK carriage return to Java linefeed. */ + if (event->string[0] == 13) + return VK_ENTER; + else + return event->string[0]; + } + else + { + switch (event->keyval) + { + case GDK_BackSpace: + return VK_BACK_SPACE; + case GDK_Tab: + return VK_TAB; + case GDK_Delete: + case GDK_KP_Delete: + return VK_DELETE; + default: + return AWT_KEY_CHAR_UNDEFINED; + } + } +} + +/* Modifier key events need special treatment. In Sun's peer + implementation, when a modifier key is pressed, the KEY_PRESSED + event has that modifier in its modifiers list. The corresponding + KEY_RELEASED event's modifier list does not contain the modifier. + For example, pressing and releasing the shift key will produce a + key press event with modifiers=Shift, and a key release event with + no modifiers. GDK's key events behave in the exact opposite way, + so this translation code is needed. */ +static jint +keyevent_state_to_awt_mods (GdkEventKey *event) +{ + jint result = 0; + guint state; + + if (event->type == GDK_KEY_PRESS) + { + state = event->state; + + if (event->keyval == GDK_Shift_L + || event->keyval == GDK_Shift_R) + result |= AWT_SHIFT_DOWN_MASK; + else + { + if (state & GDK_SHIFT_MASK) + result |= AWT_SHIFT_DOWN_MASK; + } + + if (event->keyval == GDK_Control_L + || event->keyval == GDK_Control_R) + result |= AWT_CTRL_DOWN_MASK; + else + { + if (state & GDK_CONTROL_MASK) + result |= AWT_CTRL_DOWN_MASK; + } + + if (event->keyval == GDK_Alt_L + || event->keyval == GDK_Alt_R) + result |= AWT_ALT_DOWN_MASK; + else + { + if (state & GDK_MOD1_MASK) + result |= AWT_ALT_DOWN_MASK; + } + } + else if (event->type == GDK_KEY_RELEASE) + { + state = event->state; + + if (event->keyval != GDK_Shift_L + && event->keyval != GDK_Shift_R) + { + if (state & GDK_SHIFT_MASK) + result |= AWT_SHIFT_DOWN_MASK; + } + if (event->keyval != GDK_Control_L + && event->keyval != GDK_Control_R) + { + if (state & GDK_CONTROL_MASK) + result |= AWT_CTRL_DOWN_MASK; + } + + if (event->keyval != GDK_Alt_L + && event->keyval != GDK_Alt_R) + { + if (state & GDK_MOD1_MASK) + result |= AWT_ALT_DOWN_MASK; + } + } + + return result; +} + +static gboolean window_configure_cb (GtkWidget *widget, + GdkEventConfigure *event, + jobject peer); + +/* FIXME: we're currently seeing the double-activation that occurs + with metacity and GTK. See + http://bugzilla.gnome.org/show_bug.cgi?id=140977 for details. */ + +static void window_get_frame_extents (GtkWidget *window, + int *top, int *left, + int *bottom, int *right); + +static void request_frame_extents (GtkWidget *window); + +static Bool property_notify_predicate (Display *display, + XEvent *xevent, + XPointer arg); + +static gboolean window_delete_cb (GtkWidget *widget, GdkEvent *event, + jobject peer); +static void window_destroy_cb (GtkWidget *widget, GdkEvent *event, + jobject peer); +static void window_show_cb (GtkWidget *widget, jobject peer); +static void window_active_state_change_cb (GtkWidget *widget, + GParamSpec *pspec, + jobject peer); +static void window_focus_state_change_cb (GtkWidget *widget, + GParamSpec *pspec, + jobject peer); +static gboolean window_focus_in_cb (GtkWidget * widget, + GdkEventFocus *event, + jobject peer); +static gboolean window_focus_out_cb (GtkWidget * widget, + GdkEventFocus *event, + jobject peer); +static gboolean window_window_state_cb (GtkWidget *widget, + GdkEvent *event, + jobject peer); +static jint window_get_new_state (GtkWidget *widget); +static gboolean window_property_changed_cb (GtkWidget *widget, + GdkEventProperty *event, + jobject peer); +static void realize_cb (GtkWidget *widget, jobject peer); + +static gboolean +window_configure_cb (GtkWidget *widget __attribute__((unused)), + GdkEventConfigure *event, + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postConfigureEventID, + (jint) event->x, + (jint) event->y, + (jint) event->width, + (jint) event->height); + + gdk_threads_enter (); + + return FALSE; +} + +static gboolean +key_press_cb (GtkWidget *widget __attribute__((unused)), + GdkEventKey *event, + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postKeyEventID, + (jint) AWT_KEY_PRESSED, + (jlong) event->time, + keyevent_state_to_awt_mods (event), + keysym_to_awt_keycode (event), + keyevent_to_awt_keychar (event), + keysym_to_awt_keylocation (event)); + + gdk_threads_enter (); + + /* FIXME: generation of key typed events needs to be moved + to GtkComponentPeer.postKeyEvent. If the key in a key + press event is not an "action" key + (KeyEvent.isActionKey) and is not a modifier key, then + it should generate a key typed event. */ + return TRUE; +} + + +static gboolean +key_release_cb (GtkWidget *widget __attribute__((unused)), + GdkEventKey *event, + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postKeyEventID, + (jint) AWT_KEY_RELEASED, + (jlong) event->time, + keyevent_state_to_awt_mods (event), + keysym_to_awt_keycode (event), + keyevent_to_awt_keychar (event), + keysym_to_awt_keylocation (event)); + + gdk_threads_enter (); + + return TRUE; +} + +/* Union used for type punning. */ +union extents_union +{ + guchar **gu_extents; + unsigned long **extents; +}; + +union atom_list_union +{ + guchar **gu_extents; + Atom **atom_list; +}; + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create + (JNIEnv *env, jobject obj, jint type, jboolean decorated, jobject parent) +{ + GtkWidget *window_widget; + GtkWindow *window; + void *window_parent; + GtkWidget *fixed; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + + window_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL); + window = GTK_WINDOW (window_widget); + + /* Keep this window in front of its parent, if it has one. */ + if (parent) + { + window_parent = NSA_GET_PTR (env, parent); + gtk_window_set_transient_for (window, GTK_WINDOW(window_parent)); + } + + gtk_window_set_decorated (window, decorated); + + gtk_window_set_type_hint (window, type); + + gtk_window_group_add_window (cp_gtk_global_window_group, window); + + fixed = gtk_fixed_new (); + + gtk_container_add (GTK_CONTAINER (window_widget), fixed); + + gtk_widget_show (fixed); + + NSA_SET_PTR (env, obj, window_widget); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetTitle + (JNIEnv *env, jobject obj, jstring title) +{ + const char *c_title; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + c_title = (*env)->GetStringUTFChars (env, title, NULL); + + gtk_window_set_title (GTK_WINDOW (ptr), c_title); + + (*env)->ReleaseStringUTFChars (env, title, c_title); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetResizable + (JNIEnv *env, jobject obj, jboolean resizable) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_window_set_policy (GTK_WINDOW (ptr), resizable, resizable, FALSE); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal + (JNIEnv *env, jobject obj, jboolean modal) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_window_set_modal (GTK_WINDOW (ptr), modal); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible + (JNIEnv *env, jobject obj, jboolean visible) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + if (visible) + gtk_widget_show (GTK_WIDGET (ptr)); + else + gtk_widget_hide (GTK_WIDGET (ptr)); + + XFlush (GDK_DISPLAY ()); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals + (JNIEnv *env, jobject obj) +{ + void *ptr; + jobject *gref; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); + + g_signal_connect (G_OBJECT (ptr), "delete-event", + G_CALLBACK (window_delete_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "destroy-event", + G_CALLBACK (window_destroy_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "show", + G_CALLBACK (window_show_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "notify::is-active", + G_CALLBACK (window_active_state_change_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "notify::has-toplevel-focus", + G_CALLBACK (window_focus_state_change_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "focus-in-event", + G_CALLBACK (window_focus_in_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "focus-out-event", + G_CALLBACK (window_focus_out_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "window-state-event", + G_CALLBACK (window_window_state_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "property-notify-event", + G_CALLBACK (window_property_changed_cb), *gref); + + g_signal_connect_after (G_OBJECT (ptr), "realize", + G_CALLBACK (realize_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "key-press-event", + G_CALLBACK (key_press_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "key-release-event", + G_CALLBACK (key_release_cb), *gref); + + g_signal_connect_after (G_OBJECT (ptr), "window-state-event", + G_CALLBACK (window_window_state_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "configure-event", + G_CALLBACK (window_configure_cb), *gref); + + cp_gtk_component_connect_expose_signals (ptr, gref); + cp_gtk_component_connect_mouse_signals (ptr, gref); + + /* FIXME: override focus signals here to prevent child fixed repaint? */ + + gdk_threads_leave (); +} + +/* Realize the window here so that its frame extents are known now. + That way Window.pack can operate with the accurate insets returned + by the window manager rather than the default estimates. */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_realize (JNIEnv *env, jobject obj) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gtk_widget_realize (GTK_WIDGET (ptr)); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv *env, + jobject obj) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gdk_window_lower (GTK_WIDGET (ptr)->window); + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env, + jobject obj) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + gdk_window_raise (GTK_WIDGET (ptr)->window); + gdk_flush (); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBoundsCallback + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jobject window, jint x, jint y, jint width, jint height) +{ + /* Circumvent package-private access to call Window's + setBoundsCallback method. */ + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), window, setBoundsCallbackID, + x, y, width, height); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize + (JNIEnv *env, jobject obj, jint width, jint height) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + /* Avoid GTK runtime assertion failures. */ + width = (width < 1) ? 1 : width; + height = (height < 1) ? 1 : height; + + gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds + (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) +{ + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_PTR (env, obj); + + /* Avoid GTK runtime assertion failures. */ + width = (width < 1) ? 1 : width; + height = (height < 1) ? 1 : height; + + gtk_window_move (GTK_WINDOW(ptr), x, y); + /* The call to gdk_window_move is needed in addition to the call to + gtk_window_move. If gdk_window_move isn't called, then the + following set of operations doesn't give the expected results: + + 1. show a window + 2. manually move it to another position on the screen + 3. hide the window + 4. reposition the window with Component.setLocation + 5. show the window + + Instead of being at the position set by setLocation, the window + is reshown at the position to which it was moved manually. */ + if (GTK_WIDGET (ptr)->window != NULL) + gdk_window_move (GTK_WIDGET (ptr)->window, x, y); + + /* Need to change the widget's request size. */ + gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height); + /* Also need to call gtk_window_resize. If the resize is requested + by the program and the window's "resizable" property is true then + the size request will not be honoured. */ + gtk_window_resize (GTK_WINDOW (ptr), width, height); + + gdk_threads_leave (); +} + +static void +window_get_frame_extents (GtkWidget *window, + int *top, int *left, int *bottom, int *right) +{ + unsigned long *extents = NULL; + union extents_union gu_ex; + + /* Guess frame extents in case _NET_FRAME_EXTENTS is not + supported. */ + *top = 23; + *left = 6; + *bottom = 6; + *right = 6; + + /* Request that the window manager set window's + _NET_FRAME_EXTENTS property. */ + request_frame_extents (window); + + /* Attempt to retrieve window's frame extents. */ + gu_ex.extents = &extents; + if (gdk_property_get (window->window, + gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE), + gdk_atom_intern ("CARDINAL", FALSE), + 0, + sizeof (unsigned long) * 4, + FALSE, + NULL, + NULL, + NULL, + gu_ex.gu_extents)) + { + *left = extents [0]; + *right = extents [1]; + *top = extents [2]; + *bottom = extents [3]; + } +} + +static Atom extents_atom = 0; + +/* Requests that the window manager set window's + _NET_FRAME_EXTENTS property. */ +static void +request_frame_extents (GtkWidget *window) +{ + const char *request_str = "_NET_REQUEST_FRAME_EXTENTS"; + GdkAtom request_extents = gdk_atom_intern (request_str, FALSE); + + /* Check if the current window manager supports + _NET_REQUEST_FRAME_EXTENTS. */ + if (gdk_net_wm_supports (request_extents)) + { + GdkDisplay *display = gtk_widget_get_display (window); + Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); + + GdkWindow *root_window = gdk_get_default_root_window (); + Window xroot_window = GDK_WINDOW_XID (root_window); + + Atom extents_request_atom = + gdk_x11_get_xatom_by_name_for_display (display, request_str); + + XEvent xevent; + XEvent notify_xevent; + + unsigned long window_id = GDK_WINDOW_XID (GDK_DRAWABLE(window->window)); + + if (!extents_atom) + { + const char *extents_str = "_NET_FRAME_EXTENTS"; + extents_atom = + gdk_x11_get_xatom_by_name_for_display (display, extents_str); + } + + xevent.xclient.type = ClientMessage; + xevent.xclient.message_type = extents_request_atom; + xevent.xclient.display = xdisplay; + xevent.xclient.window = window_id; + xevent.xclient.format = 32; + xevent.xclient.data.l[0] = 0; + xevent.xclient.data.l[1] = 0; + xevent.xclient.data.l[2] = 0; + xevent.xclient.data.l[3] = 0; + xevent.xclient.data.l[4] = 0; + + XSendEvent (xdisplay, xroot_window, False, + (SubstructureRedirectMask | SubstructureNotifyMask), + &xevent); + + XIfEvent(xdisplay, ¬ify_xevent, + property_notify_predicate, (XPointer) &window_id); + } +} + +static Bool +property_notify_predicate (Display *xdisplay __attribute__((unused)), + XEvent *event, + XPointer window_id) +{ + unsigned long *window = (unsigned long *) window_id; + + if (event->xany.type == PropertyNotify + && event->xany.window == *window + && event->xproperty.atom == extents_atom) + return True; + else + return False; +} + +static gboolean +window_delete_cb (GtkWidget *widget __attribute__((unused)), + GdkEvent *event __attribute__((unused)), + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_CLOSING, + (jobject) NULL, (jint) 0); + + gdk_threads_enter (); + + /* Prevents that the Window dissappears ("destroy" + not being signalled). This is necessary because it + should be up to a WindowListener implementation + how the AWT Frame responds to close requests. */ + return TRUE; +} + +static void +window_destroy_cb (GtkWidget *widget __attribute__((unused)), + GdkEvent *event __attribute__((unused)), + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_CLOSED, + (jobject) NULL, (jint) 0); + + gdk_threads_enter (); +} + +static void +window_show_cb (GtkWidget *widget __attribute__((unused)), + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_OPENED, + (jobject) NULL, (jint) 0); + + gdk_threads_enter (); +} + +static void +window_active_state_change_cb (GtkWidget *widget __attribute__((unused)), + GParamSpec *pspec __attribute__((unused)), + jobject peer __attribute__((unused))) +{ + /* FIXME: not sure if this is needed or not. */ + /* Remove the unused attributes if you fix the below. */ +#if 0 + gdk_threads_leave (); + + if (GTK_WINDOW (widget)->is_active) + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_GAINED_FOCUS, + (jobject) NULL, (jint) 0); + else + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_DEACTIVATED, + (jobject) NULL, (jint) 0); + + gdk_threads_enter (); +#endif +} + +static void +window_focus_state_change_cb (GtkWidget *widget, + GParamSpec *pspec __attribute__((unused)), + jobject peer) +{ + gdk_threads_leave (); + + if (GTK_WINDOW (widget)->has_toplevel_focus) + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_ACTIVATED, + (jobject) NULL, (jint) 0); + else + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_DEACTIVATED, + (jobject) NULL, (jint) 0); + + gdk_threads_enter (); +} + +static gboolean +window_focus_in_cb (GtkWidget * widget __attribute__((unused)), + GdkEventFocus *event __attribute__((unused)), + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_GAINED_FOCUS, + (jobject) NULL, (jint) 0); + + gdk_threads_enter (); + + return FALSE; +} + +static gboolean +window_focus_out_cb (GtkWidget * widget __attribute__((unused)), + GdkEventFocus *event __attribute__((unused)), + jobject peer) +{ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_LOST_FOCUS, + (jobject) NULL, (jint) 0); + + gdk_threads_enter (); + + return FALSE; +} + +static gboolean +window_window_state_cb (GtkWidget *widget, + GdkEvent *event, + jobject peer) +{ + jint new_state; + + /* Handle WINDOW_ICONIFIED and WINDOW_DEICONIFIED events. */ + if (event->window_state.changed_mask & GDK_WINDOW_STATE_ICONIFIED) + { + /* We've either been iconified or deiconified. */ + if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED) + { + /* We've been iconified. */ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_ICONIFIED, + (jobject) NULL, (jint) 0); + + gdk_threads_enter (); + } + else + { + /* We've been deiconified. */ + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_DEICONIFIED, + (jobject) NULL, (jint) 0); + + gdk_threads_enter (); + } + } + + /* Post a WINDOW_STATE_CHANGED event, passing the new frame state to + GtkWindowPeer. */ + new_state = AWT_FRAME_STATE_NORMAL; + + if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED) + new_state |= AWT_FRAME_STATE_ICONIFIED; + + new_state |= window_get_new_state (widget); + + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_STATE_CHANGED, + (jobject) NULL, new_state); + + gdk_threads_enter (); + + return TRUE; +} + +static jint +window_get_new_state (GtkWidget *widget) +{ + GdkDisplay *display = gtk_widget_get_display(widget); + jint new_state = AWT_FRAME_STATE_NORMAL; + Atom type; + gint format; + gulong atom_count; + gulong bytes_after; + Atom *atom_list = NULL; + union atom_list_union alu; + gulong i; + + alu.atom_list = &atom_list; + XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XID (widget->window), + gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"), + 0, G_MAXLONG, False, XA_ATOM, &type, &format, &atom_count, + &bytes_after, alu.gu_extents); + + if (type != None) + { + Atom maxvert = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT"); + Atom maxhorz = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ"); + + i = 0; + while (i < atom_count) + { + if (atom_list[i] == maxhorz) + new_state |= AWT_FRAME_STATE_MAXIMIZED_HORIZ; + else if (atom_list[i] == maxvert) + new_state |= AWT_FRAME_STATE_MAXIMIZED_VERT; + + ++i; + } + + XFree (atom_list); + } + return new_state; +} + +static gboolean +window_property_changed_cb (GtkWidget *widget __attribute__((unused)), + GdkEventProperty *event, + jobject peer) +{ + unsigned long *extents; + union extents_union gu_ex; + + gu_ex.extents = &extents; + if (gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE) == event->atom + && gdk_property_get (event->window, + gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE), + gdk_atom_intern ("CARDINAL", FALSE), + 0, + sizeof (unsigned long) * 4, + FALSE, + NULL, + NULL, + NULL, + gu_ex.gu_extents)) + { + gdk_threads_leave (); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postInsetsChangedEventID, + (jint) extents[2], /* top */ + (jint) extents[0], /* left */ + (jint) extents[3], /* bottom */ + (jint) extents[1]); /* right */ + + gdk_threads_enter (); + } + + + return FALSE; +} + +static void +realize_cb (GtkWidget *widget, jobject peer) +{ + jint top = 0; + jint left = 0; + jint bottom = 0; + jint right = 0; + jint width = 0; + jint height = 0; + + width = (*cp_gtk_gdk_env())->CallIntMethod (cp_gtk_gdk_env(), peer, windowGetWidthID); + height = (*cp_gtk_gdk_env())->CallIntMethod (cp_gtk_gdk_env(), peer, windowGetHeightID); + + window_get_frame_extents (widget, &top, &left, &bottom, &right); + + (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, + postInsetsChangedEventID, + top, left, bottom, right); + + gtk_window_set_default_size (GTK_WINDOW (widget), + MAX (1, width - left - right), + MAX (1, height - top - bottom)); + + /* set the size like we do in nativeSetBounds */ + gtk_widget_set_size_request (widget, + MAX (1, width - left - right), + MAX (1, height - top - bottom)); + + gtk_window_resize (GTK_WINDOW (widget), + MAX (1, width - left - right), + MAX (1, height - top - bottom)); +} + +/* + * This method returns a GDK keyval that corresponds to one of the + * keysyms in the X keymap table. The return value is only used to + * determine the keyval's corresponding hardware keycode, and doesn't + * reflect an accurate translation of a Java virtual key value to a + * GDK keyval. + */ +#ifdef __GNUC__ +__inline +#endif +guint +cp_gtk_awt_keycode_to_keysym (jint keyCode, jint keyLocation) +{ + /* GDK_A through GDK_Z */ + if (keyCode >= VK_A && keyCode <= VK_Z) + return gdk_keyval_to_lower (keyCode); + + /* GDK_0 through GDK_9 */ + if (keyCode >= VK_0 && keyCode <= VK_9) + return keyCode; + + switch (keyCode) + { + case VK_ENTER: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Enter : GDK_Return; + case VK_BACK_SPACE: + return GDK_BackSpace; + case VK_TAB: + return GDK_Tab; + case VK_CANCEL: + return GDK_Cancel; + case VK_CLEAR: + return GDK_Clear; + case VK_SHIFT: + return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Shift_L : GDK_Shift_R; + case VK_CONTROL: + return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Control_L : GDK_Control_R; + case VK_ALT: + return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Alt_L : GDK_Alt_R; + case VK_PAUSE: + return GDK_Pause; + case VK_CAPS_LOCK: + return GDK_Caps_Lock; + case VK_ESCAPE: + return GDK_Escape; + case VK_SPACE: + return GDK_space; + case VK_PAGE_UP: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Up : GDK_Page_Up; + case VK_PAGE_DOWN: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Down : GDK_Page_Down; + case VK_END: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_End : GDK_End; + case VK_HOME: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Home : GDK_Home; + case VK_LEFT: + return GDK_Left; + case VK_UP: + return GDK_Up; + case VK_RIGHT: + return GDK_Right; + case VK_DOWN: + return GDK_Down; + case VK_COMMA: + return GDK_comma; + case VK_MINUS: + return GDK_minus; + case VK_PERIOD: + return GDK_period; + case VK_SLASH: + return GDK_slash; + /* + case VK_0: + case VK_1: + case VK_2: + case VK_3: + case VK_4: + case VK_5: + case VK_6: + case VK_7: + case VK_8: + case VK_9: + */ + case VK_SEMICOLON: + return GDK_semicolon; + case VK_EQUALS: + return GDK_equal; + /* + case VK_A: + case VK_B: + case VK_C: + case VK_D: + case VK_E: + case VK_F: + case VK_G: + case VK_H: + case VK_I: + case VK_J: + case VK_K: + case VK_L: + case VK_M: + case VK_N: + case VK_O: + case VK_P: + case VK_Q: + case VK_R: + case VK_S: + case VK_T: + case VK_U: + case VK_V: + case VK_W: + case VK_X: + case VK_Y: + case VK_Z: + */ + case VK_OPEN_BRACKET: + return GDK_bracketleft; + case VK_BACK_SLASH: + return GDK_backslash; + case VK_CLOSE_BRACKET: + return GDK_bracketright; + case VK_NUMPAD0: + return GDK_KP_0; + case VK_NUMPAD1: + return GDK_KP_1; + case VK_NUMPAD2: + return GDK_KP_2; + case VK_NUMPAD3: + return GDK_KP_3; + case VK_NUMPAD4: + return GDK_KP_4; + case VK_NUMPAD5: + return GDK_KP_5; + case VK_NUMPAD6: + return GDK_KP_6; + case VK_NUMPAD7: + return GDK_KP_7; + case VK_NUMPAD8: + return GDK_KP_8; + case VK_NUMPAD9: + return GDK_KP_9; + case VK_MULTIPLY: + return GDK_KP_Multiply; + case VK_ADD: + return GDK_KP_Add; + /* + case VK_SEPARATER: + */ + case VK_SEPARATOR: + return GDK_KP_Separator; + case VK_SUBTRACT: + return GDK_KP_Subtract; + case VK_DECIMAL: + return GDK_KP_Decimal; + case VK_DIVIDE: + return GDK_KP_Divide; + case VK_DELETE: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Delete : GDK_Delete; + case VK_NUM_LOCK: + return GDK_Num_Lock; + case VK_SCROLL_LOCK: + return GDK_Scroll_Lock; + case VK_F1: + return GDK_F1; + case VK_F2: + return GDK_F2; + case VK_F3: + return GDK_F3; + case VK_F4: + return GDK_F4; + case VK_F5: + return GDK_F5; + case VK_F6: + return GDK_F6; + case VK_F7: + return GDK_F7; + case VK_F8: + return GDK_F8; + case VK_F9: + return GDK_F9; + case VK_F10: + return GDK_F10; + case VK_F11: + return GDK_F11; + case VK_F12: + return GDK_F12; + case VK_F13: + return GDK_F13; + case VK_F14: + return GDK_F14; + case VK_F15: + return GDK_F15; + case VK_F16: + return GDK_F16; + case VK_F17: + return GDK_F17; + case VK_F18: + return GDK_F18; + case VK_F19: + return GDK_F19; + case VK_F20: + return GDK_F20; + case VK_F21: + return GDK_F21; + case VK_F22: + return GDK_F22; + case VK_F23: + return GDK_F23; + case VK_F24: + return GDK_F24; + case VK_PRINTSCREEN: + return GDK_Print; + case VK_INSERT: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Insert : GDK_Insert; + case VK_HELP: + return GDK_Help; + case VK_META: + return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Meta_L : GDK_Meta_R; + case VK_BACK_QUOTE: + return GDK_grave; + case VK_QUOTE: + return GDK_apostrophe; + case VK_KP_UP: + return GDK_KP_Up; + case VK_KP_DOWN: + return GDK_KP_Down; + case VK_KP_LEFT: + return GDK_KP_Left; + case VK_KP_RIGHT: + return GDK_KP_Right; + case VK_DEAD_GRAVE: + return GDK_dead_grave; + case VK_DEAD_ACUTE: + return GDK_dead_acute; + case VK_DEAD_CIRCUMFLEX: + return GDK_dead_circumflex; + case VK_DEAD_TILDE: + return GDK_dead_tilde; + case VK_DEAD_MACRON: + return GDK_dead_macron; + case VK_DEAD_BREVE: + return GDK_dead_breve; + case VK_DEAD_ABOVEDOT: + return GDK_dead_abovedot; + case VK_DEAD_DIAERESIS: + return GDK_dead_diaeresis; + case VK_DEAD_ABOVERING: + return GDK_dead_abovering; + case VK_DEAD_DOUBLEACUTE: + return GDK_dead_doubleacute; + case VK_DEAD_CARON: + return GDK_dead_caron; + case VK_DEAD_CEDILLA: + return GDK_dead_cedilla; + case VK_DEAD_OGONEK: + return GDK_dead_ogonek; + case VK_DEAD_IOTA: + return GDK_dead_iota; + case VK_DEAD_VOICED_SOUND: + return GDK_dead_voiced_sound; + case VK_DEAD_SEMIVOICED_SOUND: + return GDK_dead_semivoiced_sound; + case VK_AMPERSAND: + return GDK_ampersand; + case VK_ASTERISK: + return GDK_asterisk; + case VK_QUOTEDBL: + return GDK_quotedbl; + case VK_LESS: + return GDK_less; + case VK_GREATER: + return GDK_greater; + case VK_BRACELEFT: + return GDK_braceleft; + case VK_BRACERIGHT: + return GDK_braceright; + case VK_AT: + return GDK_at; + case VK_COLON: + return GDK_colon; + case VK_CIRCUMFLEX: + return GDK_asciicircum; + case VK_DOLLAR: + return GDK_dollar; + case VK_EURO_SIGN: + return GDK_EuroSign; + case VK_EXCLAMATION_MARK: + return GDK_exclam; + case VK_INVERTED_EXCLAMATION_MARK: + return GDK_exclamdown; + case VK_LEFT_PARENTHESIS: + return GDK_parenleft; + case VK_NUMBER_SIGN: + return GDK_numbersign; + case VK_PLUS: + return GDK_plus; + case VK_RIGHT_PARENTHESIS: + return GDK_parenright; + case VK_UNDERSCORE: + return GDK_underscore; + /* + case VK_FINAL: + case VK_CONVERT: + case VK_NONCONVERT: + case VK_ACCEPT: + */ + case VK_MODECHANGE: + return GDK_Mode_switch; + /* + case VK_KANA: + */ + case VK_KANJI: + return GDK_Kanji; + /* + case VK_ALPHANUMERIC: + */ + case VK_KATAKANA: + return GDK_Katakana; + case VK_HIRAGANA: + return GDK_Hiragana; + /* + case VK_FULL_WIDTH: + case VK_HALF_WIDTH: + case VK_ROMAN_CHARACTERS: + case VK_ALL_CANDIDATES: + */ + case VK_PREVIOUS_CANDIDATE: + return GDK_PreviousCandidate; + case VK_CODE_INPUT: + return GDK_Codeinput; + /* + case VK_JAPANESE_KATAKANA: + case VK_JAPANESE_HIRAGANA: + case VK_JAPANESE_ROMAN: + */ + case VK_KANA_LOCK: + return GDK_Kana_Lock; + /* + case VK_INPUT_METHOD_ON_OFF: + case VK_CUT: + case VK_COPY: + case VK_PASTE: + case VK_UNDO: + case VK_AGAIN: + case VK_FIND: + case VK_PROPS: + case VK_STOP: + case VK_COMPOSE: + case VK_ALT_GRAPH: + */ + default: + return GDK_VoidSymbol; + } +} diff --git a/libjava/classpath/native/jni/gtk-peer/gthread-jni.c b/libjava/classpath/native/jni/gtk-peer/gthread-jni.c new file mode 100644 index 00000000000..e673de07d27 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gthread-jni.c @@ -0,0 +1,2592 @@ +/* gthread-jni.c -- JNI threading routines for GLIB + Copyright (C) 1998, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/************************************************************************/ +/* Header */ +/************************************************************************/ + +/* + * @author Julian Dolby (dolby@us.ibm.com) + * @date February 7, 2003 implemented for GLIB v.1 + * + * + * @author Steven Augart + * <steve+classpath at augart dot com>, <augart at watson dot ibm dot com> + * @date April 30, 2004 -- May 10 2004: Support new functions for Glib v.2, + * fix cond_wait to free and re-acquire the mutex, + * replaced trylock stub implementation with a full one. + * + * This code implements the GThreadFunctions interface for GLIB using + * Java threading primitives. All of the locking and conditional variable + * functionality required by GThreadFunctions is implemented using the + * monitor and wait/notify functionality of Java objects. The thread- + * local functionality uses the java.lang.ThreadLocal class. + * + * Classpath's AWT support uses GTK+ peers. GTK+ uses GLIB. GLIB by default + * uses the platform's native threading model -- pthreads in most cases. If + * the Java runtime doesn't use the native threading model, then it needs this + * code in order to use Classpath's (GTK+-based) AWT routines. + * + * This code should be portable; I believe it makes no assumptions + * about the underlying VM beyond that it implements the JNI functionality + * that this code uses. + * + * Currently, use of this code is governed by the configuration option + * --enable-portable-native-sync. We will soon add a VM hook so the VM can + * select which threading model it wants to use at run time; at that point, + * the configuration option will go away. + * + * The code in this file uses only JNI 1.1, except for one JNI 1.2 function: + * GetEnv, in the JNI Invocation API. (There seems to be no way around using + * GetEnv). + * + * ACKNOWLEDGEMENT: + * + * I would like to thank Mark Wielaard for his kindness in spending at least + * six hours of his own time in reviewing this code and correcting my GNU + * coding and commenting style. --Steve Augart + * + * + * NOTES: + * + * This code has been tested with Jikes RVM and with Kaffe. + * + * This code should have proper automated unit tests. I manually tested it + * by running an application that uses AWT. --Steven Augart + * + * MINOR NIT: + * + * - Using a jboolean in the arglist to "throw()" and "rethrow()" + * triggers many warnings from GCC's -Wconversion operation, because that + * is not the same as the conversion (upcast to an int) that would occur in + * the absence of a prototype. + * + * It would be very slightly more efficient to just pass the jboolean, but + * is not worth the clutter of messages. The right solution would be to + * turn off the -Wconversion warning for just this file, *except* that + * -Wconversion also warns you against constructs such as: + * unsigned u = -1; + * and that is a useful warning. So I went from a "jboolean" to a + * "gboolean" (-Wconversion is not enabled by default for GNU Classpath, + * but it is in my own CFLAGS, which, for gcc 3.3.3, read: -pipe -ggdb3 -W + * -Wall -Wbad-function-cast -Wcast-align -Wpointer-arith -Wcast-qual + * -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations + * -fkeep-static-consts -fkeep-inline-functions -Wundef -Wwrite-strings + * -Wno-aggregate-return -Wmissing-noreturn -Wnested-externs -Wtrigraphs + * -Wconversion -Wsign-compare -Wno-float-equal -Wmissing-format-attribute + * -Wno-unreachable-code -Wdisabled-optimization ) + */ + +#include <config.h> + +/************************************************************************/ +/* Configuration */ +/************************************************************************/ + +/** Tracing and Reporting **/ +#define TRACE_API_CALLS 0 /* announce entry and exit into each method, + by printing to stderr. */ + +#define TRACE_MONITORS 0 /* Every enterMonitor() and exitMonitor() goes + to stderr. */ + +/** Trouble handling. There is a discussion below of this. **/ +#define EXPLAIN_TROUBLE 1 /* Describe any unexpected trouble that + happens. This is a superset + of EXPLAIN_BROKEN, and if set trumps an + unset EXPLAIN_BROKEN. It is not a strict + superset, since at the moment there is no + TROUBLE that is not also BROKEN. + + Use criticalMsg() to describe the problem. + */ + +#define EXPLAIN_BROKEN 1 /* Describe trouble that is serious enough to + be BROKEN. (Right now all trouble is at + least BROKEN.) */ + +/* There is no EXPLAIN_BADLY_BROKEN definition. We always explain + BADLY_BROKEN trouble, since there is no other way to report it. */ + + +/** Error Handling **/ +#define DIE_IF_BROKEN 1 /* Dies if serious trouble happens. There is + really no non-serious trouble, except + possibly problems that arise during + pthread_create, which are reported by a + GError. + + If you do not set DIE_IF_BROKEN, then + trouble will raise a Java RuntimeException. + We probably do want to die right away, + since anything that's BROKEN really + indicates a programming error or a + system-wide error, and that's what the glib + documentation says you should do in case of + that kind of error in a glib-style + function. But it does work to turn this + off. */ + +#if DIE_IF_BROKEN +#define DIE_IF_BADLY_BROKEN 1 /* DIE_IF_BROKEN implies DIE_IF_BADLY_BROKEN */ +#else +#define DIE_IF_BADLY_BROKEN 1 /* Die if the system is badly broken -- + that is, if we have further trouble while + attempting to throw an exception + upwards, or if we are unable to generate + one of the classes we'll need in order to + throw wrapped exceptions upward. + + If unset, we will print a warning message, + and limp along anyway. Not that the system + is likely to work. */ +#endif + +/** Performance tuning parameters **/ + +#define ENABLE_EXPENSIVE_ASSERTIONS 0 /* Enable expensive assertions? */ + +#define DELETE_LOCAL_REFS 1 /* Whether to delete local references. + + JNI only guarantees that there wil be 16 + available. (Jikes RVM provides an number + only limited by VM memory.) + + Jikes RVM will probably perform faster if + this is turned off, but other VMs may need + this to be turned on in order to perform at + all, or might need it if things change. + + Remember, we don't know how many of those + local refs might have already been used up + by higher layers of JNI code that end up + calling g_thread_self(), + g_thread_set_private(), and so on. + + We set this to 1 for GNU Classpath, since + one of our principles is "always go for the + most robust implementation" */ + +#define HAVE_JNI_VERSION_1_2 0 /* Assume we don't. We could + dynamically check for this. We will + assume JNI 1.2 in later versions of + Classpath. + + As it stands, the code in this file + already needs one JNI 1.2 function: + GetEnv, in the JNI Invocation API. + + TODO This code hasn't been tested yet. + And really hasn't been implemented yet. + */ + +/************************************************************************/ +/* Global data */ +/************************************************************************/ + +#if defined HAVE_STDINT_H +#include <stdint.h> /* provides intptr_t */ +#elif defined HAVE_INTTYPES_H +#include <inttypes.h> +#endif +#include <stdarg.h> /* va_list */ +#include <glib.h> +#include "gthread-jni.h" +#include <assert.h> /* assert() */ + +/* For Java thread priority constants. */ +#include <gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h> + +/* Since not all JNI header generators actually define constants we + define them here explicitly. */ +#ifndef gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MIN_PRIORITY +#define gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MIN_PRIORITY 1 +#endif +#ifndef gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_NORM_PRIORITY +#define gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_NORM_PRIORITY 5 +#endif +#ifndef gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MAX_PRIORITY +#define gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MAX_PRIORITY 10 +#endif + +/* The VM handle. This is set in + Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit */ +JavaVM *cp_gtk_the_vm; + +/* Unions used for type punning. */ +union env_union +{ + void **void_env; + JNIEnv **jni_env; +}; + +union func_union +{ + void *void_func; + GThreadFunc g_func; +}; + +/* Forward Declarations for Functions */ +static int threadObj_set_priority (JNIEnv * env, jobject threadObj, + GThreadPriority gpriority); +static void fatalMsg (const char fmt[], ...) + __attribute__ ((format (printf, 1, 2))) + __attribute__ ((noreturn)); + +static void criticalMsg (const char fmt[], ...) + __attribute__ ((format (printf, 1, 2))); + +static void tracing (const char fmt[], ...) + __attribute__ ((format (printf, 1, 2))); + +static jint javaPriorityLevel (GThreadPriority priority) + __attribute__ ((const)); + +/************************************************************************/ +/* Trouble-handling, including utilities to reflect exceptions */ +/* back to the VM. Also some status reporting. */ +/************************************************************************/ + +/* How are we going to handle problems? + + There are several approaches: + + 1) Report them with the GError mechanism. + + (*thread_create)() is the only one of these functions that takes a + GError pointer. And the only G_THREAD error defined maps onto EAGAIN. + We don't have any errors in our (*thread_create)() implementation that + can be mapped to EAGAIN. So this idea is a non-starter. + + 2) Reflect the exception back to the VM, wrapped in a RuntimeException. + This will fail sometimes, if we're so broken (BADLY_BROKEN) that we + fail to throw the exception. + + 3) Abort execution. This is what the glib functions themselves do for + errors that they can't report via GError. + + Enable DIE_IF_BROKEN and/or DIE_IF_BADLY_BROKEN to + make this the default for BROKEN and/or BADLY_BROKEN trouble. + + 4) Display messages to stderr. We always do this for BADLY_BROKEN + trouble. The glib functions do that for errors they can't report via + GError. + + There are some complications. + + When I attempted to report a problem in g_thread_self() using g_critical (a + macro around g_log(), I found that g_log in turn looks for thread-private + data and calls g_thread_self() again. + + We got a segfault, probably due to stack overflow. So, this code doesn't + use the g_critical() and g_error() functions any more. Nor do we use + g_assert(); we use the C library's assert() instead. +*/ + + +#define WHERE __FILE__ ":" G_STRINGIFY(__LINE__) ": " + +/* This is portable to older compilers that lack variable-argument macros. + This used to be just g_critical(), but then we ran into the error reporting + problem discussed above. +*/ +static void +fatalMsg (const char fmt[], ...) +{ + va_list ap; + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + fputs ("\nAborting execution\n", stderr); + abort (); +} + + +static void +criticalMsg (const char fmt[], ...) +{ + va_list ap; + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + putc ('\n', stderr); +} + +/* Unlike the other two, this one does not append a newline. This is only + used if one of the TRACE_ macros is defined. */ +static void +tracing (const char fmt[], ...) +{ + va_list ap; + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); +} + +#define assert_not_reached() \ + do \ + { \ + fputs(WHERE "You should never get here. Aborting execution.\n", \ + stderr); \ + abort(); \ + } \ + while(0) + + +#if DIE_IF_BADLY_BROKEN +#define BADLY_BROKEN fatalMsg +#else +#define BADLY_BROKEN criticalMsg +/* So, the user may still attempt to recover, even though we do not advise + this. */ +#endif + +/* I find it so depressing to have to use C without varargs macros. */ +#define BADLY_BROKEN_MSG WHERE "Something fundamental" \ + " to GNU Classpath's AWT JNI broke while we were trying to pass up a Java error message" + +#define BADLY_BROKEN0() \ + BADLY_BROKEN(BADLY_BROKEN_MSG); +#define BADLY_BROKEN1(msg) \ + BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg) +#define BADLY_BROKEN2(msg, arg) \ + BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg, arg) +#define BADLY_BROKEN3(msg, arg, arg2) \ + BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg, arg1, arg2) +#define BADLY_BROKEN4(msg, arg, arg2, arg3) \ + BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg, arg1, arg2, arg3) + +#define DELETE_LOCAL_REF(env, ref) \ + do \ + { \ + if ( DELETE_LOCAL_REFS ) \ + { \ + (*env)->DeleteLocalRef (env, ref); \ + (ref) = NULL; \ + } \ + } \ + while(0) + +/* Cached info for Exception-wrapping */ + +static jclass runtimeException_class; /* java.lang.RuntimeException */ +static jmethodID runtimeException_ctor; /* constructor for it */ + + +/* Throw a new RuntimeException. It may wrap around an existing exception. + 1 if we did rethrow, -1 if we had trouble while rethrowing. + isBroken is always true in this case. */ +static int +throw (JNIEnv * env, jthrowable cause, const char *message, + gboolean isBroken, const char *file, int line) +{ + jstring jmessage; + gboolean describedException = FALSE; /* Did we already describe the + exception to stderr or the + equivalent? */ + jthrowable wrapper; + + /* allocate local message in Java */ + const char fmt[] = "In AWT JNI, %s (at %s:%d)"; + size_t len = strlen (message) + strlen (file) + sizeof fmt + 25; + char *buf; + + if (EXPLAIN_TROUBLE || (isBroken && EXPLAIN_BROKEN)) + { + criticalMsg ("%s:%d: AWT JNI failure%s: %s\n", file, line, + isBroken ? " (BROKEN)" : "", message); + if (cause) + { + jthrowable currentException = (*env)->ExceptionOccurred (env); + + if (cause == currentException) + { + criticalMsg ("Description follows to System.err:"); + (*env)->ExceptionDescribe (env); + /* ExceptionDescribe has the side-effect of clearing the pending + exception; relaunch it. */ + describedException = TRUE; + + if ((*env)->Throw (env, cause)) + { + BADLY_BROKEN1 + ("Relaunching an exception with Throw failed."); + return -1; + } + } + else + { + DELETE_LOCAL_REF (env, currentException); + criticalMsg (WHERE + "currentException != cause; something else happened" + " while handling an exception."); + } + } + } /* if (EXPLAIN_TROUBLE) */ + + if (isBroken && DIE_IF_BROKEN) + fatalMsg ("%s:%d: Aborting execution; BROKEN: %s\n", file, line, message); + + if ((buf = malloc (len))) + { + memset (buf, 0, len); + g_snprintf (buf, len, fmt, message, file, line); + jmessage = (*env)->NewStringUTF (env, buf); + free (buf); + } + else + { + jmessage = NULL; + } + + /* Create the RuntimeException wrapper object and throw it. It is OK for + CAUSE to be NULL. */ + wrapper = (jthrowable) (*env)->NewObject + (env, runtimeException_class, runtimeException_ctor, jmessage, cause); + DELETE_LOCAL_REF (env, jmessage); + + if (!wrapper) + { + /* I think this should only happen: + - if there are bugs in my JNI code, or + - if the VM is broken, or + - if we run out of memory. + */ + if (EXPLAIN_TROUBLE) + { + criticalMsg (WHERE "GNU Classpath: JNI NewObject() could not create" + " a new java.lang.RuntimeException."); + criticalMsg ("We were trying to warn about the following" + " previous failure:"); + criticalMsg ("%s:%d: %s", file, line, message); + criticalMsg ("The latest (NewObject()) exception's description" + " follows, to System.err:"); + (*env)->ExceptionDescribe (env); + } + BADLY_BROKEN1 ("Failure of JNI NewObject()" + " to make a java.lang.RuntimeException"); + return -1; + } + + + /* throw it */ + if ((*env)->Throw (env, wrapper)) + { + /* Throw() should just never fail, unless we're in such severe trouble + that we might as well die. */ + BADLY_BROKEN1 + ("GNU Classpath: Failure of JNI Throw to report an Exception"); + return -1; + } + + DELETE_LOCAL_REF (env, wrapper); + return 1; +} + + + +/* Rethrow an exception we received, wrapping it with a RuntimeException. 1 + if we did rethrow, -1 if we had trouble while rethrowing. + CAUSE should be identical to the most recent exception that happened, so + that ExceptionDescribe will work. (Otherwise nix.) */ +static int +rethrow (JNIEnv * env, jthrowable cause, const char *message, + gboolean isBroken, const char *file, int line) +{ + assert (cause); + return throw (env, cause, message, isBroken, file, line); +} + + +/* This function checks for a pending exception, and rethrows it with + * a wrapper RuntimeException to deal with possible type problems (in + * case some calling piece of code does not expect the exception being + * thrown) and to include the given extra message. + * + * Returns 0 if no problems found (so no exception thrown), 1 if we rethrew an + * exception. Returns -1 on failure. + */ +static int +maybe_rethrow (JNIEnv * env, const char *message, gboolean isBroken, + const char *file, int line) +{ + jthrowable cause = (*env)->ExceptionOccurred (env); + int ret = 0; + + /* rethrow if an exception happened */ + if (cause) + { + ret = rethrow (env, cause, message, isBroken, file, line); + DELETE_LOCAL_REF (env, cause); + } + + return 0; +} + +/* MAYBE_TROUBLE() is used to include a source location in the exception + message. Once we have run maybe_rethrow, if there WAS trouble, + return TRUE, else FALSE. + + MAYBE_TROUBLE() is actually never used; all problems that throw exceptions + are BROKEN, at least. Nothing is recoverable :(. See the discussion of + possible errors at thread_create_jni_impl(). */ +#define MAYBE_TROUBLE(_env, _message) \ + maybe_rethrow(_env, _message, FALSE, __FILE__, __LINE__) + +/* MAYBE_TROUBLE(), but something would be BROKEN if it were true. */ +#define MAYBE_BROKEN(_env, _message) \ + maybe_rethrow(_env, _message, TRUE, __FILE__, __LINE__) + +/* Like MAYBE_TROUBLE(), TROUBLE() is never used. */ +#define TROUBLE(_env, _message) \ + rethrow(_env, (*env)->ExceptionOccurred (env), _message, FALSE, \ + __FILE__, __LINE__) + +#define BROKEN(_env, _message) \ + rethrow (_env, (*env)->ExceptionOccurred (env), _message, TRUE, \ + __FILE__, __LINE__) + +/* Like MAYBE_TROUBLE(), NEW_TROUBLE() is never used. */ +#define NEW_TROUBLE(_env, _message) \ + throw (_env, NULL, _message, FALSE, __FILE__, __LINE__) + +#define NEW_BROKEN(_env, _message) \ + throw (_env, NULL, _message, TRUE, __FILE__, __LINE__) + +/* Like MAYBE_TROUBLE(), RETHROW_CAUSE() is never used. */ +#define RETHROW_CAUSE(_env, _cause, _message) \ + rethrow (_env, _cause, _message, FALSE, __FILE__, __LINE__) + +#define BROKEN_CAUSE(_env, _cause, _message) \ + rethrow (_env, _cause, _message, TRUE, __FILE__, __LINE__) + +/* Macros to handle the possibility that someone might have called one of the + GThreadFunctions API functions with a Java exception pending. It is + generally discouraged to continue to use JNI after a Java exception has + been raised. Sun's JNI book advises that one trap JNI errors immediately + and not continue with an exception pending. + + These are #if'd out for these reasons: + + 1) They do not work in the C '89 subset that Classpath is currently + (2004 May 10) sticking to; HIDE_OLD_TROUBLE() includes a declaration + that should be in scope for the rest of the function, so it needs a + language version that lets you mix declarations and statements. (This + could be worked around if it were important.) + + 2) They chew up more time and resources. + + 3) There does not ever seem to be old trouble -- the assertion in + HIDE_OLD_TROUBLE never goes off. + + You will want to re-enable them if this code needs to be used in a context + where old exceptions might be pending when the GThread functions are + called. + + The implementations in this file are responsible for skipping around calls + to SHOW_OLD_TROUBLE() if they've raised exceptions during the call. So, if + we reach SHOW_OLD_TROUBLE, we are guaranteed that there are no exceptions + pending. */ +#if 1 +#define HIDE_OLD_TROUBLE(env) \ + assert ( NULL == (*env)->ExceptionOccurred (env) ) + +#define SHOW_OLD_TROUBLE() \ + assert ( NULL == (*env)->ExceptionOccurred (env) ) +#else /* 0 */ +#define HIDE_OLD_TROUBLE(env) \ + jthrowable savedTrouble = (*env)->ExceptionOccurred (env); \ + (*env)->ExceptionClear (env); + +#define SHOW_OLD_TROUBLE() do \ +{ \ + assert ( NULL == (*env)->ExceptionOccurred (env) ) \ + if (savedTrouble) \ + { \ + if ((*env)->Throw (env, savedTrouble)) \ + BADLY_BROKEN ("ReThrowing the savedTrouble failed"); \ + } \ + DELETE_LOCAL_REF (env, savedTrouble); \ +} while(0) + +#endif /* 0 */ + +/* Set up the cache of jclass and jmethodID primitives we need + in order to throw new exceptions and rethrow exceptions. We do this + independently of the other caching. We need to have this cache set up + first, so that we can then report errors properly. + + If any errors while setting up the error cache, the world is BADLY_BROKEN. + + May be called more than once. + + Returns -1 if the cache was not initialized properly, 1 if it was. +*/ +static int +setup_exception_cache (JNIEnv * env) +{ + static int exception_cache_initialized = 0; /* -1 for trouble, 1 for proper + init. */ + + jclass lcl_class; /* a class used for local refs */ + + if (exception_cache_initialized) + return exception_cache_initialized; + lcl_class = (*env)->FindClass (env, "java/lang/RuntimeException"); + if ( ! lcl_class ) + { + BADLY_BROKEN1 ("Broken Class library or VM?" + " Couldn't find java/lang/RuntimeException"); + return exception_cache_initialized = -1; + } + /* Pin it down. */ + runtimeException_class = (jclass) (*env)->NewGlobalRef (env, lcl_class); + DELETE_LOCAL_REF (env, lcl_class); + if (!runtimeException_class) + { + BADLY_BROKEN1 ("Serious trouble: could not turn" + " java.lang.RuntimeException into a global reference"); + return exception_cache_initialized = -1; + } + + runtimeException_ctor = + (*env)->GetMethodID (env, runtimeException_class, "<init>", + "(Ljava/lang/String;Ljava/lang/Throwable;)V"); + if ( ! runtimeException_ctor ) + { + BADLY_BROKEN1 ("Serious trouble: classpath couldn't find a" + " two-arg constructor for java/lang/RuntimeException"); + return exception_cache_initialized = -1; + } + + return exception_cache_initialized = 1; +} + + +/**********************************************************/ +/***** The main cache *************************************/ +/**********************************************************/ + +/** This is a cache of all classes, methods, and field IDs that we use during + the run. We maintain a permanent global reference to each of the classes + we cache, since otherwise the (local) jclass that refers to that class + would go out of scope and possibly be reused in further calls. + + The permanent global reference also achieves the secondary goal of + protecting the validity of the methods and field IDs in case the classes + were otherwise unloaded and then later loaded again. Obviously, this will + never happen to classes such as java.lang.Thread and java.lang.Object, but + the primary reason for maintaining permanent global refs is sitll valid. + + The code in jnilink.c has a similar objective. TODO: Consider using that + code instead. + + --Steven Augart +*/ + +/* All of these are cached classes and method IDs: */ +/* java.lang.Object */ +static jclass obj_class; /* java.lang.Object */ +static jmethodID obj_ctor; /* no-arg Constructor for java.lang.Object */ +static jmethodID obj_notify_mth; /* java.lang.Object.notify() */ +static jmethodID obj_notifyall_mth; /* java.lang.Object.notifyall() */ +static jmethodID obj_wait_mth; /* java.lang.Object.wait() */ +static jmethodID obj_wait_nanotime_mth; /* java.lang.Object.wait(JI) */ + +/* GThreadMutex and its methods */ +static jclass mutex_class; +static jmethodID mutex_ctor; +static jfieldID mutex_lockForPotentialLockers_fld; +static jfieldID mutex_potentialLockers_fld; + +/* java.lang.Thread and its methods*/ +static jclass thread_class; /* java.lang.Thread */ +static jmethodID thread_current_mth; /* Thread.currentThread() */ +static jmethodID thread_equals_mth; /* Thread.equals() */ +static jmethodID thread_join_mth; /* Thread.join() */ +static jmethodID thread_setPriority_mth; /* Thread.setPriority() */ +static jmethodID thread_stop_mth; /* Thread.stop() */ +static jmethodID thread_yield_mth; /* Thread.yield() */ + +/* java.lang.ThreadLocal and its methods */ +static jclass threadlocal_class; /* java.lang.ThreadLocal */ +static jmethodID threadlocal_ctor; /* Its constructor */ +static jmethodID threadlocal_set_mth; /* ThreadLocal.set() */ +static jmethodID threadlocal_get_mth; /* ThreadLocal.get() */ + +/* java.lang.Long and its methods */ +static jclass long_class; /* java.lang.Long */ +static jmethodID long_ctor; /* constructor for it: (J) */ +static jmethodID long_longValue_mth; /* longValue()J */ + + +/* GThreadNativeMethodRunner */ +static jclass runner_class; +static jmethodID runner_ctor; +static jmethodID runner_threadToThreadID_mth; +static jmethodID runner_threadIDToThread_mth; +static jmethodID runner_deRegisterJoinable_mth; +static jmethodID runner_start_mth; /* Inherited Thread.start() */ + + +/* java.lang.InterruptedException */ +static jclass interrupted_exception_class; + + + + +/* Returns a negative value if there was trouble during initialization. + Returns a positive value of the cache was initialized correctly. + Never returns zero. */ +static int +setup_cache (JNIEnv * env) +{ + jclass lcl_class; + static int initialized = 0; /* 1 means initialized, 0 means uninitialized, + -1 means mis-initialized */ + + if (initialized) + return initialized; + + /* make sure we can report on trouble */ + if (setup_exception_cache (env) < 0) + return initialized = -1; + +#ifdef JNI_VERSION_1_2 + if (HAVE_JNI_VERSION_1_2) + assert ( ! (*env)->ExceptionCheck (env)); + else +#endif + assert ( ! (*env)->ExceptionOccurred (env)); + + /* java.lang.Object and its methods */ + lcl_class = (*env)->FindClass (env, "java/lang/Object"); + if (!lcl_class) + { + BROKEN (env, "cannot find java.lang.Object"); + return initialized = -1; + } + + /* Pin it down. */ + obj_class = (jclass) (*env)->NewGlobalRef (env, lcl_class); + DELETE_LOCAL_REF (env, lcl_class); + if (!obj_class) + { + BROKEN (env, "Cannot get a global reference to java.lang.Object"); + return initialized = -1; + } + + obj_ctor = (*env)->GetMethodID (env, obj_class, "<init>", "()V"); + if (!obj_ctor) + { + BROKEN (env, "cannot find constructor for java.lang.Object"); + return initialized = -1; + } + + obj_notify_mth = (*env)->GetMethodID (env, obj_class, "notify", "()V"); + if ( ! obj_notify_mth ) + { + BROKEN (env, "cannot find java.lang.Object.notify()V"); + return initialized = -1; + } + + obj_notifyall_mth = + (*env)->GetMethodID (env, obj_class, "notifyAll", "()V"); + if ( ! obj_notifyall_mth) + { + BROKEN (env, "cannot find java.lang.Object.notifyall()V"); + return initialized = -1; + } + + obj_wait_mth = (*env)->GetMethodID (env, obj_class, "wait", "()V"); + if ( ! obj_wait_mth ) + { + BROKEN (env, "cannot find Object.<wait()V>"); + return initialized = -1; + } + + obj_wait_nanotime_mth = + (*env)->GetMethodID (env, obj_class, "wait", "(JI)V"); + if ( ! obj_wait_nanotime_mth ) + { + BROKEN (env, "cannot find Object.<wait(JI)V>"); + return initialized = -1; + } + + /* GThreadMutex and its methods */ + lcl_class = (*env)->FindClass (env, "gnu/java/awt/peer/gtk/GThreadMutex"); + if ( ! lcl_class) + { + BROKEN (env, "cannot find gnu.java.awt.peer.gtk.GThreadMutex"); + return initialized = -1; + } + /* Pin it down. */ + mutex_class = (jclass) (*env)->NewGlobalRef (env, lcl_class); + DELETE_LOCAL_REF (env, lcl_class); + if ( ! mutex_class) + { + BROKEN (env, "Cannot get a global reference to GThreadMutex"); + return initialized = -1; + } + + mutex_ctor = (*env)->GetMethodID (env, mutex_class, "<init>", "()V"); + if ( ! mutex_ctor) + { + BROKEN (env, "cannot find zero-arg constructor for GThreadMutex"); + return initialized = -1; + } + + mutex_potentialLockers_fld = (*env)->GetFieldID + (env, mutex_class, "potentialLockers", "I"); + if ( ! mutex_class ) + { + BROKEN (env, "cannot find GThreadMutex.potentialLockers"); + return initialized = -1; + } + + if (! (mutex_lockForPotentialLockers_fld = (*env)->GetFieldID + (env, mutex_class, "lockForPotentialLockers", "Ljava/lang/Object;"))) + { + BROKEN (env, "cannot find GThreadMutex.lockForPotentialLockers"); + return initialized = -1; + } + + + /* java.lang.Thread */ + if (! (lcl_class = (*env)->FindClass (env, "java/lang/Thread"))) + { + BROKEN (env, "cannot find java.lang.Thread"); + return initialized = -1; + } + + /* Pin it down. */ + thread_class = (jclass) (*env)->NewGlobalRef (env, lcl_class); + DELETE_LOCAL_REF (env, lcl_class); + if (!thread_class) + { + BROKEN (env, "Cannot get a global reference to java.lang.Thread"); + return initialized = -1; + } + + thread_current_mth = + (*env)->GetStaticMethodID (env, thread_class, "currentThread", + "()Ljava/lang/Thread;"); + if (!thread_current_mth) + { + BROKEN (env, "cannot find Thread.currentThread() method"); + return initialized = -1; + } + + thread_equals_mth = + (*env)->GetMethodID (env, thread_class, "equals", "(Ljava/lang/Object;)Z"); + if (!thread_equals_mth) + { + BROKEN (env, "cannot find Thread.equals() method"); + return initialized = -1; + } + + thread_join_mth = (*env)->GetMethodID (env, thread_class, "join", "()V"); + if (!thread_join_mth) + { + BROKEN (env, "cannot find Thread.join() method"); + return initialized = -1; + } + + thread_stop_mth = (*env)->GetMethodID (env, thread_class, "stop", "()V"); + if ( ! thread_stop_mth ) + { + BROKEN (env, "cannot find Thread.stop() method"); + return initialized = -1; + } + + thread_setPriority_mth = + (*env)->GetMethodID (env, thread_class, "setPriority", "(I)V"); + if ( ! thread_setPriority_mth ) + { + BROKEN (env, "cannot find Thread.setPriority() method"); + return initialized = -1; + } + + thread_yield_mth = + (*env)->GetStaticMethodID (env, thread_class, "yield", "()V"); + if ( ! thread_yield_mth ) + { + BROKEN (env, "cannot find Thread.yield() method"); + return initialized = -1; + } + + /* java.lang.ThreadLocal */ + lcl_class = (*env)->FindClass (env, "java/lang/ThreadLocal"); + if ( ! lcl_class ) + { + BROKEN (env, "cannot find class java.lang.ThreadLocal"); + return initialized = -1; + } + + /* Pin it down. */ + threadlocal_class = (jclass) (*env)->NewGlobalRef (env, lcl_class); + DELETE_LOCAL_REF (env, lcl_class); + if ( ! threadlocal_class ) + { + BROKEN (env, "Cannot get a global reference to java.lang.ThreadLocal"); + return initialized = -1; + } + + threadlocal_ctor = (*env)->GetMethodID (env, threadlocal_class, + "<init>", "()V"); + if ( ! threadlocal_ctor ) + { + BROKEN (env, "cannot find ThreadLocal.<init>()V"); + return initialized = -1; + } + + threadlocal_get_mth = (*env)->GetMethodID (env, threadlocal_class, + "get", "()Ljava/lang/Object;"); + if ( ! threadlocal_get_mth ) + { + BROKEN (env, "cannot find java.lang.ThreadLocal.get()Object"); + return initialized = -1; + } + + threadlocal_set_mth = (*env)->GetMethodID (env, threadlocal_class, + "set", "(Ljava/lang/Object;)V"); + if ( ! threadlocal_set_mth ) + { + BROKEN (env, "cannot find ThreadLocal.set(Object)V"); + return initialized = -1; + } + + /* java.lang.Long */ + lcl_class = (*env)->FindClass (env, "java/lang/Long"); + if ( ! lcl_class ) + { + BROKEN (env, "cannot find class java.lang.Long"); + return initialized = -1; + } + + /* Pin it down. */ + long_class = (jclass) (*env)->NewGlobalRef (env, lcl_class); + DELETE_LOCAL_REF (env, lcl_class); + if (!long_class) + { + BROKEN (env, "Cannot get a global reference to java.lang.Long"); + return initialized = -1; + } + + long_ctor = (*env)->GetMethodID (env, long_class, "<init>", "(J)V"); + if (!long_ctor) + { + BROKEN (env, "cannot find method java.lang.Long.<init>(J)V"); + return initialized = -1; + } + + long_longValue_mth = + (*env)->GetMethodID (env, long_class, "longValue", "()J"); + if (!long_longValue_mth) + { + BROKEN (env, "cannot find method java.lang.Long.longValue()J"); + return initialized = -1; + } + + + /* GThreadNativeMethodRunner */ + lcl_class = + (*env)->FindClass (env, + "gnu/java/awt/peer/gtk/GThreadNativeMethodRunner"); + if ( ! lcl_class ) + { + BROKEN (env, + "cannot find gnu.java.awt.peer.gtk.GThreadNativeMethodRunner"); + return initialized = -1; + } + + /* Pin it down. */ + runner_class = (jclass) (*env)->NewGlobalRef (env, lcl_class); + DELETE_LOCAL_REF (env, lcl_class); + if (!runner_class) + { + BROKEN (env, + "Cannot get a global reference to the class GThreadNativeMethodRunner"); + return initialized = -1; + } + + runner_ctor = (*env)->GetMethodID (env, runner_class, "<init>", "(JJZ)V"); + if ( ! runner_ctor ) + { + BROKEN (env, + "cannot find method GThreadNativeMethodRunner.<init>(JJZ)"); + return initialized = -1; + } + + runner_start_mth = (*env)->GetMethodID (env, runner_class, "start", "()V"); + if ( ! runner_start_mth ) + { + BROKEN (env, "cannot find method GThreadNativeMethodRunner.start()V"); + return initialized = -1; + } + + + runner_threadToThreadID_mth = + (*env)->GetStaticMethodID (env, runner_class, + "threadToThreadID", "(Ljava/lang/Thread;)I"); + if ( ! runner_threadToThreadID_mth ) + { + BROKEN (env, + "cannot find method GThreadNativeMethodRunner.threadToThreadID(java.lang.Thread)I"); + return initialized = -1; + } + + + runner_threadIDToThread_mth = + (*env)->GetStaticMethodID (env, runner_class, + "threadIDToThread", "(I)Ljava/lang/Thread;"); + if ( ! runner_threadIDToThread_mth ) + { + BROKEN (env, + "cannot find method GThreadNativeMethodRunner.threadIDToThread(I)java.lang.Thread"); + return initialized = -1; + } + + + runner_deRegisterJoinable_mth = + (*env)->GetStaticMethodID (env, runner_class, "deRegisterJoinable", + "(Ljava/lang/Thread;)V"); + if (!runner_deRegisterJoinable_mth) + { + BROKEN (env, + "cannot find method GThreadNativeMethodRunner.deRegisterJoinable(java.lang.Thread)V"); + return initialized = -1; + } + + + /* java.lang.InterruptedException */ + lcl_class = (*env)->FindClass (env, "java/lang/InterruptedException"); + if ( ! lcl_class ) + { + BROKEN (env, "cannot find class java.lang.InterruptedException"); + return initialized = -1; + } + + /* Pin it down. */ + interrupted_exception_class = (jclass) (*env)->NewGlobalRef (env, lcl_class); + DELETE_LOCAL_REF (env, lcl_class); + if (!interrupted_exception_class) + { + BROKEN (env, "Cannot make a global reference" + " to java.lang.InterruptedException"); + return initialized = -1; + } + +#ifdef JNI_VERSION_1_2 + if (HAVE_JNI_VERSION_1_2) + assert ( ! (*env)->ExceptionCheck (env)); + else +#endif + assert ( ! (*env)->ExceptionOccurred (env)); + + + return initialized = 1; +} + + + + + +/************************************************************************/ +/* Utilities to allocate and free java.lang.Objects */ +/************************************************************************/ + +/* The condition variables are java.lang.Object objects, + * which this method allocates and returns a global ref. Note that global + * refs must be explicitly freed (isn't C fun?). + */ +static jobject +allocatePlainObject (JNIEnv * env) +{ + jobject lcl_obj, global_obj; + + lcl_obj = (*env)->NewObject (env, obj_class, obj_ctor); + if (!lcl_obj) + { + BROKEN (env, "cannot allocate object"); + return NULL; + } + + global_obj = (*env)->NewGlobalRef (env, lcl_obj); + DELETE_LOCAL_REF (env, lcl_obj); + if (!global_obj) + { + NEW_BROKEN (env, "cannot make global ref for a new plain Java object"); + /* Deliberate fall-through */ + } + + return global_obj; +} + +/* Frees any Java object given a global ref (isn't C fun?) */ +static void +freeObject (JNIEnv * env, jobject obj) +{ + if (obj) + { + (*env)->DeleteGlobalRef (env, obj); + /* DeleteGlobalRef can never fail */ + } +} + + +/************************************************************************/ +/* Utilities to allocate and free Java mutexes */ +/************************************************************************/ + +/* The mutexes are gnu.java.awt.peer.gtk.GThreadMutex objects, + * which this method allocates and returns a global ref. Note that global + * refs must be explicitly freed (isn't C fun?). + * + * Free this with freeObject() + */ +static jobject +allocateMutexObject (JNIEnv * env) +{ + jobject lcl_obj, global_obj; + + lcl_obj = (*env)->NewObject (env, mutex_class, mutex_ctor); + if (!lcl_obj) + { + BROKEN (env, "cannot allocate a GThreadMutex"); + return NULL; + } + + global_obj = (*env)->NewGlobalRef (env, lcl_obj); + DELETE_LOCAL_REF (env, lcl_obj); + if (!global_obj) + { + NEW_BROKEN (env, "cannot make global ref"); + /* Deliberate fallthrough */ + } + + return global_obj; +} + + +/************************************************************************/ +/* Locking code */ +/************************************************************************/ + +/* Lock a Java object */ +#define ENTER_MONITOR(env, m) \ + enterMonitor(env, m, G_STRINGIFY(m)) + +/* Return -1 on failure, 0 on success. */ +static int +enterMonitor (JNIEnv * env, jobject monitorObj, const char monName[]) +{ + if (TRACE_MONITORS) + tracing (" <MonitorEnter(%s)>", monName); + assert (monitorObj); + if ((*env)->MonitorEnter (env, monitorObj) < 0) + { + BROKEN (env, "cannot enter monitor"); + return -1; + } + return 0; +} + + +/* Unlock a Java object */ +#define EXIT_MONITOR(env, m) \ + exitMonitor(env, m, G_STRINGIFY(m)) + +static int +exitMonitor (JNIEnv * env, jobject mutexObj, const char monName[]) +{ + if (TRACE_MONITORS) + tracing (" <MonitorExit(%s)>", monName); + assert (mutexObj); + if ((*env)->MonitorExit (env, mutexObj) < 0) + { + BROKEN (env, "cannot exit monitor "); + return -1; + } + return 0; +} + + +/************************************************************************/ +/* Miscellaneous utilities */ +/************************************************************************/ + +/* Get the Java Thread object that corresponds to a particular thread ID. + A negative thread Id gives us a null object. + + Returns a local reference. +*/ +static jobject +getThreadFromThreadID (JNIEnv * env, gpointer gThreadID) +{ + jint threadNum = (jint) gThreadID; + jobject thread; + + if (threadNum < 0) + { + NEW_BROKEN (env, "getThreadFromThreadID asked to look up" + " a negative thread index"); + return NULL; + } + + thread = (*env)->CallStaticObjectMethod + (env, runner_class, runner_threadIDToThread_mth, threadNum); + + if (MAYBE_BROKEN (env, "cannot get Thread for threadID ")) + return NULL; + + return thread; +} + +/** Return the unique threadID of THREAD. + + Error handling: Return (gpointer) -1 on all failures, + and propagate an exception. +*/ +static gpointer +getThreadIDFromThread (JNIEnv * env, jobject thread) +{ + jint threadNum; + + if (ENABLE_EXPENSIVE_ASSERTIONS) + assert ((*env)->IsInstanceOf (env, thread, thread_class)); + + HIDE_OLD_TROUBLE (env); + + threadNum = (*env)->CallStaticIntMethod + (env, runner_class, runner_threadToThreadID_mth, thread); + + if (MAYBE_BROKEN (env, "cannot get ThreadID for a Thread ")) + { + threadNum = -1; + goto done; + } + + + SHOW_OLD_TROUBLE (); + +done: + return (gpointer) threadNum; +} + + +/************************************************************************/ +/* The Actual JNI functions that we pass to the function vector. */ +/************************************************************************/ + + +/************************************************************************/ +/* Mutex Functions */ +/************************************************************************/ + +/*** Mutex Utilities ****/ +struct mutexObj_cache +{ + jobject lockForPotentialLockersObj; /* Lock for the potentialLockers + field. Local reference. */ + jobject lockObj; /* The real lock we use. This is a GLOBAL + reference and must not be freed. */ +}; + +/* Initialize the cache of sub-locks for a particular mutex object. + + -1 on error, 0 on success. The caller is not responsible for freeing the + partially-populated cache in case of failure (but in practice does anyway) + (This actually never fails, though, since GetObjectField allegedly never + fails.) + + Guaranteed to leave all fields of the cache initialized, even if only to + zero. +*/ +static int +populate_mutexObj_cache (JNIEnv * env, jobject mutexObj, + struct mutexObj_cache *mcache) +{ + mcache->lockObj = mutexObj; /* the mutexObj is its own lock. */ + assert (mcache->lockObj); + + mcache->lockForPotentialLockersObj = (*env)->GetObjectField + (env, mutexObj, mutex_lockForPotentialLockers_fld); + /* GetObjectField can never fail. */ + + /* Retrieving a NULL object could only happen if we somehow got a + a mutex object that was not properly intialized. */ + assert (mcache->lockForPotentialLockersObj); + + return 0; +} + + +/* Clean out the mutexObj_cache, even if it was never populated. */ +static void +clean_mutexObj_cache (JNIEnv * env, struct mutexObj_cache *mcache) +{ + /* OK to pass NULL refs to DELETE_LOCAL_REF */ + DELETE_LOCAL_REF (env, mcache->lockForPotentialLockersObj); + /* mcache->lockObj is a GLOBAL reference. */ + mcache->lockObj = NULL; +} + +/* -1 on failure, 0 on success. + The mutexObj_cache is already populated for this particular object. */ +static int +mutexObj_lock (JNIEnv * env, jobject mutexObj, struct mutexObj_cache *mcache) +{ + jint potentialLockers; + + if (ENTER_MONITOR (env, mcache->lockForPotentialLockersObj)) + return -1; + + assert(mutexObj); + potentialLockers = + (*env)->GetIntField (env, mutexObj, mutex_potentialLockers_fld); + /* GetIntField() never fails. */ + + ++potentialLockers; + + (*env)->SetIntField + (env, mutexObj, mutex_potentialLockers_fld, potentialLockers); + + if (EXIT_MONITOR (env, mcache->lockForPotentialLockersObj)) + return -1; + + if (ENTER_MONITOR (env, mcache->lockObj)) + return -1; + + SHOW_OLD_TROUBLE (); + + return 0; +} + +/* Unlock a GMutex, once we're already in JNI and have already gotten the + mutexObj for it. This skips the messages that TRACE_API_CALLS would + print. + + Returns -1 on error, 0 on success. */ +static int +mutexObj_unlock (JNIEnv * env, jobject mutexObj, + struct mutexObj_cache *mcache) +{ + jint potentialLockers; + int ret = -1; /* assume failure until we suceed. */ + + /* Free the lock first, so that someone waiting for the lock can get it + ASAP. */ + /* This is guaranteed not to block. */ + if (EXIT_MONITOR (env, mcache->lockObj) < 0) + goto done; + + /* Kick down potentialLockers by one. We do this AFTER we free the lock, so + that we hold it no longer than necessary. */ + if (ENTER_MONITOR (env, mcache->lockForPotentialLockersObj) < 0) + goto done; + + potentialLockers = (*env)->GetIntField + (env, mutexObj, mutex_potentialLockers_fld); + /* GetIntField never fails */ + + assert (potentialLockers >= 1); + --potentialLockers; + + (*env)->SetIntField + (env, mutexObj, mutex_potentialLockers_fld, potentialLockers); + /* Never fails, so the JNI book says. */ + + /* Clean up. */ + if (EXIT_MONITOR (env, mcache->lockForPotentialLockersObj) < 0) + goto done; + ret = 0; + +done: + return ret; +} + +/*** Mutex Implementations ****/ + +/* Create a mutex, which is a java.lang.Object for us. + In case of failure, we'll return NULL. Which will implicitly + cause future calls to fail. */ +static GMutex * +mutex_new_jni_impl (void) +{ + jobject mutexObj; + JNIEnv *env; + union env_union e; + + if (TRACE_API_CALLS) + tracing ("mutex_new_jni_impl()"); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + + if (setup_cache (env) < 0) + { + mutexObj = NULL; + goto done; + } + + mutexObj = allocateMutexObject (env); + +done: + if (TRACE_API_CALLS) + tracing (" ==> %p \n", mutexObj); + + return (GMutex *) mutexObj; + +} + +/* Lock a mutex. */ +static void +mutex_lock_jni_impl (GMutex * mutex) +{ + struct mutexObj_cache mcache; + jobject mutexObj = (jobject) mutex; + JNIEnv *env; + union env_union e; + + if (TRACE_API_CALLS) + tracing ("mutex_lock_jni_impl( mutexObj = %p )", mutexObj); + + assert (mutexObj); + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + + if (setup_cache (env) < 0) + goto done; + + HIDE_OLD_TROUBLE (env); + + if (populate_mutexObj_cache (env, mutexObj, &mcache) < 0) + goto done; + + mutexObj_lock (env, mutexObj, &mcache); + /* No need to error check; we've already reported it in any case. */ + +done: + clean_mutexObj_cache (env, &mcache); + if (TRACE_API_CALLS) + tracing (" ==> VOID \n"); +} + + +/* Try to lock a mutex. Return TRUE if we succeed, FALSE if we fail. + FALSE on error. */ +static gboolean +mutex_trylock_jni_impl (GMutex * gmutex) +{ + jobject mutexObj = (jobject) gmutex; + jint potentialLockers; + gboolean ret = FALSE; + JNIEnv *env; + union env_union e; + struct mutexObj_cache mcache; + + if (TRACE_API_CALLS) + tracing ("mutex_trylock_jni_impl(mutexObj=%p)", mutexObj); + + assert (mutexObj); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + if (populate_mutexObj_cache (env, mutexObj, &mcache) < 0) + goto done; + + if (ENTER_MONITOR (env, mcache.lockForPotentialLockersObj)) + goto done; + + potentialLockers = (*env)->GetIntField + (env, mutexObj, mutex_potentialLockers_fld); + + assert (potentialLockers >= 0); + + if (potentialLockers) + { + /* Already locked. Clean up and leave. */ + EXIT_MONITOR (env, mcache.lockForPotentialLockersObj); + /* Ignore any error code from EXIT_MONITOR; there's nothing we could do + at this level, in any case. */ + goto done; + } + + /* Guaranteed not to block. */ + if (ENTER_MONITOR (env, mcache.lockObj)) + { + /* Clean up the existing lock. */ + EXIT_MONITOR (env, mcache.lockForPotentialLockersObj); + /* Ignore any error code from EXIT_MONITOR; there's nothing we could do + at this level, in any case. */ + goto done; + } + + + /* We have the monitor. Record that fact. */ + potentialLockers = 1; + (*env)->SetIntField + (env, mutexObj, mutex_potentialLockers_fld, potentialLockers); + /* Set*Field() never fails */ + + ret = TRUE; /* We have the lock. */ + + /* Clean up. */ + if (EXIT_MONITOR (env, mcache.lockForPotentialLockersObj)) + goto done; /* If we fail at this point, still keep the + main lock. */ + + SHOW_OLD_TROUBLE (); +done: + clean_mutexObj_cache (env, &mcache); + if (TRACE_API_CALLS) + tracing (" ==> %s\n", ret ? "TRUE" : "FALSE"); + return ret; +} + + +/* Unlock a mutex. */ +static void +mutex_unlock_jni_impl (GMutex * gmutex) +{ + jobject mutexObj = (jobject) gmutex; + struct mutexObj_cache mcache; + JNIEnv *env; + union env_union e; + + if (TRACE_API_CALLS) + tracing ("mutex_unlock_jni_impl(mutexObj=%p)", mutexObj); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + assert (mutexObj); + + if ( populate_mutexObj_cache (env, mutexObj, &mcache) < 0) + goto done; + + (void) mutexObj_unlock (env, mutexObj, &mcache); + + SHOW_OLD_TROUBLE (); + +done: + clean_mutexObj_cache (env, &mcache); + if (TRACE_API_CALLS) + tracing (" ==> VOID\n"); +} + + + +/* Free a mutex (isn't C fun?). OK this time for it to be NULL. + No failure conditions, for a change. */ +static void +mutex_free_jni_impl (GMutex * mutex) +{ + jobject mutexObj = (jobject) mutex; + JNIEnv *env; + union env_union e; + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + + if (TRACE_API_CALLS) + tracing ("mutex_free_jni_impl(%p)", mutexObj); + + freeObject (env, mutexObj); + + if (TRACE_API_CALLS) + tracing (" ==> VOID\n"); +} + + + + +/************************************************************************/ +/* Condition variable code */ +/************************************************************************/ + +/* Create a new condition variable. This is a java.lang.Object for us. */ +static GCond * +cond_new_jni_impl (void) +{ + jobject condObj; + JNIEnv *env; + union env_union e; + + if (TRACE_API_CALLS) + tracing ("mutex_free_jni_impl()"); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + + condObj = allocatePlainObject (env); + + if (TRACE_API_CALLS) + tracing (" ==> %p\n", condObj); + + return (GCond *) condObj; +} + +/* Signal on a condition variable. This is simply calling Object.notify + * for us. + */ +static void +cond_signal_jni_impl (GCond * gcond) +{ + JNIEnv *env; + union env_union e; + jobject condObj = (jobject) gcond; + + if (TRACE_API_CALLS) + tracing ("cond_signal_jni_impl(condObj = %p)", condObj); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + assert (condObj); + + /* Must have locked an object to call notify */ + if (ENTER_MONITOR (env, condObj)) + goto done; + + (*env)->CallVoidMethod (env, condObj, obj_notify_mth); + if (MAYBE_BROKEN (env, "cannot signal mutex with Object.notify()")) + { + if (EXIT_MONITOR (env, condObj)) + BADLY_BROKEN1 ("Failed to unlock a monitor; the VM may deadlock."); + goto done; + } + + EXIT_MONITOR (env, condObj); + + SHOW_OLD_TROUBLE (); + +done: + if (TRACE_API_CALLS) + tracing (" ==> VOID\n"); +} + +/* Broadcast to all waiting on a condition variable. This is simply + * calling Object.notifyAll for us. + */ +static void +cond_broadcast_jni_impl (GCond * gcond) +{ + jobject condObj = (jobject) gcond; + JNIEnv *env; + union env_union e; + + if (TRACE_API_CALLS) + tracing ("cond_broadcast_jni_impl(condObj=%p)", condObj); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + assert (condObj); + /* Must have locked an object to call notifyAll */ + if (ENTER_MONITOR (env, condObj)) + goto done; + + (*env)->CallVoidMethod (env, condObj, obj_notifyall_mth); + if (MAYBE_BROKEN (env, "cannot broadcast to mutex with Object.notify()")) + { + EXIT_MONITOR (env, condObj); + goto done; + } + + EXIT_MONITOR (env, condObj); + + SHOW_OLD_TROUBLE (); + +done: + if (TRACE_API_CALLS) + tracing (" ==> VOID\n"); +} + + +/* Wait on a condition variable. For us, this simply means calling + * Object.wait. + * + * Throws a Java exception on trouble; may leave the mutexes set arbitrarily. + * XXX TODO: Further improve error recovery. + */ +static void +cond_wait_jni_impl (GCond * gcond, GMutex * gmutex) +{ + struct mutexObj_cache cache; + jobject condObj = (jobject) gcond; + jobject mutexObj = (jobject) gmutex; + JNIEnv *env; + union env_union e; + + if (TRACE_API_CALLS) + tracing ("cond_wait_jni_impl(condObj=%p, mutexObj=%p)", + condObj, mutexObj); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + assert (condObj); + assert (mutexObj); + /* Must have locked a Java object to call wait on it */ + if (ENTER_MONITOR (env, condObj) < 0) + goto done; + + /* Our atomicity is now guaranteed; we're protected by the Java monitor on + condObj. Unlock the GMutex. */ + if (mutexObj_unlock (env, mutexObj, &cache)) + goto done; + + (*env)->CallVoidMethod (env, condObj, obj_wait_mth); + if (MAYBE_BROKEN (env, "cannot wait on condObj")) + { + EXIT_MONITOR (env, condObj); /* ignore err checking */ + goto done; + } + + /* Re-acquire the lock on the GMutex. Do this while we're protected by the + Java monitor on condObj. */ + if (mutexObj_lock (env, mutexObj, &cache)) + goto done; + + EXIT_MONITOR (env, condObj); + + SHOW_OLD_TROUBLE (); + +done: + if (TRACE_API_CALLS) + tracing (" ==> VOID\n"); +} + + +/** Wait on a condition variable until a timeout. This is a little tricky + * for us. We first call Object.wait(J) giving it the appropriate timeout + * value. On return, we check whether an InterruptedException happened. If + * so, that is Java-speak for wait timing out. + * + * We return FALSE if we timed out. Return TRUE if the condition was + * signalled first, before we timed out. + * + * In case of trouble we throw a Java exception. Whether we return FALSE or + * TRUE depends upon whether the condition was raised before the trouble + * happened. + * + * I believe that this function goes to the proper lengths to try to unlock + * all of the locked mutexes and monitors, as appropriate, and that it further + * tries to make sure that the thrown exception is the current one, not any + * future cascaded one from something like a failure to unlock the monitors. + */ +static gboolean +cond_timed_wait_jni_impl (GCond * gcond, GMutex * gmutex, GTimeVal * end_time) +{ + JNIEnv *env; + union env_union e; + jlong time_millisec; + jint time_nanosec; + jthrowable cause; + jobject condObj = (jobject) gcond; + jobject mutexObj = (jobject) gmutex; + gboolean condRaised = FALSE; /* Condition has not been raised yet. */ + struct mutexObj_cache cache; + gboolean interrupted; + + if (TRACE_API_CALLS) + { + tracing ("cond_timed_wait_jni_impl(cond=%p, mutex=%p," + " end_time=< sec=%lu, usec=%lu >)", condObj, mutexObj, + (unsigned long) end_time->tv_sec, + (unsigned long) end_time->tv_usec); + } + + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + time_millisec = end_time->tv_sec * 1000 + end_time->tv_usec / 1000; + time_nanosec = 1000 * (end_time->tv_usec % 1000); + + /* Must have locked an object to call wait */ + if (ENTER_MONITOR (env, condObj) < 0) + goto done; + + if (mutexObj_unlock (env, mutexObj, &cache) < 0) + { + if (EXIT_MONITOR (env, condObj) < 0) + criticalMsg + ("Unable to unlock an existing lock on a condition; your proram may deadlock"); + goto done; + } + + + (*env)->CallVoidMethod (env, condObj, obj_wait_nanotime_mth, + time_millisec, time_nanosec); + + /* If there was trouble, save that fact, and the reason for the trouble. We + want to respond to this condition as fast as possible. */ + cause = (*env)->ExceptionOccurred (env); + + if ( ! cause ) + { + condRaised = TRUE; /* condition was signalled */ + } + else if ((*env)->IsInstanceOf (env, cause, interrupted_exception_class)) + { + condRaised = FALSE; /* Condition was not raised before timeout. + (This is redundant with the initialization + of condRaised above) */ + (*env)->ExceptionClear (env); /* Clear the InterruptedException. */ + cause = NULL; /* no pending cause now. */ + } + else + { + interrupted = FALSE; /* Trouble, but not because of + InterruptedException. Assume the condition + was not raised. */ + /* Leave condRaised set to FALSE */ + } + + /* Irrespective of whether there is a pending problem to report, go ahead + and try to clean up. This may end up throwing an exception that is + different from the one that was thrown by the call to Object.wait(). + So we will override it with the first exception (don't want to have + cascading problems). */ + if (mutexObj_lock (env, mutexObj, &cache) && !cause) + { + cause = (*env)->ExceptionOccurred (env); + assert (cause); + } + + if (EXIT_MONITOR (env, condObj) && !cause) + { + cause = (*env)->ExceptionOccurred (env); + assert (cause); + } + + if (cause) /* Raise the first cause. */ + { + BROKEN_CAUSE (env, cause, "error in timed wait or during its cleanup"); + goto done; + } + + SHOW_OLD_TROUBLE (); + +done: + if (TRACE_API_CALLS) + tracing (" ==> condRaised = %s\n", condRaised ? "TRUE" : "FALSE"); + return condRaised; +} + + +/* Free a condition variable. (isn't C fun?). Can not fail. */ +static void +cond_free_jni_impl (GCond * cond) +{ + jobject condObj = (jobject) cond; + JNIEnv *env; + union env_union e; + + if (TRACE_API_CALLS) + tracing ("cond_free_jni_impl(condObj = %p)", condObj); + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + + freeObject (env, condObj); + + if (TRACE_API_CALLS) + tracing (" ==> VOID\n"); +} + + +/************************************************************************/ +/* Thread-local data code */ +/************************************************************************/ + +/* Create a new thread-local key. We use java.lang.ThreadLocal objects + * for this. This returns the pointer representation of a Java global + * reference. + * + * We will throw a Java exception and return NULL in case of failure. + */ +static GPrivate * +private_new_jni_impl (GDestroyNotify notify __attribute__ ((unused))) +{ + JNIEnv *env; + union env_union e; + jobject lcl_key; + jobject global_key; + GPrivate *gkey = NULL; /* Error return code */ + + if (TRACE_API_CALLS) + tracing ("private_new_jni_impl()"); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + lcl_key = (*env)->NewObject (env, threadlocal_class, threadlocal_ctor); + if ( ! lcl_key ) + { + BROKEN (env, "cannot allocate a ThreadLocal"); + goto done; + } + + global_key = ((*env)->NewGlobalRef (env, lcl_key)); + DELETE_LOCAL_REF (env, lcl_key); + if ( ! global_key) + { + NEW_BROKEN (env, "cannot create a GlobalRef to a new ThreadLocal"); + goto done; + } + + gkey = (GPrivate *) global_key; + SHOW_OLD_TROUBLE (); + +done: + if (TRACE_API_CALLS) + tracing (" ==> %p\n", (void *) gkey); + + return gkey; +} + +/* Get this thread's value for a thread-local key. This is simply + * ThreadLocal.get for us. Return NULL if no value. (I can't think of + * anything else to do.) + */ +static gpointer +private_get_jni_impl (GPrivate * gkey) +{ + JNIEnv *env; + union env_union e; + jobject val_wrapper; + jobject keyObj = (jobject) gkey; + gpointer thread_specific_data = NULL; /* Init to the error-return value */ + + jlong val; + + if (TRACE_API_CALLS) + tracing ("private_get_jni_impl(keyObj=%p)", keyObj); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + val_wrapper = (*env)->CallObjectMethod (env, keyObj, threadlocal_get_mth); + if (MAYBE_BROKEN (env, "cannot find thread-local object")) + goto done; + + if (! val_wrapper ) + { + /* It's Java's "null" object. No ref found. This is OK; we must never + have set a value in this thread. Note that this next statement is + not necessary, strictly speaking, since we're already initialized to + NULL. A good optimizing C compiler will detect that and optimize out + this statement. */ + thread_specific_data = NULL; + goto done; + } + + val = (*env)->CallLongMethod (env, val_wrapper, long_longValue_mth); + + if (MAYBE_BROKEN (env, "cannot get thread local value")) + goto done; + + thread_specific_data = (gpointer) (intptr_t) val; + + /* Only re-raise the old pending exception if a new one hasn't come along to + supersede it. */ + SHOW_OLD_TROUBLE (); + +done: + + if (TRACE_API_CALLS) + tracing (" ==> %p\n", thread_specific_data); + + return thread_specific_data; +} + +/* Set this thread's value for a thread-local key. This is simply + * ThreadLocal.set() for us. + */ +static void +private_set_jni_impl (GPrivate * gkey, gpointer thread_specific_data) +{ + JNIEnv *env; + union env_union e; + jobject val_wrapper; + jobject keyObj = (jobject) gkey; + + + if (TRACE_API_CALLS) + tracing ("private_set_jni_impl(keyObj=%p, thread_specific_data=%p)", + keyObj, thread_specific_data); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + /* We are just going to always use a Java long to represent a C pointer. + Otherwise all of the code would end up being conditionalized for various + pointer sizes, and that seems like too much of a hassle, in order to save + a paltry few bytes, especially given the horrendous overhead of JNI in + any case. + */ + + val_wrapper = (*env)->NewObject (env, long_class, long_ctor, + (jlong) (intptr_t) thread_specific_data); + if ( ! val_wrapper ) + { + BROKEN (env, "cannot create a java.lang.Long"); + goto done; + } + + /* At this point, we now have set lcl_obj as a numeric class that wraps + around the thread-specific data we were given. */ + (*env)->CallVoidMethod (env, keyObj, threadlocal_set_mth, val_wrapper); + if (MAYBE_BROKEN (env, "cannot set thread local value")) + goto done; + + SHOW_OLD_TROUBLE (); +done: + if (TRACE_API_CALLS) + tracing (" ==> VOID\n"); +} + + +/** Create an object of type gnu.java.awt.peer.gtk.GThreadNativeMethodRunner. + Run it. + + We need to create joinable threads. We handle the notion of a joinable + thread by determining whether or not we are going to maintain a permanent + hard reference to it until it croaks. + + Posix does not appear to have a Java-like concept of daemon threads, where + the JVM will exit when there are only daemon threads running. + + Error handling: + + To quote from the glib guide: + "GError should only be used to report recoverable runtime errors, never + to report programming errors." + + So how do we consider the failure to create a thread? Well, each of the + failure cases in this function are discussed, and none of them are really + recoverable. + + The glib library is really designed so that you should fail + catastrophically in case of "programming errors". The only error defined + for the GThread functions is G_THREAD_ERROR_AGAIN, and that for + thread_create. + + Most of these GThread functions could fail if we run out of memory, for + example, but the only one capable of reporting that fact is + thread_create. */ +static void +thread_create_jni_impl (GThreadFunc func, + gpointer data, + gulong stack_size __attribute__((unused)), + gboolean joinable, + gboolean bound __attribute__((unused)), + GThreadPriority gpriority, + /* This prototype is horrible. threadIDp is actually + a gpointer to the thread's thread-ID. Which is, + of course, itself a gpointer-typed value. Ouch. */ + gpointer threadIDp, + /* Do not touch the GError stuff unless you have + RECOVERABLE trouble. There is no recoverable + trouble in this implementation. */ + GError **errorp __attribute__((unused))) +{ + JNIEnv *env; + union env_union e; + union func_union f; + jboolean jjoinable = joinable; + jobject newThreadObj; + gpointer threadID; /* to be filled in */ + + if (TRACE_API_CALLS) + { + f.g_func = func; + tracing ("thread_create_jni_impl(func=%p, data=%p, joinable=%s," + " threadIDp=%p, *(int *) threadIDp = %d)", + f.void_func, data, joinable ? "TRUE" : "FALSE", + threadIDp, *(int *) threadIDp); + } + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + { + /* The failed call to setup the cache is certainly not recoverable; + not appropriate for G_THREAD_ERROR_AGAIN. */ + *(gpointer *) threadIDp = NULL; + goto done; + } + HIDE_OLD_TROUBLE (env); + + /* If a thread is joinable, then notify its constructor. The constructor + will enter a hard reference for it, and the hard ref. won't go away until + the thread has been joined. */ + newThreadObj = + (*env)->NewObject (env, runner_class, runner_ctor, + (jlong) (intptr_t) func, (jlong) (intptr_t) data, + jjoinable); + if ( ! newThreadObj ) + { + BROKEN (env, "creating a new thread failed in the constructor"); + *(gpointer *) threadIDp = NULL; + /* The failed call to the constructor does not throw any errors such + that G_THREAD_ERROR_AGAIN is appropriate. No other recoverable + errors defined. Once again, we go back to the VM. */ + goto done; + } + + if (threadObj_set_priority (env, newThreadObj, gpriority) < 0) + { + *(gpointer *) threadIDp = NULL; + /* None of these possible exceptions from Thread.setPriority() are + recoverable, so they are not appropriate for EAGAIN. So we should + fail. */ + goto done; + } + + (*env)->CallVoidMethod (env, runner_class, runner_start_mth); + + if (MAYBE_BROKEN (env, "starting a new thread failed")) + { + *(gpointer *) threadIDp = NULL; + /* The only exception Thread.start() throws is + IllegalStateException. And that would indicate a programming error. + + So there are no situations such that G_THREAD_ERROR_AGAIN would be + OK. + + So, we don't use g_set_error() here to perform any error reporting. + */ + goto done; + } + + threadID = getThreadIDFromThread (env, newThreadObj); + + *(gpointer *) threadIDp = threadID; + SHOW_OLD_TROUBLE (); + +done: + if (TRACE_API_CALLS) + tracing (" ==> (threadID = %p) \n", threadID); +} + + +/* Wraps a call to g_thread_yield. */ +static void +thread_yield_jni_impl (void) +{ + JNIEnv *env; + union env_union e; + + if (TRACE_API_CALLS) + tracing ("thread_yield_jni_impl()"); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + (*env)->CallStaticVoidMethod (env, thread_class, thread_yield_mth); + if (MAYBE_BROKEN (env, "Thread.yield() failed")) + goto done; + + SHOW_OLD_TROUBLE (); + +done: + if (TRACE_API_CALLS) + tracing (" ==> VOID\n"); +} + + +static void +thread_join_jni_impl (gpointer threadID) +{ + JNIEnv *env; + union env_union e; + jobject threadObj = NULL; + + if ( TRACE_API_CALLS ) + tracing ("thread_join_jni_impl(threadID=%p) ", threadID); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + HIDE_OLD_TROUBLE (env); + + threadObj = getThreadFromThreadID (env, threadID); + if ( ! threadObj ) /* Already reported with BROKEN */ + goto done; + + (*env)->CallVoidMethod (env, threadObj, thread_join_mth); + if (MAYBE_BROKEN (env, "Thread.join() failed")) + goto done; + + + (*env)->CallStaticVoidMethod + (env, runner_class, runner_deRegisterJoinable_mth, threadObj); + if (MAYBE_BROKEN (env, "Thread.deRegisterJoinableThread() failed")) + goto done; + + SHOW_OLD_TROUBLE (); + +done: + DELETE_LOCAL_REF (env, threadObj); + if (TRACE_API_CALLS) + tracing (" ==> VOID \n"); +} + +/* Terminate the current thread. Unlike pthread_exit(), here we do not need + to bother with a return value or exit value for the thread which is about + to croak. (The gthreads abstraction doesn't use it.) However, we *do* + need to bail immediately. We handle this with Thread.stop(), which is + a deprecated method. + + It's deprecated since we might leave objects protected by monitors in + half-constructed states on the way out -- Thread.stop() throws a + ThreadDeath exception, which is usually unchecked. There is no good + solution that I can see. */ +static void +thread_exit_jni_impl (void) +{ + JNIEnv *env; + union env_union e; + jobject this_thread; + + if (TRACE_API_CALLS) + tracing ("thread_exit_jni_impl() "); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + goto done; + + HIDE_OLD_TROUBLE (env); + + this_thread = (*env)-> + CallStaticObjectMethod (env, thread_class, thread_current_mth); + + if ( ! this_thread ) + { + BROKEN (env, "cannot get current thread"); + goto done; + } + + (*env)->CallVoidMethod (env, this_thread, thread_stop_mth); + if (MAYBE_BROKEN (env, "cannot call Thread.stop() on current thread")) + goto done; + + SHOW_OLD_TROUBLE (); + +done: + if (TRACE_API_CALLS) + tracing (" ==> VOID \n"); +} + + +/* Translate a GThreadPriority to a Java priority level. */ +static jint +javaPriorityLevel (GThreadPriority priority) +{ + /* We have these fields in java.lang.Thread to play with: + + static int MIN_PRIORITY The minimum priority that a thread can have. + static int NORM_PRIORITY The default priority that is assigned to a + thread. + static int MAX_PRIORITY The maximum priority that a thread can have. + + We get these from the header file generated by javah, even though they're + documented as being 1, 5, and 10. + */ + static const jint minJPri = + gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MIN_PRIORITY; + static const jint normJPri = + gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_NORM_PRIORITY; + static const jint maxJPri = + gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MAX_PRIORITY; + + switch (priority) + { + case G_THREAD_PRIORITY_LOW: + return minJPri; + break; + + default: + assert_not_reached (); + /* Deliberate fall-through if assertions are turned off; also shuts up + GCC warnings if they're turned on. */ + case G_THREAD_PRIORITY_NORMAL: + return normJPri; + break; + + case G_THREAD_PRIORITY_HIGH: + return (normJPri + maxJPri) / 2; + break; + + case G_THREAD_PRIORITY_URGENT: + return maxJPri; + break; + } +} + + +/** It would be safe not to implement this, according to the JNI docs, since + not all platforms do thread priorities. However, we might as well + provide the hint for those who want it. +*/ +static void +thread_set_priority_jni_impl (gpointer gThreadID, GThreadPriority gpriority) +{ + jobject threadObj = NULL; + JNIEnv *env; + union env_union e; + + if (TRACE_API_CALLS) + tracing ("thread_set_priority_jni_impl(gThreadID=%p, gpriority = %u) ", + gThreadID, gpriority); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + + if (setup_cache (env) < 0) + goto done; + + HIDE_OLD_TROUBLE (env); + + + threadObj = getThreadFromThreadID (env, gThreadID); + if ( ! threadObj) /* Reported with BROKEN already. */ + goto done; + + if (threadObj_set_priority (env, threadObj, gpriority)) + goto done; + + SHOW_OLD_TROUBLE (); + +done: + DELETE_LOCAL_REF (env, threadObj); + + if (TRACE_API_CALLS) + tracing (" ==> VOID\n"); +} + + +/** It would be safe not to implement this, according to the JNI docs, since + not all platforms do thread priorities. However, we might as well + provide the hint for those who want it. + + -1 on failure, 0 on success. */ +static int +threadObj_set_priority (JNIEnv * env, jobject threadObj, + GThreadPriority gpriority) +{ + jint javaPriority = javaPriorityLevel (gpriority); + (*env)->CallVoidMethod (env, threadObj, thread_setPriority_mth, + javaPriority); + return MAYBE_BROKEN (env, "Thread.setPriority() failed"); +} + + +/** Return the result of Thread.currentThread(), a static method. */ +static void +thread_self_jni_impl (/* Another confusing glib prototype. This is + actually a gpointer to the thread's thread-ID. + Which is, of course, a gpointer. */ + gpointer my_thread_IDp) +{ + JNIEnv *env; + union env_union e; + jobject this_thread; + gpointer my_threadID; + + if (TRACE_API_CALLS) + tracing ("thread_self_jni_impl(my_thread_IDp=%p)", my_thread_IDp); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + + if (setup_cache (env) < 0) + return; + + HIDE_OLD_TROUBLE (env); + + this_thread = (*env)-> + CallStaticObjectMethod (env, thread_class, thread_current_mth); + if (! this_thread ) + { + BROKEN (env, "cannot get current thread"); + my_threadID = NULL; + goto done; + } + + my_threadID = getThreadIDFromThread (env, this_thread); + SHOW_OLD_TROUBLE (); + +done: + if (TRACE_API_CALLS) + tracing (" ==> (my_threadID = %p) \n", my_threadID); + + *(gpointer *) my_thread_IDp = my_threadID; +} + + +static gboolean +thread_equal_jni_impl (gpointer thread1, gpointer thread2) +{ + JNIEnv *env; + union env_union e; + + gpointer threadID1 = *(gpointer *) thread1; + gpointer threadID2 = *(gpointer *) thread2; + + jobject thread1_obj = NULL; + jobject thread2_obj = NULL; + gboolean ret; + + if (TRACE_API_CALLS) + tracing ("thread_equal_jni_impl(threadID1=%p, threadID2=%p)", + threadID1, threadID2); + + e.jni_env = &env; + (*cp_gtk_the_vm)->GetEnv (cp_gtk_the_vm, e.void_env, JNI_VERSION_1_1); + if (setup_cache (env) < 0) + { + ret = FALSE; /* what is safer? We really don't ever want + to return from here. */ + goto done; + } + + HIDE_OLD_TROUBLE (env); + thread1_obj = getThreadFromThreadID (env, threadID1); + thread2_obj = getThreadFromThreadID (env, threadID2); + + ret = (*env)->CallBooleanMethod (env, thread1_obj, + thread_equals_mth, thread2_obj); + + if (MAYBE_BROKEN (env, "Thread.equals() failed")) + { + ret = FALSE; + goto done; + } + + SHOW_OLD_TROUBLE (); + + +done: + DELETE_LOCAL_REF (env, thread1_obj); + DELETE_LOCAL_REF (env, thread2_obj); + + if (TRACE_API_CALLS) + tracing (" ==> %s\n", ret ? "TRUE" : "FALSE"); + + return ret; +} + + + + +/************************************************************************/ +/* GLIB interface */ +/************************************************************************/ + +/* set of function pointers to give to glib. */ +GThreadFunctions cp_gtk_portable_native_sync_jni_functions = { + mutex_new_jni_impl, /* mutex_new */ + mutex_lock_jni_impl, /* mutex_lock */ + mutex_trylock_jni_impl, /* mutex_trylock */ + mutex_unlock_jni_impl, /* mutex_unlock */ + mutex_free_jni_impl, /* mutex_free */ + cond_new_jni_impl, /* cond_new */ + cond_signal_jni_impl, /* cond_signal */ + cond_broadcast_jni_impl, /* cond_broadcast */ + cond_wait_jni_impl, /* cond_wait */ + cond_timed_wait_jni_impl, /* cond_timed_wait */ + cond_free_jni_impl, /* cond_free */ + private_new_jni_impl, /* private_new */ + private_get_jni_impl, /* private_get */ + private_set_jni_impl, /* private_set */ + thread_create_jni_impl, /* thread_create */ + thread_yield_jni_impl, /* thread_yield */ + thread_join_jni_impl, /* thread_join */ + thread_exit_jni_impl, /* thread_exit */ + thread_set_priority_jni_impl, /* thread_set_priority */ + thread_self_jni_impl, /* thread_self */ + thread_equal_jni_impl, /* thread_equal */ +}; + + +/* Keep c-font-lock-extra-types in alphabetical order. */ +/* Local Variables: */ +/* c-file-style: "gnu" */ +/* c-font-lock-extra-types: ("\\sw+_t" "gboolean" "GError" "gpointer" + "GPrivate" "GThreadFunc" "GThreadFunctions" "GThreadPriority" + "gulong" + "JNIEnv" + "jboolean" "jclass" "jfieldID" "jint" "jlong" "jmethodID" "jobject" "jstring" "jthrowable" ) */ +/* End: */ diff --git a/libjava/classpath/native/jni/gtk-peer/gthread-jni.h b/libjava/classpath/native/jni/gtk-peer/gthread-jni.h new file mode 100644 index 00000000000..3d052dc106e --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gthread-jni.h @@ -0,0 +1,48 @@ +/* gthread-jni.h + Copyright (C) 1998, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef __GTHREADJNI_H__ +#define __GTHREADJNI_H__ + +#include <jni.h> +#include <glib.h> +#include "gtkpeer.h" + +extern GThreadFunctions cp_gtk_portable_native_sync_jni_functions; +extern JavaVM *cp_gtk_the_vm; + +#endif /* __GTHREADJNI_H__ */ diff --git a/libjava/classpath/native/jni/gtk-peer/gtkcairopeer.h b/libjava/classpath/native/jni/gtk-peer/gtkcairopeer.h new file mode 100644 index 00000000000..dee843c8a70 --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gtkcairopeer.h @@ -0,0 +1,93 @@ +#ifndef __GTKCAIROPEER_H__ +#define __GTKCAIROPEER_H__ + +/* gtkcairopeer.h -- Some global variables and #defines + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "gtkpeer.h" +#include <cairo.h> +#include <gdk-pixbuf/gdk-pixbuf.h> + +/* + A graphics2d struct is both simpler and uglier than a graphics + struct. + + Most of the graphics2d drawing state is held in the referenced cairo_t + and corresponding cairo_surface_t, so we can ignore it. + + In addition to the cairo_t, we need to hold an extra reference to the + underlying GdkDrawable so its refcount matches the lifecycle of the java + Graphics object which is peering with us; also a reference to a byte + buffer and cairo_surface_t which contain the pattern you're drawing from + (if it exists). + + Finally, it is possible that we are using a non-RENDER capable X server, + therefore we will be drawing to an cairo_surface_t which is actually a + pixbuf. When this is the case, the pointer to a GdkPixbuf will be + non-NULL and any drawing operation needs to be bracketed by pixbuf + load/save operations. If the GdkPixbuf pointer is NULL, we will treat + the cairo_surface_t as RENDER-capable. + */ + +struct graphics2d +{ + cairo_t *cr; + cairo_surface_t *surface; + GdkDrawable *drawable; + GdkWindow *win; + GdkPixbuf *drawbuf; + char *pattern_pixels; + cairo_surface_t *pattern_surface; + cairo_pattern_t *pattern; + gboolean debug; + enum + { + MODE_DRAWABLE_WITH_RENDER, + MODE_DRAWABLE_NO_RENDER, + MODE_JAVA_ARRAY + } + mode; + + /* Support for MODE_JAVA_ARRAY */ + jintArray jarray; + jint width, height; + jint *javabuf; + jint *javabuf_copy; + jboolean isCopy; +}; + +#endif /* __GTKCAIROPEER_H */ diff --git a/libjava/classpath/native/jni/gtk-peer/gtkpeer.h b/libjava/classpath/native/jni/gtk-peer/gtkpeer.h new file mode 100644 index 00000000000..f291d82ef4b --- /dev/null +++ b/libjava/classpath/native/jni/gtk-peer/gtkpeer.h @@ -0,0 +1,206 @@ +/* gtkpeer.h -- Some global variables and #defines + Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include <gtk/gtk.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <config.h> +#include "native_state.h" + +#include <jni.h> + +#ifndef __GTKPEER_H__ +#define __GTKPEER_H__ + +#ifndef __GNUC__ +#define __attribute__(x) /* nothing */ +#endif + +extern struct state_table *cp_gtk_native_state_table; +extern struct state_table *cp_gtk_native_global_ref_table; + +#define NSA_INIT(env, clazz) \ + do {cp_gtk_native_state_table = cp_gtk_init_state_table (env, clazz); \ + cp_gtk_native_global_ref_table = cp_gtk_init_state_table (env, clazz);} while (0) + +#define NSA_GET_PTR(env, obj) \ + cp_gtk_get_state (env, obj, cp_gtk_native_state_table) + +#define NSA_SET_PTR(env, obj, ptr) \ + cp_gtk_set_state (env, obj, cp_gtk_native_state_table, (void *)ptr) + +#define NSA_DEL_PTR(env, obj) \ + cp_gtk_remove_state_slot (env, obj, cp_gtk_native_state_table) + +#define NSA_GET_GLOBAL_REF(env, obj) \ + cp_gtk_get_state (env, obj, cp_gtk_native_global_ref_table) + +#define NSA_SET_GLOBAL_REF(env, obj) \ + do {jobject *globRefPtr; \ + globRefPtr = (jobject *) malloc (sizeof (jobject)); \ + *globRefPtr = (*env)->NewGlobalRef (env, obj); \ + cp_gtk_set_state (env, obj, cp_gtk_native_global_ref_table, (void *)globRefPtr);} while (0) + +#define NSA_DEL_GLOBAL_REF(env, obj) \ + do {jobject *globRefPtr = cp_gtk_get_state (env, obj, cp_gtk_native_global_ref_table); \ + cp_gtk_remove_state_slot (env, obj, cp_gtk_native_global_ref_table); \ + (*env)->DeleteGlobalRef (env, *globRefPtr); \ + free (globRefPtr);} while (0) + +#define SWAPU32(w) \ + (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24)) + +struct graphics +{ + GdkDrawable *drawable; + GdkGC *gc; + GdkColormap *cm; + PangoFontDescription *pango_font; + PangoContext *pango_context; + PangoLayout *pango_layout; + jint x_offset, y_offset; +}; + +#define AWT_SHIFT_DOWN_MASK (1 << 6) +#define AWT_CTRL_DOWN_MASK (1 << 7) +#define AWT_META_DOWN_MASK (1 << 8) +#define AWT_ALT_DOWN_MASK (1 << 9) + +#define AWT_BUTTON1_MASK (1 << 4) +#define AWT_BUTTON2_MASK (1 << 3) +#define AWT_BUTTON3_MASK (1 << 2) + +#define AWT_ITEM_SELECTED 1 +#define AWT_ITEM_DESELECTED 2 + +#define AWT_KEY_TYPED 400 +#define AWT_KEY_PRESSED 401 +#define AWT_KEY_RELEASED 402 + +#define AWT_KEY_LOCATION_UNKNOWN 0 +#define AWT_KEY_LOCATION_STANDARD 1 +#define AWT_KEY_LOCATION_LEFT 2 +#define AWT_KEY_LOCATION_RIGHT 3 +#define AWT_KEY_LOCATION_NUMPAD 4 + +#define AWT_STYLE_PLAIN 0 +#define AWT_STYLE_BOLD 1 +#define AWT_STYLE_ITALIC 2 + +/* Used in GtkComponentPeer and GtkWindowPeer */ +#define VK_NUMPAD0 96 +#define VK_NUMPAD1 97 +#define VK_NUMPAD2 98 +#define VK_NUMPAD3 99 +#define VK_NUMPAD4 100 +#define VK_NUMPAD5 101 +#define VK_NUMPAD6 102 +#define VK_NUMPAD7 103 +#define VK_NUMPAD8 104 +#define VK_NUMPAD9 105 +#define VK_DECIMAL 110 + +JNIEnv *cp_gtk_gdk_env(void); + +/* Global variables */ +extern double cp_gtk_dpi_conversion_factor; +extern GtkWindowGroup *cp_gtk_global_window_group; + +/* Union used for type punning. */ +union widget_union +{ + void **void_widget; + GtkWidget **widget; +}; + +/* Keycode helpers */ +guint cp_gtk_awt_keycode_to_keysym (jint keyCode, jint keyLocation); + +/* Image helpers */ +GdkPixbuf *cp_gtk_image_get_pixbuf (JNIEnv *env, jobject obj); +GdkPixmap *cp_gtk_image_get_pixmap (JNIEnv *env, jobject obj); +jboolean cp_gtk_image_is_offscreen (JNIEnv *env, jobject obj); + +/* JNI initialization functions */ +#if GTK_CAIRO +void cp_gtk_graphics2d_init_jni (void); +#endif +void cp_gtk_graphics_init_jni (void); +void cp_gtk_button_init_jni (void); +void cp_gtk_checkbox_init_jni (void); +void cp_gtk_choice_init_jni (void); +void cp_gtk_component_init_jni (void); +void cp_gtk_list_init_jni (void); +void cp_gtk_menuitem_init_jni (void); +void cp_gtk_scrollbar_init_jni (void); +void cp_gtk_textcomponent_init_jni (void); +void cp_gtk_window_init_jni (void); + +/* Signal connection convience functions */ +void cp_gtk_component_connect_expose_signals (GObject *ptr, jobject *gref); +void cp_gtk_component_connect_focus_signals (GObject *ptr, jobject *gref); +void cp_gtk_component_connect_mouse_signals (GObject *ptr, jobject *gref); +void cp_gtk_component_connect_signals (GObject *ptr, jobject *gref); +void cp_gtk_textcomponent_connect_signals (GObject *ptr, jobject *gref); + +/* Debugging */ +void cp_gtk_print_current_thread (void); + +#define DEBUG_LOCKING 0 + +#if DEBUG_LOCKING +#define gdk_threads_enter() \ +{ \ + g_print ("locking: %s, %d\n", __FILE__, __LINE__); \ + cp_gtk_print_current_thread (); \ + gdk_threads_enter (); \ + g_print ("locked: %s, %d\n", __FILE__, __LINE__); \ + cp_gtk_print_current_thread (); \ +} +#define gdk_threads_leave() \ +{ \ + g_print ("unlocking: %s, %d\n", __FILE__, __LINE__); \ + cp_gtk_print_current_thread (); \ + gdk_threads_leave (); \ + g_print ("unlocked: %s, %d\n", __FILE__, __LINE__); \ + cp_gtk_print_current_thread (); \ +} +#endif + +#endif /* __GTKPEER_H */ diff --git a/libjava/classpath/native/jni/java-io/.cvsignore b/libjava/classpath/native/jni/java-io/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/java-io/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/java-io/Makefile.am b/libjava/classpath/native/jni/java-io/Makefile.am new file mode 100644 index 00000000000..5ed8a1baf4c --- /dev/null +++ b/libjava/classpath/native/jni/java-io/Makefile.am @@ -0,0 +1,13 @@ +pkglib_LTLIBRARIES = libjavaio.la + +libjavaio_la_SOURCES = javaio.h \ + javaio.c \ + java_io_VMFile.c \ + java_io_VMObjectInputStream.c \ + java_io_VMObjectStreamClass.c + +libjavaio_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo + +AM_LDFLAGS = @CLASSPATH_MODULE@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@ diff --git a/libjava/classpath/native/jni/java-io/java_io_VMFile.c b/libjava/classpath/native/jni/java-io/java_io_VMFile.c new file mode 100644 index 00000000000..b32c29477e0 --- /dev/null +++ b/libjava/classpath/native/jni/java-io/java_io_VMFile.c @@ -0,0 +1,734 @@ +/* java_io_VMFile.c - Native methods for java.io.File class + Copyright (C) 1998, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> + +#include <jni.h> +#include <jcl.h> + +#include "target_native.h" +#ifndef WITHOUT_FILESYSTEM +#include "target_native_file.h" +#endif +#include "target_native_math_int.h" + +#include "javaio.h" + +#include "java_io_VMFile.h" + +/*************************************************************************/ + +/* + * Method to create an empty file. + * + * Class: java_io_VMFile + * Method: create + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_create (JNIEnv * env, + jclass clazz __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int fd; + int result; + + filename = JCL_jstring_to_cstring (env, name); + if (filename == NULL) + { + return (0); + } + + TARGET_NATIVE_FILE_OPEN_CREATE (filename, fd, result); + if (result != TARGET_NATIVE_OK) + { + /* XXX ??? NYI */ + if (errno != EEXIST) + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + JCL_free_cstring (env, name, filename); + return (0); + } + TARGET_NATIVE_FILE_CLOSE (fd, result); + + JCL_free_cstring (env, name, filename); + return (1); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method checks to see if we have read permission on a file. + * + * Class: java_io_VMFile + * Method: canRead + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_canRead (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int fd; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (0); + } + + /* The lazy man's way out. We actually do open the file for reading + briefly to verify it can be done */ + TARGET_NATIVE_FILE_OPEN_READ (filename, fd, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + if (result != TARGET_NATIVE_OK) + { + return (0); + } + TARGET_NATIVE_FILE_CLOSE (fd, result); + + return (1); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method checks to see if we have write permission on a file. + * + * Class: java_io_VMFile + * Method: canWrite + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_canWrite (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int fd; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (0); + } + + /* The lazy man's way out. We actually do open the file for writing + briefly to verify it can be done */ + TARGET_NATIVE_FILE_OPEN_READWRITE (filename, fd, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + if (result != TARGET_NATIVE_OK) + { + return (0); + } + TARGET_NATIVE_FILE_CLOSE (fd, result); + + return (1); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method makes a file read only. + * + * Class: java_io_VMFile + * Method: setReadOnly + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_setReadOnly (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (0); + } + + TARGET_NATIVE_FILE_SET_MODE_READONLY (filename, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return ((result == TARGET_NATIVE_OK) ? 1 : 0); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method checks to see if a file exists. + * + * Class: java_io_VMFile + * Method: exists + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_exists (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (0); + } + + TARGET_NATIVE_FILE_EXISTS (filename, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return ((result == TARGET_NATIVE_OK) ? 1 : 0); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method checks to see if a file is a "plain" file; that is, not + * a directory, pipe, etc. + * + * Class: java_io_VMFile + * Method: isFile + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_isFile (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (0); + } + + TARGET_NATIVE_FILE_IS_FILE (filename, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return ((result == TARGET_NATIVE_OK) ? 1 : 0); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method checks to see if a file is a directory or not. + * + * Class: java_io_VMFile + * Method: isDirectory + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_isDirectory (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (0); + } + + TARGET_NATIVE_FILE_IS_DIRECTORY (filename, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return ((result == TARGET_NATIVE_OK) ? 1 : 0); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method returns the length of the file. + * + * Class: java_io_VMFile + * Method: length + * Signature: (Ljava/lang/String;)J + */ + +JNIEXPORT jlong JNICALL +Java_java_io_VMFile_length (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int tmpfd; + jlong length; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (TARGET_NATIVE_MATH_INT_INT64_CONST_0); + } + + /* open file for reading, get size and close file */ + TARGET_NATIVE_FILE_OPEN_READ (filename, tmpfd, result); + if (result != TARGET_NATIVE_OK) + { + return (TARGET_NATIVE_MATH_INT_INT64_CONST_0); + } + TARGET_NATIVE_FILE_SIZE (tmpfd, length, result); + if (result != TARGET_NATIVE_OK) + { + TARGET_NATIVE_FILE_CLOSE (tmpfd, result); + return (TARGET_NATIVE_MATH_INT_INT64_CONST_0); + } + TARGET_NATIVE_FILE_CLOSE (tmpfd, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return ((result == + TARGET_NATIVE_OK) ? length : TARGET_NATIVE_MATH_INT_INT64_CONST_0); +#else /* not WITHOUT_FILESYSTEM */ + return (TARGET_NATIVE_MATH_INT_INT64_CONST_0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method returns the modification date of the file. + * + * Class: java_io_VMFile + * Method: lastModified + * Signature: (Ljava/lang/String;)J + */ + +JNIEXPORT jlong JNICALL +Java_java_io_VMFile_lastModified (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + jlong mtime; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (TARGET_NATIVE_MATH_INT_INT64_CONST_0); + } + + TARGET_NATIVE_FILE_GET_LAST_MODIFIED (filename, mtime, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return ((result == + TARGET_NATIVE_OK) ? mtime : TARGET_NATIVE_MATH_INT_INT64_CONST_0); +#else /* not WITHOUT_FILESYSTEM */ + return (TARGET_NATIVE_MATH_INT_INT64_CONST_0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method sets the modification date of the file. + * + * Class: java_io_VMFile + * Method: setLastModified + * Signature: (Ljava/lang/String;J)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_setLastModified (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name, jlong newtime) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (0); + } + + TARGET_NATIVE_FILE_SET_LAST_MODIFIED (filename, newtime, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return ((result == TARGET_NATIVE_OK) ? 1 : 0); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method deletes a file (actually a name for a file - additional + * links could exist). + * + * Class: java_io_VMFile + * Method: delete + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_delete (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + filename = (*env)->GetStringUTFChars (env, name, 0); + if (filename == NULL) + { + return (0); + } + + TARGET_NATIVE_FILE_DELETE (filename, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + + return ((result == TARGET_NATIVE_OK) ? 1 : 0); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method creates a directory. + * + * Class: java_io_VMFile + * Method: mkdir + * Signature: (Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_mkdir (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *pathname; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + pathname = (*env)->GetStringUTFChars (env, name, 0); + if (pathname == NULL) + { + return (0); + } + + TARGET_NATIVE_FILE_MAKE_DIR (pathname, result); + (*env)->ReleaseStringUTFChars (env, name, pathname); + + return ((result == TARGET_NATIVE_OK) ? 1 : 0); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method renames a (link to a) file. + * + * Class: java_io_VMFile + * Method: renameTo + * Signature: (Ljava/lang/String;Ljava/lang/String;)Z + */ + +JNIEXPORT jboolean JNICALL +Java_java_io_VMFile_renameTo (JNIEnv * env, + jobject obj __attribute__ ((__unused__)), + jstring t, jstring d) +{ +#ifndef WITHOUT_FILESYSTEM + const char *old_filename, *new_filename; + int result; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + old_filename = (*env)->GetStringUTFChars (env, t, 0); + if (old_filename == NULL) + { + return (0); + } + + new_filename = (*env)->GetStringUTFChars (env, d, 0); + if (new_filename == NULL) + { + (*env)->ReleaseStringUTFChars (env, t, old_filename); + return (0); + } + + TARGET_NATIVE_FILE_RENAME (old_filename, new_filename, result); + (*env)->ReleaseStringUTFChars (env, d, new_filename); + (*env)->ReleaseStringUTFChars (env, t, old_filename); + + return ((result == TARGET_NATIVE_OK) ? 1 : 0); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * This method returns an array of String representing all the files + * in a directory except "." and "..". + * + * Class: java_io_VMFile + * Method: list + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ + +JNIEXPORT jobjectArray JNICALL +Java_java_io_VMFile_list (JNIEnv * env, jobject obj + __attribute__ ((__unused__)), jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const int REALLOC_SIZE = 10; + + const char *dirname; + int result; + char **filelist; + void *handle; + const char *filename; + unsigned long int filelist_count, max_filelist_count; + char **tmp_filelist; + jclass str_clazz; + jobjectArray filearray; + unsigned long int i; + jstring str; + + /* Don't use the JCL convert function because it throws an exception + on failure */ + dirname = (*env)->GetStringUTFChars (env, name, 0); + if (dirname == NULL) + { + return (0); + } + + /* open directory for reading */ + TARGET_NATIVE_FILE_OPEN_DIR (dirname, handle, result); + + (*env)->ReleaseStringUTFChars (env, name, dirname); + + if (result != TARGET_NATIVE_OK) + { + return (0); + } + + /* allocate filelist */ + filelist = (char **) JCL_malloc (env, sizeof (char *) * REALLOC_SIZE); + if (filelist == NULL) + { + TARGET_NATIVE_FILE_CLOSE_DIR (handle, result); + return (0); + } + filelist_count = 0; + max_filelist_count = REALLOC_SIZE; + + /* read the files from the directory */ + TARGET_NATIVE_FILE_READ_DIR (handle, filename, result); + while (result == TARGET_NATIVE_OK) + { + if ((strcmp (filename, ".") != 0) && (strcmp (filename, "..") != 0)) + { + /* allocate more memory if necessary */ + if (filelist_count >= max_filelist_count) + { + tmp_filelist = (char **) JCL_realloc (env, + filelist, + (max_filelist_count + + REALLOC_SIZE) * + sizeof (char *)); + if (tmp_filelist == NULL) + { + for (i = 0; i < filelist_count; i++) + { + JCL_free (env, filelist[i]); + } + JCL_free (env, filelist); + TARGET_NATIVE_FILE_CLOSE_DIR (handle, result); + return (0); + } + filelist = tmp_filelist; + max_filelist_count += REALLOC_SIZE; + } + + /* save entry in list (avoid strdup, because it is not ANSI C, thus difficult to port) */ + filelist[filelist_count] = + (char *) JCL_malloc (env, strlen (filename) + 1); + assert (filelist[filelist_count] != NULL); + strcpy (filelist[filelist_count], filename); + filelist_count++; + } + + /* read next directory entry */ + TARGET_NATIVE_FILE_READ_DIR (handle, filename, result); + } + + /* close directory */ + TARGET_NATIVE_FILE_CLOSE_DIR (handle, result); + + /* put the list of files into a Java String array and return it */ + str_clazz = (*env)->FindClass (env, "java/lang/String"); + if (str_clazz == NULL) + { + for (i = 0; i < filelist_count; i++) + { + JCL_free (env, filelist[i]); + } + JCL_free (env, filelist); + return (0); + } + filearray = (*env)->NewObjectArray (env, filelist_count, str_clazz, 0); + if (filearray == NULL) + { + for (i = 0; i < filelist_count; i++) + { + JCL_free (env, filelist[i]); + } + JCL_free (env, filelist); + return (0); + } + for (i = 0; i < filelist_count; i++) + { + /* create new string */ + str = (*env)->NewStringUTF (env, filelist[i]); + if (str == NULL) + { + /* We don't clean up everything here, but if this failed, + something serious happened anyway */ + for (i = 0; i < filelist_count; i++) + { + JCL_free (env, filelist[i]); + } + JCL_free (env, filelist); + return (0); + } + + /* save into array */ + (*env)->SetObjectArrayElement (env, filearray, i, str); + + /* delete local reference */ + (*env)->DeleteLocalRef (env, str); + } + + /* free resources */ + for (i = 0; i < filelist_count; i++) + { + JCL_free (env, filelist[i]); + } + JCL_free (env, filelist); + + return (filearray); +#else /* not WITHOUT_FILESYSTEM */ + return (0); +#endif /* not WITHOUT_FILESYSTEM */ +} diff --git a/libjava/classpath/native/jni/java-io/java_io_VMObjectInputStream.c b/libjava/classpath/native/jni/java-io/java_io_VMObjectInputStream.c new file mode 100644 index 00000000000..d8d80714989 --- /dev/null +++ b/libjava/classpath/native/jni/java-io/java_io_VMObjectInputStream.c @@ -0,0 +1,69 @@ +/* java_io_VMObjectInputStream.c -- Native methods for ObjectInputStream class + Copyright (C) 1998, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +/* TODO: check exceptions */ +/* comments */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <jni.h> +#include <jcl.h> + +#include "java_io_VMObjectInputStream.h" + +/* + * Class: java_io_VMObjectInputStream + * Method: allocateObject + * Signature: (Ljava/lang/Class;)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL +Java_java_io_VMObjectInputStream_allocateObject (JNIEnv * env, + jclass clazz + __attribute__((__unused__)), + jclass target_clazz, + jclass constr_clazz, + jobject constructor) +{ + jobject obj = (*env)->AllocObject (env, target_clazz); + jmethodID id = (*env)->FromReflectedMethod (env, constructor); + + (*env)->CallNonvirtualVoidMethod (env, obj, constr_clazz, id); + + return obj; +} diff --git a/libjava/classpath/native/jni/java-io/java_io_VMObjectStreamClass.c b/libjava/classpath/native/jni/java-io/java_io_VMObjectStreamClass.c new file mode 100644 index 00000000000..8c2556bcf30 --- /dev/null +++ b/libjava/classpath/native/jni/java-io/java_io_VMObjectStreamClass.c @@ -0,0 +1,381 @@ +/* java_io_VMObjectStreamClass.c -- Native methods for VMObjectStreamClass.java + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include <jni.h> +#include <jcl.h> + +#include <stdlib.h> +#include <string.h> + +#include "java_io_VMObjectStreamClass.h" + +/* + * Class: java_io_VMObjectOutputStream + * Method: hasClassInitializer + * Signature: (Ljava/lang/Class;)Z + */ +JNIEXPORT jboolean JNICALL +Java_java_io_VMObjectStreamClass_hasClassInitializer (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), jclass klass) +{ + jmethodID mid = (*env)->GetStaticMethodID (env, klass, "<clinit>", "()V"); + if (mid == NULL) + { + (*env)->ExceptionClear (env); + return JNI_FALSE; + } + return JNI_TRUE; +} + +static void +throwInternalError (JNIEnv * env) +{ + jclass internalErrorClass; + jthrowable previousException, newException; + jmethodID initException, getMessageID, initCauseID; + jstring message; + + internalErrorClass = (*env)->FindClass (env, "java/lang/InternalError"); + /** Just give up if this also fails. */ + if (internalErrorClass == NULL) + return; + + previousException = (*env)->ExceptionOccurred (env); + + if (previousException == NULL) + { + (*env)->ThrowNew (env, internalErrorClass, + "Unknown error raised by the VM"); + return; + } + + initException = (*env)->GetMethodID + (env, internalErrorClass, "<init>", "(Ljava/lang/String;)V"); + getMessageID = (*env)->GetMethodID + (env, (*env)->GetObjectClass (env, previousException), + "getMessage", "()Ljava/lang/String;"); + initCauseID = (*env)->GetMethodID + (env, internalErrorClass, "initCause", "(Ljava/lang/Throwable;)V"); + + message = (*env)->CallObjectMethod (env, previousException, getMessageID); + + newException = (*env)->NewObject (env, internalErrorClass, initException, + message); + (*env)->CallVoidMethod (env, newException, initCauseID, previousException); + + (*env)->ExceptionClear (env); + (*env)->Throw (env, newException); +} + +static jfieldID +getFieldReference (JNIEnv * env, jobject field, const char *type) +{ + jclass classClass; + jclass fieldClass; + jclass declaringClass; + jclass typeClass; + jfieldID fid; + const char *field_name; + const char *type_name; + int type_len; + jmethodID mid; + jstring name; + jstring tname; + int i; + + fieldClass = (*env)->GetObjectClass (env, field); + + mid = + (*env)->GetMethodID (env, fieldClass, "getName", "()Ljava/lang/String;"); + if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL) + { + throwInternalError (env); + return NULL; + } + + name = (*env)->CallObjectMethod (env, field, mid); + field_name = (*env)->GetStringUTFChars (env, name, NULL); + + mid = (*env)->GetMethodID (env, fieldClass, + "getDeclaringClass", "()Ljava/lang/Class;"); + if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL) + { + throwInternalError (env); + return NULL; + } + + declaringClass = (*env)->CallObjectMethod (env, field, mid); + + /* Do we need to find out the exact type descriptor of the field? */ + if (type == NULL) + { + char *the_type; + + mid = (*env)->GetMethodID (env, fieldClass, + "getType", "()Ljava/lang/Class;"); + + if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL) + { + throwInternalError (env); + return NULL; + } + + typeClass = (*env)->CallObjectMethod (env, field, mid); + classClass = (*env)->FindClass (env, "java/lang/Class"); + + mid = (*env)->GetMethodID (env, classClass, + "getName", "()Ljava/lang/String;"); + + if (mid == NULL || (*env)->ExceptionOccurred (env) != NULL) + { + throwInternalError (env); + return NULL; + } + + tname = (*env)->CallObjectMethod (env, typeClass, mid); + type_name = (*env)->GetStringUTFChars (env, tname, NULL); + + /* + * If it isn't an array class then the actual field type descriptor + * starts with 'L', ends with ';' and has '/' instead of '.'. + */ + type_len = strlen ((char *) type_name); + if (type_name[0] != '[') + { + /* XXX - FIXME - should not use dynamic allocation in core lib. */ + the_type = (char *) malloc (type_len + 3); + the_type[0] = 'L'; + the_type[type_len + 1] = ';'; + the_type[type_len + 2] = '\0'; + the_type++; + } + else + { + /* XXX - FIXME - should not use dynamic allocation in core lib. */ + the_type = (char *) malloc (type_len + 1); + the_type[type_len] = '\0'; + } + + for (i = 0; i < type_len; i++) + if (type_name[i] == '.') + the_type[i] = '/'; + else + the_type[i] = type_name[i]; + + if (type_name[0] != '[') + the_type--; + + (*env)->ReleaseStringUTFChars (env, tname, type_name); + fid = (*env)->GetFieldID (env, declaringClass, field_name, the_type); + free (the_type); + } + else + { + type_len = -1; + fid = (*env)->GetFieldID (env, declaringClass, field_name, type); + } + + if (fid == NULL) + { + throwInternalError (env); + return NULL; + } + (*env)->ReleaseStringUTFChars (env, name, field_name); + + return fid; +} + +/* + * Class: java_io_VMObjectOutputStream + * Method: setBooleanNative + * Signature: (Ljava/lang/reflect/Field;Ljava/lang/Object;Z)V + */ +JNIEXPORT void JNICALL +Java_java_io_VMObjectStreamClass_setBooleanNative (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), jobject field, jobject object, jboolean value) +{ + jfieldID fid = getFieldReference (env, field, "Z"); + + if (fid != NULL) + (*env)->SetBooleanField (env, object, fid, value); +} + +/* + * Class: java_io_VMObjectOutputStream + * Method: setCharNative + * Signature: (Ljava/lang/reflect/Field;Ljava/lang/Object;C)V + */ +JNIEXPORT void JNICALL +Java_java_io_VMObjectStreamClass_setCharNative (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), + jobject field, + jobject object, jchar value) +{ + jfieldID fid = getFieldReference (env, field, "C"); + + if (fid != NULL) + (*env)->SetCharField (env, object, fid, value); +} + +/* + * Class: java_io_VMObjectOutputStream + * Method: setByteNative + * Signature: (Ljava/lang/reflect/Field;Ljava/lang/Object;B)V + */ +JNIEXPORT void JNICALL +Java_java_io_VMObjectStreamClass_setByteNative (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), + jobject field, + jobject object, jbyte value) +{ + jfieldID fid = getFieldReference (env, field, "B"); + + if (fid != NULL) + (*env)->SetByteField (env, object, fid, value); +} + + +/* + * Class: java_io_VMObjectOutputStream + * Method: setShortNative + * Signature: (Ljava/lang/reflect/Field;Ljava/lang/Object;S)V + */ +JNIEXPORT void JNICALL +Java_java_io_VMObjectStreamClass_setShortNative (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), + jobject field, + jobject object, jshort value) +{ + jfieldID fid = getFieldReference (env, field, "S"); + + if (fid != NULL) + (*env)->SetShortField (env, object, fid, value); +} + +/* + * Class: java_io_VMObjectOutputStream + * Method: setIntNative + * Signature: (Ljava/lang/reflect/Field;Ljava/lang/Object;I)V + */ +JNIEXPORT void JNICALL +Java_java_io_VMObjectStreamClass_setIntNative (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), + jobject field, + jobject object, jint value) +{ + jfieldID fid = getFieldReference (env, field, "I"); + + if (fid != NULL) + (*env)->SetIntField (env, object, fid, value); +} + + +/* + * Class: java_io_VMObjectOutputStream + * Method: setLongNative + * Signature: (Ljava/lang/reflect/Field;Ljava/lang/Object;J)V + */ +JNIEXPORT void JNICALL +Java_java_io_VMObjectStreamClass_setLongNative (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), + jobject field, + jobject object, jlong value) +{ + jfieldID fid = getFieldReference (env, field, "J"); + + if (fid != NULL) + (*env)->SetLongField (env, object, fid, value); +} + + +/* + * Class: java_io_VMObjectOutputStream + * Method: setFloatNative + * Signature: (Ljava/lang/reflect/Field;Ljava/lang/Object;F)V + */ +JNIEXPORT void JNICALL +Java_java_io_VMObjectStreamClass_setFloatNative (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), + jobject field, + jobject object, jfloat value) +{ + jfieldID fid = getFieldReference (env, field, "F"); + + if (fid != NULL) + (*env)->SetFloatField (env, object, fid, value); +} + +/* + * Class: java_io_VMObjectOutputStream + * Method: setDoubleNative + * Signature: (Ljava/lang/reflect/Field;Ljava/lang/Object;D)V + */ +JNIEXPORT void JNICALL +Java_java_io_VMObjectStreamClass_setDoubleNative (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), jobject field, jobject object, jdouble value) +{ + jfieldID fid = getFieldReference (env, field, "D"); + + if (fid != NULL) + (*env)->SetDoubleField (env, object, fid, value); +} + +/* + * Class: java_io_VMObjectOutputStream + * Method: setObjectNative + * Signature: (Ljava/lang/reflect/Field;Ljava/lang/Object;Ljava/lang/Object;)V + */ +JNIEXPORT void JNICALL +Java_java_io_VMObjectStreamClass_setObjectNative (JNIEnv * env, + jclass vmosklass + __attribute__ ((__unused__)), jobject field, jobject object, jobject value) +{ + jfieldID fid = getFieldReference (env, field, NULL); + + if (fid != NULL) + (*env)->SetObjectField (env, object, fid, value); +} diff --git a/libjava/classpath/native/jni/java-io/javaio.c b/libjava/classpath/native/jni/java-io/javaio.c new file mode 100644 index 00000000000..6dc3de8f041 --- /dev/null +++ b/libjava/classpath/native/jni/java-io/javaio.c @@ -0,0 +1,363 @@ +/* javaio.c - Common java.io native functions + Copyright (C) 1998, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> + +#include <jni.h> +#include <jcl.h> + +#include "target_native.h" +#ifndef WITHOUT_FILESYSTEM +#include "target_native_file.h" +#endif +#include "target_native_math_int.h" + +#include "javaio.h" + +/* + * Function to open a file + */ + +jint +_javaio_open_read (JNIEnv * env, jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int fd; + int result; + + filename = JCL_jstring_to_cstring (env, name); + if (filename == NULL) + return (-1); + + TARGET_NATIVE_FILE_OPEN_READ (filename, fd, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + if (result != TARGET_NATIVE_OK) + { + if (TARGET_NATIVE_LAST_ERROR () == TARGET_NATIVE_ERROR_NO_SUCH_FILE) + JCL_ThrowException (env, + "java/io/FileNotFoundException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + else + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + } + + JCL_free_cstring (env, name, filename); + return (fd); +#else /* not WITHOUT_FILESYSTEM */ + return (-1); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/* + * Function to open a file for reading/writing + */ + +jint +_javaio_open_readwrite (JNIEnv * env, jstring name) +{ +#ifndef WITHOUT_FILESYSTEM + const char *filename; + int fd; + int result; + + filename = JCL_jstring_to_cstring (env, name); + if (filename == NULL) + return (-1); + + TARGET_NATIVE_FILE_OPEN_READWRITE (filename, fd, result); + (*env)->ReleaseStringUTFChars (env, name, filename); + if (result != TARGET_NATIVE_OK) + { + if (TARGET_NATIVE_LAST_ERROR () == TARGET_NATIVE_ERROR_NO_SUCH_FILE) + JCL_ThrowException (env, + "java/io/FileNotFoundException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + else + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + } + + JCL_free_cstring (env, name, filename); + return (fd); +#else /* not WITHOUT_FILESYSTEM */ + return (-1); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * Function to close a file + */ + +void +_javaio_close (JNIEnv * env, jint fd) +{ +#ifndef WITHOUT_FILESYSTEM + int result; + + if (fd != -1) + { + TARGET_NATIVE_FILE_CLOSE (fd, result); + if (result != TARGET_NATIVE_OK) + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + } +#else /* not WITHOUT_FILESYSTEM */ +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * Skips bytes in a file + */ + +jlong +_javaio_skip_bytes (JNIEnv * env, jint fd, jlong num_bytes) +{ +#ifndef WITHOUT_FILESYSTEM + jlong current_offset, new_offset; + int result; + + TARGET_NATIVE_FILE_SEEK_CURRENT (fd, TARGET_NATIVE_MATH_INT_INT64_CONST_0, + current_offset, result); + if (result != TARGET_NATIVE_OK) + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + + TARGET_NATIVE_FILE_SEEK_CURRENT (fd, num_bytes, new_offset, result); + if (result != TARGET_NATIVE_OK) + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + + return (TARGET_NATIVE_MATH_INT_INT64_SUB (new_offset, current_offset)); +#else /* not WITHOUT_FILESYSTEM */ + return (TARGET_NATIVE_MATH_INT_INT64_CONST_0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * Gets the size of the file + */ + +jlong +_javaio_get_file_length (JNIEnv * env, jint fd) +{ +#ifndef WITHOUT_FILESYSTEM + jlong length; + int result; + + TARGET_NATIVE_FILE_SIZE (fd, length, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1); + } + + return (length); +#else /* not WITHOUT_FILESYSTEM */ + return (TARGET_NATIVE_MATH_INT_INT64_CONST_0); +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * Reads data from a file + */ + +jint +_javaio_read (JNIEnv * env, jint fd, jarray buf, jint offset, jint len) +{ +#ifndef WITHOUT_FILESYSTEM + jbyte *bufptr; + int bytesRead; + int result; + + assert (offset >= 0); + assert (len >= 0); + + if (len == 0) + return 0; /* Nothing todo, and GetByteArrayElements() seems undefined. */ + + bufptr = (*env)->GetByteArrayElements (env, buf, JNI_FALSE); + if (bufptr == NULL) + { + JCL_ThrowException (env, "java/io/IOException", + "Internal Error: get byte array fail"); + return (-1); + } + + TARGET_NATIVE_FILE_READ (fd, (bufptr + offset), len, bytesRead, result); + (*env)->ReleaseByteArrayElements (env, buf, bufptr, 0); + if (result != TARGET_NATIVE_OK) + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + + if (bytesRead == 0) + return (-1); + + return (bytesRead); +#else /* not WITHOUT_FILESYSTEM */ + jbyte *bufptr; + int bytesRead; + + assert (offset >= 0); + assert (len >= 0); + + if ((fd == 0) || (fd == 1) || (fd == 2)) + { + if (len == 0) + return 0; /* Nothing todo, and GetByteArrayElements() seems undefined. */ + + bufptr = (*env)->GetByteArrayElements (env, buf, JNI_FALSE); + if (bufptr == NULL) + { + JCL_ThrowException (env, "java/io/IOException", + "Internal Error: get byte array"); + return (-1); + } + + TARGET_NATIVE_FILE_READ (fd, (bufptr + offset), len, bytesRead, result); + (*env)->ReleaseByteArrayElements (env, buf, bufptr, 0); + if (result != TARGET_NATIVE_OK) + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + + if (bytesRead == 0) + return (-1); + + return (bytesRead); + } + else + { + return (-1); + } +#endif /* not WITHOUT_FILESYSTEM */ +} + +/*************************************************************************/ + +/* + * Writes data to a file + */ + +jint +_javaio_write (JNIEnv * env, jint fd, jarray buf, jint offset, jint len) +{ +#ifndef WITHOUT_FILESYSTEM + jbyte *bufptr; + int bytes_written; + int result; + + if (len == 0) + return 0; /* Nothing todo, and GetByteArrayElements() seems undefined. */ + + bufptr = (*env)->GetByteArrayElements (env, buf, 0); + if (bufptr == NULL) + { + JCL_ThrowException (env, "java/io/IOException", + "Internal Error: get byte array"); + return (-1); + } + + TARGET_NATIVE_FILE_WRITE (fd, (bufptr + offset), len, bytes_written, + result); + (*env)->ReleaseByteArrayElements (env, buf, bufptr, 0); + if (result != TARGET_NATIVE_OK) + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + + if (bytes_written == 0) + return (-1); + + return (bytes_written); +#else /* not WITHOUT_FILESYSTEM */ + jbyte *bufptr; + int bytesWritten; + + if ((fd == 0) || (fd == 1) || (fd == 2)) + { + if (len == 0) + return 0; /* Nothing todo, and GetByteArrayElements() seems undefined. */ + + bufptr = (*env)->GetByteArrayElements (env, buf, 0); + if (bufptr == NULL) + { + JCL_ThrowException (env, "java/io/IOException", "Internal Error"); + return (-1); + } + + TARGET_NATIVE_FILE_WRITE (fd, (bufptr + offset), len, bytes_written, + result); + (*env)->ReleaseByteArrayElements (env, buf, bufptr, 0); + + if (bytes_written == -1) + JCL_ThrowException (env, + "java/io/IOException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + + if (bytes_written == 0) + return (-1); + + return (bytes_written); + } + else + { + return (-1); + } +#endif /* not WITHOUT_FILESYSTEM */ +} diff --git a/libjava/classpath/native/jni/java-io/javaio.h b/libjava/classpath/native/jni/java-io/javaio.h new file mode 100644 index 00000000000..2e4a8d1037f --- /dev/null +++ b/libjava/classpath/native/jni/java-io/javaio.h @@ -0,0 +1,58 @@ +/* javaio.h - Declaration for common java.io native functions + Copyright (C) 1998, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#ifndef JAVAIO_H_INCLUDED +#define JAVAIO_H_INCLUDED + +#include <stddef.h> + +/* + * Function Prototypes + */ + +extern jlong _javaio_get_file_length(JNIEnv *, jint); +extern jlong _javaio_skip_bytes(JNIEnv *, jint, jlong); +extern jint _javaio_open(JNIEnv *, jstring, int); +extern jint _javaio_open_read(JNIEnv *, jstring); +extern jint _javaio_open_readwrite(JNIEnv *, jstring); +extern void _javaio_close(JNIEnv *, jint fd); +extern jint _javaio_read(JNIEnv *, jint, jarray, jint, jint); +extern jint _javaio_write(JNIEnv *, jint, jarray, jint, jint); + +#endif /* JAVAIO_H_INCLUDED */ + diff --git a/libjava/classpath/native/jni/java-lang/.cvsignore b/libjava/classpath/native/jni/java-lang/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/java-lang/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/java-lang/Makefile.am b/libjava/classpath/native/jni/java-lang/Makefile.am new file mode 100644 index 00000000000..34ffe00fba7 --- /dev/null +++ b/libjava/classpath/native/jni/java-lang/Makefile.am @@ -0,0 +1,16 @@ +pkglib_LTLIBRARIES = libjavalang.la libjavalangreflect.la + +libjavalang_la_SOURCES = java_lang_VMSystem.c \ + java_lang_VMFloat.c \ + java_lang_VMDouble.c \ + java_lang_Math.c \ + java_lang_VMProcess.c + +libjavalang_la_LIBADD = $(wildcard $(top_builddir)/native/fdlibm/*.lo) \ + $(top_builddir)/native/jni/classpath/jcl.lo + +libjavalangreflect_la_SOURCES = java_lang_reflect_Array.c + +AM_LDFLAGS = @CLASSPATH_MODULE@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ -I$(top_srcdir)/native/fdlibm +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@ diff --git a/libjava/classpath/native/jni/java-lang/java_lang_Math.c b/libjava/classpath/native/jni/java-lang/java_lang_Math.c new file mode 100644 index 00000000000..b4b88a77537 --- /dev/null +++ b/libjava/classpath/native/jni/java-lang/java_lang_Math.c @@ -0,0 +1,161 @@ +/* Math.c - java.lang.Math native functions + Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include <config.h> +#include <java_lang_Math.h> +#include <fdlibm.h> + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_sin + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return sin (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_cos + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return cos (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_tan + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return tan (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_asin + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return asin (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_acos + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return acos (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_atan + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return atan (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_atan2 + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble y, jdouble x) +{ + return atan2 (y, x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_exp + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return exp (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_log + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return log (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_sqrt + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return sqrt (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_pow + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x, jdouble y) +{ + return pow (x, y); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_IEEEremainder + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x, jdouble y) +{ + return remainder (x, y); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_ceil + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return ceil (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_floor + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return floor (x); +} + +JNIEXPORT jdouble JNICALL +Java_java_lang_Math_rint + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble x) +{ + return rint (x); +} diff --git a/libjava/classpath/native/jni/java-lang/java_lang_VMDouble.c b/libjava/classpath/native/jni/java-lang/java_lang_VMDouble.c new file mode 100644 index 00000000000..6b4aed42d27 --- /dev/null +++ b/libjava/classpath/native/jni/java-lang/java_lang_VMDouble.c @@ -0,0 +1,381 @@ +/* VMDouble.c - java.lang.VMDouble native functions + Copyright (C) 1998, 1999, 2001, 2003, 2004i, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "mprec.h" +#include "fdlibm.h" +#include "jcl.h" + +#include "java_lang_VMDouble.h" + +static jclass clsDouble; +static jmethodID isNaNID; +static jdouble NEGATIVE_INFINITY; +static jdouble POSITIVE_INFINITY; +static jdouble NaN; + +/* + * Class: java_lang_VMDouble + * Method: initIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_java_lang_VMDouble_initIDs (JNIEnv * env, jclass cls __attribute__ ((__unused__))) +{ + jfieldID negInfID; + jfieldID posInfID; + jfieldID nanID; + + clsDouble = (*env)->FindClass (env, "java/lang/Double"); + if (clsDouble == NULL) + { + DBG ("unable to get class java.lang.Double\n") return; + } + isNaNID = (*env)->GetStaticMethodID (env, clsDouble, "isNaN", "(D)Z"); + if (isNaNID == NULL) + { + DBG ("unable to determine method id of isNaN\n") return; + } + negInfID = (*env)->GetStaticFieldID (env, clsDouble, "NEGATIVE_INFINITY", "D"); + if (negInfID == NULL) + { + DBG ("unable to determine field id of NEGATIVE_INFINITY\n") return; + } + posInfID = (*env)->GetStaticFieldID (env, clsDouble, "POSITIVE_INFINITY", "D"); + if (posInfID == NULL) + { + DBG ("unable to determine field id of POSITIVE_INFINITY\n") return; + } + nanID = (*env)->GetStaticFieldID (env, clsDouble, "NaN", "D"); + if (posInfID == NULL) + { + DBG ("unable to determine field id of NaN\n") return; + } + POSITIVE_INFINITY = (*env)->GetStaticDoubleField (env, clsDouble, posInfID); + NEGATIVE_INFINITY = (*env)->GetStaticDoubleField (env, clsDouble, negInfID); + NaN = (*env)->GetStaticDoubleField (env, clsDouble, nanID); + +#ifdef DEBUG + fprintf (stderr, "java.lang.Double.initIDs() POSITIVE_INFINITY = %g\n", + POSITIVE_INFINITY); + fprintf (stderr, "java.lang.Double.initIDs() NEGATIVE_INFINITY = %g\n", + NEGATIVE_INFINITY); + fprintf (stderr, "java.lang.Double.initIDs() NaN = %g\n", NaN); +#endif +} + +/* + * Class: java_lang_VMDouble + * Method: doubleToLongBits + * Signature: (D)J + */ +JNIEXPORT jlong JNICALL +Java_java_lang_VMDouble_doubleToLongBits + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble doubleValue) +{ + jvalue val; + jlong e, f; + val.d = doubleValue; + + e = val.j & 0x7ff0000000000000LL; + f = val.j & 0x000fffffffffffffLL; + + if (e == 0x7ff0000000000000LL && f != 0L) + val.j = 0x7ff8000000000000LL; + + return val.j; +} + +/* + * Class: java_lang_VMDouble + * Method: doubleToRawLongBits + * Signature: (D)J + */ +JNIEXPORT jlong JNICALL +Java_java_lang_VMDouble_doubleToRawLongBits + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble doubleValue) +{ + jvalue val; + val.d = doubleValue; + return val.j; +} + +/* + * Class: java_lang_VMDouble + * Method: longBitsToDouble + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL +Java_java_lang_VMDouble_longBitsToDouble + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jlong longValue) +{ + jvalue val; + val.j = longValue; + return val.d; +} + +/* + * Class: java_lang_VMDouble + * Method: toString + * Signature: (DZ)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_java_lang_VMDouble_toString + (JNIEnv * env, jclass cls __attribute__ ((__unused__)), jdouble value, jboolean isFloat) +{ + char buffer[50], result[50]; + int decpt, sign; + char *s, *d; + int i; + +#ifdef DEBUG + fprintf (stderr, "java.lang.VMDouble.toString (%g)\n", value); +#endif + + if ((*env)->CallStaticBooleanMethod (env, clsDouble, isNaNID, value)) + return (*env)->NewStringUTF (env, "NaN"); + + if (value == POSITIVE_INFINITY) + return (*env)->NewStringUTF (env, "Infinity"); + + if (value == NEGATIVE_INFINITY) + return (*env)->NewStringUTF (env, "-Infinity"); + + _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int) isFloat); + + value = fabs (value); + + s = buffer; + d = result; + + if (sign) + *d++ = '-'; + + if ((value >= 1e-3 && value < 1e7) || (value == 0)) + { + if (decpt <= 0) + *d++ = '0'; + else + { + for (i = 0; i < decpt; i++) + if (*s) + *d++ = *s++; + else + *d++ = '0'; + } + + *d++ = '.'; + + if (*s == 0) + { + *d++ = '0'; + decpt++; + } + + while (decpt++ < 0) + *d++ = '0'; + + while (*s) + *d++ = *s++; + + *d = 0; + + return (*env)->NewStringUTF (env, result); + } + + *d++ = *s++; + decpt--; + *d++ = '.'; + + if (*s == 0) + *d++ = '0'; + + while (*s) + *d++ = *s++; + + *d++ = 'E'; + + if (decpt < 0) + { + *d++ = '-'; + decpt = -decpt; + } + + { + char exp[4]; + char *e = exp + sizeof exp; + + *--e = 0; + do + { + *--e = '0' + decpt % 10; + decpt /= 10; + } + while (decpt > 0); + + while (*e) + *d++ = *e++; + } + + *d = 0; + + return (*env)->NewStringUTF (env, result); +} + +/* + * Class: java_lang_VMDouble + * Method: parseDouble + * Signature: (Ljava/lang/String;)D + */ +JNIEXPORT jdouble JNICALL +Java_java_lang_VMDouble_parseDouble + (JNIEnv * env, jclass cls __attribute__ ((__unused__)), jstring str) +{ + jboolean isCopy; + const char *buf; + char *endptr; + jdouble val = 0.0; + + if (str == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", "null"); + return val; + } + + buf = (char *) (*env)->GetStringUTFChars (env, str, &isCopy); + if (buf == NULL) + { + /* OutOfMemoryError already thrown */ + } + else + { + const char *p = buf, *end, *last_non_ws, *temp; + int ok = 1; + +#ifdef DEBUG + fprintf (stderr, "java.lang.VMDouble.parseDouble (%s)\n", buf); +#endif + + /* Trim the buffer, similar to String.trim(). First the leading + characters. */ + while (*p && *p <= ' ') + ++p; + + /* Find the last non-whitespace character. This method is safe + even with multi-byte UTF-8 characters. */ + end = p; + last_non_ws = NULL; + while (*end) + { + if (*end > ' ') + last_non_ws = end; + ++end; + } + + if (last_non_ws == NULL) + last_non_ws = p + strlen (p); + else + { + /* Skip past the last non-whitespace character. */ + ++last_non_ws; + } + + /* Check for infinity and NaN */ + temp = p; + if (temp[0] == '+' || temp[0] == '-') + temp++; + if (strncmp ("Infinity", temp, (size_t) 8) == 0) + { + if (p[0] == '-') + return NEGATIVE_INFINITY; + return POSITIVE_INFINITY; + } + if (strncmp ("NaN", temp, (size_t) 3) == 0) + return NaN; + + /* Skip a trailing `f' or `d'. */ + if (last_non_ws > p + && (last_non_ws[-1] == 'f' + || last_non_ws[-1] == 'F' + || last_non_ws[-1] == 'd' || last_non_ws[-1] == 'D')) + --last_non_ws; + + if (last_non_ws > p) + { + struct _Jv_reent reent; + memset (&reent, 0, sizeof reent); + +#ifdef KISSME_LINUX_USER + /* FIXME: The libc strtod may not be reliable. */ + val = strtod (p, &endptr); +#else + val = _strtod_r (&reent, p, &endptr); +#endif + +#ifdef DEBUG + fprintf (stderr, "java.lang.VMDouble.parseDouble val = %g\n", val); + fprintf (stderr, "java.lang.VMDouble.parseDouble %i != %i ???\n", + endptr, last_non_ws); +#endif + if (endptr != last_non_ws) + ok = 0; + } + else + ok = 0; + + if (!ok) + { + val = 0.0; + JCL_ThrowException (env, + "java/lang/NumberFormatException", + "unable to parse double"); + } + + (*env)->ReleaseStringUTFChars (env, str, buf); + } + + return val; +} diff --git a/libjava/classpath/native/jni/java-lang/java_lang_VMFloat.c b/libjava/classpath/native/jni/java-lang/java_lang_VMFloat.c new file mode 100644 index 00000000000..7bff629fc89 --- /dev/null +++ b/libjava/classpath/native/jni/java-lang/java_lang_VMFloat.c @@ -0,0 +1,93 @@ +/* VMFloat.c - java.lang.VMFloat native functions + Copyright (C) 1998, 1999, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include <config.h> + +#include "java_lang_VMFloat.h" + +/* + * Class: java_lang_VMFloat + * Method: floatToIntBits + * Signature: (F)I + */ +JNIEXPORT jint JNICALL +Java_java_lang_VMFloat_floatToIntBits + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jfloat value) +{ + jvalue u; + jint e, f; + u.f = value; + e = u.i & 0x7f800000; + f = u.i & 0x007fffff; + + if (e == 0x7f800000 && f != 0) + u.i = 0x7fc00000; + + return u.i; +} + +/* + * Class: java_lang_VMFloat + * Method: floatToRawIntBits + * Signature: (F)I + */ +JNIEXPORT jint JNICALL +Java_java_lang_VMFloat_floatToRawIntBits + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jfloat value) +{ + jvalue u; + u.f = value; + return u.i; +} + +/* + * Class: java_lang_VMFloat + * Method: intBitsToFloat + * Signature: (I)F + */ +JNIEXPORT jfloat JNICALL +Java_java_lang_VMFloat_intBitsToFloat + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jint bits) +{ + jvalue u; + u.i = bits; + return u.f; +} diff --git a/libjava/classpath/native/jni/java-lang/java_lang_VMProcess.c b/libjava/classpath/native/jni/java-lang/java_lang_VMProcess.c new file mode 100644 index 00000000000..c1090ed3736 --- /dev/null +++ b/libjava/classpath/native/jni/java-lang/java_lang_VMProcess.c @@ -0,0 +1,494 @@ +/* java_lang_VMProcess.c -- native code for java.lang.VMProcess + Copyright (C) 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include <config.h> + +#include "java_lang_VMProcess.h" +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> + +#include "target_native.h" +#include "target_native_misc.h" + +/* Internal functions */ +static char *copy_string (JNIEnv * env, jobject string); +static char *copy_elem (JNIEnv * env, jobject stringArray, jint i); + +/* Some O/S's don't declare 'environ' */ +#if HAVE_CRT_EXTERNS_H +/* Darwin does not have a variable named environ + but has a function which you can get the environ + variable with. */ +#include <crt_externs.h> +#define environ (*_NSGetEnviron()) +#else +extern char **environ; +#endif /* HAVE_CRT_EXTERNS_H */ + +/* + * Internal helper function to copy a String in UTF-8 format. + */ +static char * +copy_string (JNIEnv * env, jobject string) +{ + char errbuf[64]; + const char *utf; + jclass clazz; + char *copy; + + /* Check for null */ + if (string == NULL) + { + clazz = (*env)->FindClass (env, "java/lang/NullPointerException"); + if ((*env)->ExceptionOccurred (env)) + return NULL; + (*env)->ThrowNew (env, clazz, NULL); + (*env)->DeleteLocalRef (env, clazz); + return NULL; + } + + /* Extract UTF-8 */ + utf = (*env)->GetStringUTFChars (env, string, NULL); + if ((*env)->ExceptionOccurred (env)) + return NULL; + + /* Copy it */ + if ((copy = strdup (utf)) == NULL) + { + TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf, sizeof (errbuf), + "strdup: %s", strerror (errno)); + clazz = (*env)->FindClass (env, "java/lang/InternalError"); + if ((*env)->ExceptionOccurred (env)) + return NULL; + (*env)->ThrowNew (env, clazz, errbuf); + (*env)->DeleteLocalRef (env, clazz); + } + + /* Done */ + (*env)->ReleaseStringUTFChars (env, string, utf); + return copy; +} + +/* + * Internal helper function to copy a String[] element in UTF-8 format. + */ +static char * +copy_elem (JNIEnv * env, jobject stringArray, jint i) +{ + jobject elem; + char *rtn; + + elem = (*env)->GetObjectArrayElement (env, stringArray, i); + if ((*env)->ExceptionOccurred (env)) + return NULL; + if ((rtn = copy_string (env, elem)) == NULL) + return NULL; + (*env)->DeleteLocalRef (env, elem); + return rtn; +} + +/* + * private final native void nativeSpawn(String[], String[], File) + * throws java/io/IOException + */ +JNIEXPORT void JNICALL +Java_java_lang_VMProcess_nativeSpawn (JNIEnv * env, jobject this, + jobjectArray cmdArray, + jobjectArray envArray, jobject dirFile) +{ + int fds[3][2] = { {-1, -1}, {-1, -1}, {-1, -1} }; + jobject streams[3] = { NULL, NULL, NULL }; + jobject dirString = NULL; + char **newEnviron = NULL; + jsize cmdArrayLen = 0; + jsize envArrayLen = 0; + char **strings = NULL; + int num_strings = 0; + char *dir = NULL; + pid_t pid = -1; + char errbuf[64]; + jmethodID method; + jclass clazz; + int i; + + /* Check for null */ + if (cmdArray == NULL) + goto null_pointer_exception; + + /* Invoke dirFile.getPath() */ + if (dirFile != NULL) + { + clazz = (*env)->FindClass (env, "java/io/File"); + if ((*env)->ExceptionOccurred (env)) + return; + method = (*env)->GetMethodID (env, + clazz, "getPath", "()Ljava/lang/String;"); + if ((*env)->ExceptionOccurred (env)) + return; + dirString = (*env)->CallObjectMethod (env, dirFile, method); + if ((*env)->ExceptionOccurred (env)) + return; + (*env)->DeleteLocalRef (env, clazz); + } + + /* + * Allocate array of C strings. We put all the C strings we need to + * handle the command parameters, the new environment, and the new + * directory into a single array for simplicity of (de)allocation. + */ + cmdArrayLen = (*env)->GetArrayLength (env, cmdArray); + if (cmdArrayLen == 0) + goto null_pointer_exception; + if (envArray != NULL) + envArrayLen = (*env)->GetArrayLength (env, envArray); + if ((strings = malloc (((cmdArrayLen + 1) + + (envArray != NULL ? envArrayLen + 1 : 0) + + (dirString != + NULL ? 1 : 0)) * sizeof (*strings))) == NULL) + { + TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf, + sizeof (errbuf), "malloc: %s", + strerror (errno)); + goto out_of_memory; + } + + /* Extract C strings from the various String parameters */ + for (i = 0; i < cmdArrayLen; i++) + { + if ((strings[num_strings++] = copy_elem (env, cmdArray, i)) == NULL) + goto done; + } + strings[num_strings++] = NULL; /* terminate array with NULL */ + if (envArray != NULL) + { + newEnviron = strings + num_strings; + for (i = 0; i < envArrayLen; i++) + { + if ((strings[num_strings++] = copy_elem (env, envArray, i)) == NULL) + goto done; + } + strings[num_strings++] = NULL; /* terminate array with NULL */ + } + if (dirString != NULL) + { + if ((dir = copy_string (env, dirString)) == NULL) + goto done; + strings[num_strings++] = dir; + } + + /* Create inter-process pipes */ + for (i = 0; i < 3; i++) + { + if (pipe (fds[i]) == -1) + { + TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf, + sizeof (errbuf), "pipe: %s", + strerror (errno)); + goto system_error; + } + } + + /* Set close-on-exec flag for parent's ends of pipes */ + (void) fcntl (fds[0][1], F_SETFD, 1); + (void) fcntl (fds[1][0], F_SETFD, 1); + (void) fcntl (fds[2][0], F_SETFD, 1); + + /* Fork into parent and child processes */ + if ((pid = fork ()) == (pid_t) - 1) + { + TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf, + sizeof (errbuf), "fork: %s", + strerror (errno)); + goto system_error; + } + + /* Child becomes the new process */ + if (pid == 0) + { + char *const path = strings[0]; + + /* Move file descriptors to standard locations */ + if (fds[0][0] != 0) + { + if (dup2 (fds[0][0], 0) == -1) + { + fprintf (stderr, "dup2: %s", strerror (errno)); + exit (127); + } + close (fds[0][0]); + } + if (fds[1][1] != 1) + { + if (dup2 (fds[1][1], 1) == -1) + { + fprintf (stderr, "dup2: %s", strerror (errno)); + exit (127); + } + close (fds[1][1]); + } + if (fds[2][1] != 2) + { + if (dup2 (fds[2][1], 2) == -1) + { + fprintf (stderr, "dup2: %s", strerror (errno)); + exit (127); + } + close (fds[2][1]); + } + + /* Change into destination directory */ + if (dir != NULL && chdir (dir) == -1) + { + fprintf (stderr, "%s: %s", dir, strerror (errno)); + exit (127); + } + + /* Make argv[0] last component of executable pathname */ + /* XXX should use "file.separator" property here XXX */ + for (i = strlen (path); i > 0 && path[i - 1] != '/'; i--); + strings[0] = path + i; + + /* Set new environment */ + if (newEnviron != NULL) + environ = newEnviron; + + /* Execute new program (this will close the parent end of the pipes) */ + execvp (path, strings); + + /* Failed */ + fprintf (stderr, "%s: %s", path, strerror (errno)); + exit (127); + } + + /* Create Input/OutputStream objects around parent file descriptors */ + clazz = (*env)->FindClass (env, "gnu/java/nio/channels/FileChannelImpl"); + if ((*env)->ExceptionOccurred (env)) + goto done; + method = (*env)->GetMethodID (env, clazz, "<init>", "(II)V"); + if ((*env)->ExceptionOccurred (env)) + goto done; + for (i = 0; i < 3; i++) + { + /* Mode is WRITE (2) for in and READ (1) for out and err. */ + const int fd = fds[i][i == 0]; + const int mode = (i == 0) ? 2 : 1; + jclass sclazz; + jmethodID smethod; + + jobject channel = (*env)->NewObject (env, clazz, method, fd, mode); + if ((*env)->ExceptionOccurred (env)) + goto done; + + if (mode == 2) + sclazz = (*env)->FindClass (env, "java/io/FileOutputStream"); + else + sclazz = (*env)->FindClass (env, "java/io/FileInputStream"); + if ((*env)->ExceptionOccurred (env)) + goto done; + + smethod = (*env)->GetMethodID (env, sclazz, "<init>", + "(Lgnu/java/nio/channels/FileChannelImpl;)V"); + if ((*env)->ExceptionOccurred (env)) + goto done; + + streams[i] = (*env)->NewObject (env, sclazz, smethod, channel); + if ((*env)->ExceptionOccurred (env)) + goto done; + + (*env)->DeleteLocalRef (env, sclazz); + } + (*env)->DeleteLocalRef (env, clazz); + + /* Invoke VMProcess.setProcessInfo() to update VMProcess object */ + method = (*env)->GetMethodID (env, + (*env)->GetObjectClass (env, this), + "setProcessInfo", + "(Ljava/io/OutputStream;Ljava/io/InputStream;Ljava/io/InputStream;J)V"); + if ((*env)->ExceptionOccurred (env)) + goto done; + (*env)->CallVoidMethod (env, this, method, + streams[0], streams[1], streams[2], (jlong) pid); + if ((*env)->ExceptionOccurred (env)) + goto done; + (*env)->DeleteLocalRef (env, clazz); + +done: + /* + * We get here in both the success and failure cases in the + * parent process. Our goal is to clean up the mess we created. + */ + + /* Close child's ends of pipes */ + for (i = 0; i < 3; i++) + { + const int fd = fds[i][i != 0]; + + if (fd != -1) + close (fd); + } + + /* + * Close parent's ends of pipes if Input/OutputStreams never got created. + * This can only happen in a failure case. If a Stream object + * was created for a file descriptor, we don't close it because it + * will get closed when the Stream object is finalized. + */ + for (i = 0; i < 3; i++) + { + const int fd = fds[i][i == 0]; + + if (fd != -1 && streams[i] == NULL) + close (fd); + } + + /* Free C strings */ + while (num_strings > 0) + free (strings[--num_strings]); + free (strings); + + /* Done */ + return; + +null_pointer_exception: + clazz = (*env)->FindClass (env, "java/lang/NullPointerException"); + if ((*env)->ExceptionOccurred (env)) + goto done; + (*env)->ThrowNew (env, clazz, NULL); + (*env)->DeleteLocalRef (env, clazz); + goto done; + +out_of_memory: + clazz = (*env)->FindClass (env, "java/lang/InternalError"); + if ((*env)->ExceptionOccurred (env)) + goto done; + (*env)->ThrowNew (env, clazz, errbuf); + (*env)->DeleteLocalRef (env, clazz); + goto done; + +system_error: + clazz = (*env)->FindClass (env, "java/io/IOException"); + if ((*env)->ExceptionOccurred (env)) + goto done; + (*env)->ThrowNew (env, clazz, errbuf); + (*env)->DeleteLocalRef (env, clazz); + goto done; +} + +/* + * private static final native boolean nativeReap() + */ +JNIEXPORT jboolean JNICALL +Java_java_lang_VMProcess_nativeReap (JNIEnv * env, jclass clazz) +{ + char ebuf[64]; + jfieldID field; + jint status; + pid_t pid; + + /* Try to reap a child process, but don't block */ + if ((pid = waitpid ((pid_t) - 1, &status, WNOHANG)) == 0) + return JNI_FALSE; + + /* Check result from waitpid() */ + if (pid == (pid_t) - 1) + { + if (errno == ECHILD || errno == EINTR) + return JNI_FALSE; + TARGET_NATIVE_MISC_FORMAT_STRING2 (ebuf, + sizeof (ebuf), "waitpid(%ld): %s", + (long) pid, strerror (errno)); + clazz = (*env)->FindClass (env, "java/lang/InternalError"); + if ((*env)->ExceptionOccurred (env)) + return JNI_FALSE; + (*env)->ThrowNew (env, clazz, ebuf); + (*env)->DeleteLocalRef (env, clazz); + return JNI_FALSE; + } + + /* Get exit code; for signal termination return negative signal value XXX */ + if (WIFEXITED (status)) + status = (jint) (jbyte) WEXITSTATUS (status); + else if (WIFSIGNALED (status)) + status = -(jint) WTERMSIG (status); + else + return JNI_FALSE; /* process merely stopped; ignore */ + + /* Return process pid and exit status */ + field = (*env)->GetStaticFieldID (env, clazz, "reapedPid", "J"); + if ((*env)->ExceptionOccurred (env)) + return JNI_FALSE; + (*env)->SetStaticLongField (env, clazz, field, (jlong) pid); + if ((*env)->ExceptionOccurred (env)) + return JNI_FALSE; + field = (*env)->GetStaticFieldID (env, clazz, "reapedExitValue", "I"); + if ((*env)->ExceptionOccurred (env)) + return JNI_FALSE; + (*env)->SetStaticIntField (env, clazz, field, status); + if ((*env)->ExceptionOccurred (env)) + return JNI_FALSE; + + /* Done */ + return JNI_TRUE; +} + +/* + * private static final native void nativeKill(long) + */ +JNIEXPORT void JNICALL +Java_java_lang_VMProcess_nativeKill (JNIEnv * env, jclass clazz, jlong pid) +{ + char ebuf[64]; + + if (kill ((pid_t) pid, SIGKILL) == -1) + { + TARGET_NATIVE_MISC_FORMAT_STRING2 (ebuf, + sizeof (ebuf), "kill(%ld): %s", + (long) pid, strerror (errno)); + clazz = (*env)->FindClass (env, "java/lang/InternalError"); + if ((*env)->ExceptionOccurred (env)) + return; + (*env)->ThrowNew (env, clazz, ebuf); + (*env)->DeleteLocalRef (env, clazz); + } +} diff --git a/libjava/classpath/native/jni/java-lang/java_lang_VMSystem.c b/libjava/classpath/native/jni/java-lang/java_lang_VMSystem.c new file mode 100644 index 00000000000..0edbb2e965a --- /dev/null +++ b/libjava/classpath/native/jni/java-lang/java_lang_VMSystem.c @@ -0,0 +1,156 @@ +/* System.c -- native code for java.lang.System + Copyright (C) 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "java_lang_VMSystem.h" + +#include <jcl.h> + +#include <sys/time.h> +#include <stdlib.h> + +/* + * Class: java_lang_VMSystem + * Method: setIn0 + * Signature: (Ljava/io/InputStream;)V + */ +JNIEXPORT void JNICALL +Java_java_lang_VMSystem_setIn (JNIEnv * env, + jclass thisClass __attribute__ ((__unused__)), + jobject obj) +{ + jclass cls; + jfieldID field; + + cls = JCL_FindClass (env, "java/lang/System"); + if (!cls) + return; + + field = (*env)->GetStaticFieldID (env, cls, "in", "Ljava/io/InputStream;"); + if (!field) + return; + (*env)->SetStaticObjectField (env, cls, field, obj); +} + +/* + * Class: java_lang_VMSystem + * Method: setOut0 + * Signature: (Ljava/io/PrintStream;)V + */ +JNIEXPORT void JNICALL +Java_java_lang_VMSystem_setOut (JNIEnv * env, + jclass thisClass __attribute__ ((__unused__)), + jobject obj) +{ + jclass cls; + jfieldID field; + + cls = JCL_FindClass (env, "java/lang/System"); + if (!cls) + return; + + field = (*env)->GetStaticFieldID (env, cls, "out", "Ljava/io/PrintStream;"); + if (!field) + return; + (*env)->SetStaticObjectField (env, cls, field, obj); +} + +/* + * Class: java_lang_VMSystem + * Method: setErr0 + * Signature: (Ljava/io/PrintStream;)V + */ +JNIEXPORT void JNICALL +Java_java_lang_VMSystem_setErr (JNIEnv * env, + jclass thisClass __attribute__ ((__unused__)), + jobject obj) +{ + jclass cls; + jfieldID field; + + cls = JCL_FindClass (env, "java/lang/System"); + if (!cls) + return; + + field = (*env)->GetStaticFieldID (env, cls, "err", "Ljava/io/PrintStream;"); + if (!field) + return; + (*env)->SetStaticObjectField (env, cls, field, obj); +} + +/* + * Class: java_lang_VMSystem + * Method: currentTimeMillis + * Signature: ()J + */ +JNIEXPORT jlong JNICALL +Java_java_lang_VMSystem_currentTimeMillis + (JNIEnv * env __attribute__ ((__unused__)), + jclass thisClass __attribute__ ((__unused__))) +{ + /* Note: this implementation copied directly from Japhar's, by Chris Toshok. */ + jlong result; + struct timeval tp; + + if (gettimeofday (&tp, NULL) == -1) + (*env)->FatalError (env, "gettimeofday call failed."); + + result = (jlong) tp.tv_sec; + result *= 1000; + result += (tp.tv_usec / 1000); + + return result; +} + +JNIEXPORT jstring JNICALL +Java_java_lang_VMSystem_getenv (JNIEnv * env, + jclass klass __attribute__ ((__unused__)), + jstring jname) +{ + const char *cname; + const char *envname; + + cname = JCL_jstring_to_cstring (env, jname); + if (cname == NULL) + return NULL; + + envname = getenv (cname); + if (envname == NULL) + return NULL; + + JCL_free_cstring (env, jname, cname); + return (*env)->NewStringUTF (env, envname); +} diff --git a/libjava/classpath/native/jni/java-lang/java_lang_reflect_Array.c b/libjava/classpath/native/jni/java-lang/java_lang_reflect_Array.c new file mode 100644 index 00000000000..0bd23c16ffc --- /dev/null +++ b/libjava/classpath/native/jni/java-lang/java_lang_reflect_Array.c @@ -0,0 +1,61 @@ +/* java.lang.reflect.Array native functions + Copyright (C) 1998, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* + * java.lang.reflect.Array native functions. + * Author: John Keiser + * Version: 1.1.0 + * Date: 2 Jun 1998 + */ + +#include <stddef.h> + +#include "java_lang_reflect_Array.h" + +/* + * Class: java_lang_reflect_Array + * Method: createObjectArray + * Signature: (Ljava/lang/Class;I)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL +Java_java_lang_reflect_Array_createObjectArray + (JNIEnv * env, + jclass thisClass __attribute__ ((__unused__)), + jclass arrayType, jint arrayLength) +{ + return (jobject) (*env)->NewObjectArray (env, arrayLength, arrayType, NULL); +} diff --git a/libjava/classpath/native/jni/java-net/.cvsignore b/libjava/classpath/native/jni/java-net/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/java-net/Makefile.am b/libjava/classpath/native/jni/java-net/Makefile.am new file mode 100644 index 00000000000..3e8c863a9a9 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/Makefile.am @@ -0,0 +1,14 @@ +pkglib_LTLIBRARIES = libjavanet.la + +libjavanet_la_SOURCES = javanet.c \ + javanet.h \ + java_net_VMInetAddress.c \ + java_net_VMNetworkInterface.c \ + gnu_java_net_PlainDatagramSocketImpl.c \ + gnu_java_net_PlainSocketImpl.c + +libjavanet_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo + +AM_LDFLAGS = @CLASSPATH_MODULE@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@ diff --git a/libjava/classpath/native/jni/java-net/gnu_java_net_PlainDatagramSocketImpl.c b/libjava/classpath/native/jni/java-net/gnu_java_net_PlainDatagramSocketImpl.c new file mode 100644 index 00000000000..5bc284f6426 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/gnu_java_net_PlainDatagramSocketImpl.c @@ -0,0 +1,452 @@ +/* PlainDatagramSocketImpl.c - Native methods for PlainDatagramSocketImpl class + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "javanet.h" + +#include "target_native.h" +#ifndef WITHOUT_NETWORK +#include "target_native_network.h" +#endif /* WITHOUT_NETWORK */ + +#include "gnu_java_net_PlainDatagramSocketImpl.h" + +/* + * Note that most of the functions in this module simply redirect to another + * internal function. Why? Because many of these functions are shared + * with PlainSocketImpl. + */ + +/*************************************************************************/ + +/* + * Creates a new datagram socket + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_create (JNIEnv * env, jobject obj) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + _javanet_create (env, obj, 0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Close the socket. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_close (JNIEnv * env, jobject obj) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + _javanet_close (env, obj, 0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method binds the specified address to the specified local port. + * Note that we have to set the local address and local port public instance + * variables. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_bind (JNIEnv * env, jobject obj, + jint port, jobject addr) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + _javanet_bind (env, obj, addr, port, 0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method sets the specified option for a socket + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_setOption (JNIEnv * env, + jobject obj, + jint option_id, + jobject val) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + _javanet_set_option (env, obj, option_id, val); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method sets the specified option for a socket + */ +JNIEXPORT jobject JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_getOption (JNIEnv * env, + jobject obj, + jint option_id) +{ + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + return (_javanet_get_option (env, obj, option_id)); +#else /* not WITHOUT_NETWORK */ + return NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Reads a buffer from a remote host + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_receive0 (JNIEnv * env, jobject obj, + jobject packet) +{ +#ifndef WITHOUT_NETWORK + int addr, port, bytes_read; + unsigned int maxlen, offset; + jclass cls, addr_cls; + jfieldID fid; + jmethodID mid; + jarray arr; + unsigned char octets[4]; + char ip_str[16]; + jobject ip_str_obj, addr_obj; + + assert (env != NULL); + assert ((*env) != NULL); + + addr = 0; + port = 0; + maxlen = 0; + offset = 0; + bytes_read = 0; + + if (packet == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", + "Null datagram packet"); + return; + } + + /* Get the buffer from the packet */ + cls = (*env)->GetObjectClass (env, packet); + if (cls == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error"); + return; + } + + mid = (*env)->GetMethodID (env, cls, "getData", "()[B"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: getData"); + return; + } + + arr = (*env)->CallObjectMethod (env, packet, mid); + if ((*env)->ExceptionOccurred (env)) + return; + if (arr == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: call getData"); + return; + } + + /* Now get the offset from the packet */ + mid = (*env)->GetMethodID (env, cls, "getOffset", "()I"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: getOffset"); + return; + } + + offset = (*env)->CallIntMethod (env, packet, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.receive(): Got the offset\n"); + + /* Now get the maximal available length from the packet */ + fid = (*env)->GetFieldID (env, cls, "maxlen", "I"); + if (fid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: maxlen"); + return; + } + + maxlen = (*env)->GetIntField (env, packet, fid); + if ((*env)->ExceptionOccurred (env)) + return; + + /* Receive the packet */ + /* should we try some sort of validation on the length? */ + bytes_read = + _javanet_recvfrom (env, obj, arr, offset, maxlen, &addr, &port); + if ((*env)->ExceptionOccurred (env)) + return; + if (bytes_read == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: receive"); + return; + } + + DBG ("PlainDatagramSocketImpl.receive(): Received packet\n"); + + /* Store the address */ + TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (addr, + octets[0], + octets[1], + octets[2], octets[3]); + sprintf (ip_str, "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]); + ip_str_obj = (*env)->NewStringUTF (env, ip_str); + if (ip_str_obj == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: new string"); + return; + } + + addr_cls = (*env)->FindClass (env, "java/net/InetAddress"); + if (addr_cls == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: InetAddress class"); + return; + } + DBG ("PlainDatagramSocketImpl.receive(): Found InetAddress class\n"); + + mid = (*env)->GetStaticMethodID (env, addr_cls, "getByName", + "(Ljava/lang/String;)Ljava/net/InetAddress;"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal Error"); + return; + } + DBG + ("PlainDatagramSocketImpl.receive(): Found InetAddress.getByName method\n"); + + addr_obj = (*env)->CallStaticObjectMethod (env, addr_cls, mid, ip_str_obj); + if ((*env)->ExceptionOccurred (env)) + return; + + mid = (*env)->GetMethodID (env, cls, "setAddress", + "(Ljava/net/InetAddress;)V"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: setAddress"); + return; + } + + (*env)->CallVoidMethod (env, packet, mid, addr_obj); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.receive(): Stored the address\n"); + + /* Store the port */ + mid = (*env)->GetMethodID (env, cls, "setPort", "(I)V"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: setPort"); + return; + } + + (*env)->CallVoidMethod (env, packet, mid, port); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.receive(): Stored the port\n"); + + /* Store back the length */ + fid = (*env)->GetFieldID (env, cls, "length", "I"); + if (fid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error: length"); + return; + } + + (*env)->SetIntField (env, packet, fid, bytes_read); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.receive(): Stored the length\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Writes a buffer to the remote host + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_sendto (JNIEnv * env, jobject obj, + jobject addr, jint port, + jarray buf, jint offset, + jint len) +{ +#ifndef WITHOUT_NETWORK + jint netAddress; + + assert (env != NULL); + assert ((*env) != NULL); + + netAddress = _javanet_get_netaddr (env, addr); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.sendto(): have addr\n"); + + _javanet_sendto (env, obj, buf, offset, len, netAddress, port); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.sendto(): finished\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Joins a multicast group + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_join (JNIEnv * env, jobject obj, + jobject addr) +{ +#ifndef WITHOUT_NETWORK + jint netAddress; + int fd; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + netAddress = _javanet_get_netaddr (env, addr); + if ((*env)->ExceptionOccurred (env)) + return; + + fd = _javanet_get_int_field (env, obj, "native_fd"); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.join(): have native fd\n"); + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_ADD_MEMBERSHIP (fd, netAddress, + result); + + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + DBG ("PlainDatagramSocketImpl.join(): finished\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Leaves a multicast group + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainDatagramSocketImpl_leave (JNIEnv * env, jobject obj, + jobject addr) +{ +#ifndef WITHOUT_NETWORK + jint netAddress; + int fd; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + netAddress = _javanet_get_netaddr (env, addr); + if ((*env)->ExceptionOccurred (env)) + return; + + fd = _javanet_get_int_field (env, obj, "native_fd"); + if ((*env)->ExceptionOccurred (env)) + return; + + DBG ("PlainDatagramSocketImpl.leave(): have native fd\n"); + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_DROP_MEMBERSHIP (fd, netAddress, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + DBG ("PlainDatagramSocketImpl.leave(): finished\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} diff --git a/libjava/classpath/native/jni/java-net/gnu_java_net_PlainSocketImpl.c b/libjava/classpath/native/jni/java-net/gnu_java_net_PlainSocketImpl.c new file mode 100644 index 00000000000..a5261514dce --- /dev/null +++ b/libjava/classpath/native/jni/java-net/gnu_java_net_PlainSocketImpl.c @@ -0,0 +1,320 @@ +/* PlainSocketImpl.c - Native methods for PlainSocketImpl class + Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "javanet.h" + +#include "target_native.h" +#ifndef WITHOUT_NETWORK +#include "target_native_network.h" +#endif /* WITHOUT_NETWORK */ + +#include "gnu_java_net_PlainSocketImpl.h" + +/* + * Note that the functions in this module simply redirect to another + * internal function. Why? Because many of these functions are shared + * with PlainDatagramSocketImpl. The unshared ones were done the same + * way for consistency. + */ + +/*************************************************************************/ + +/* + * Creates a new stream or datagram socket + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_create (JNIEnv * env, jobject this, + jboolean stream) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_create (env, this, stream); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Close the socket. Any underlying streams will be closed by this + * action as well. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_close (JNIEnv * env, jobject this) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_close (env, this, 1); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Connects to the specified destination. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_connect (JNIEnv * env, jobject this, + jobject addr, jint port) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_connect (env, this, addr, port); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method binds the specified address to the specified local port. + * Note that we have to set the local address and local port public instance + * variables. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_bind (JNIEnv * env, jobject this, + jobject addr, jint port) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_bind (env, this, addr, port, 1); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Starts listening on a socket with the specified number of pending + * connections allowed. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_listen (JNIEnv * env, jobject this, + jint queuelen) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_listen (env, this, queuelen); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Accepts a new connection and assigns it to the passed in SocketImpl + * object. Note that we assume this is a PlainSocketImpl just like us. + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_accept (JNIEnv * env, jobject this, + jobject impl) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_accept (env, this, impl); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +JNIEXPORT jint JNICALL +Java_gnu_java_net_PlainSocketImpl_available (JNIEnv * env, jobject this) +{ +#ifndef WITHOUT_NETWORK + jclass cls; + jfieldID fid; + int fd; + int bytesAvailable; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + cls = (*env)->GetObjectClass (env, this); + if (cls == 0) + { + JCL_ThrowException (env, IO_EXCEPTION, "internal error"); + return 0; + } + + fid = (*env)->GetFieldID (env, cls, "native_fd", "I"); + if (fid == 0) + { + JCL_ThrowException (env, IO_EXCEPTION, "internal error"); + return 0; + } + + fd = (*env)->GetIntField (env, this, fid); + + TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_AVAILABLE (fd, bytesAvailable, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return 0; + } + + return bytesAvailable; +#else /* not WITHOUT_NETWORK */ + return 0; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method sets the specified option for a socket + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_setOption (JNIEnv * env, jobject this, + jint option_id, jobject val) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_set_option (env, this, option_id, val); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method sets the specified option for a socket + */ +JNIEXPORT jobject JNICALL +Java_gnu_java_net_PlainSocketImpl_getOption (JNIEnv * env, jobject this, + jint option_id) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + return (_javanet_get_option (env, this, option_id)); +#else /* not WITHOUT_NETWORK */ + return NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Reads a buffer from a remote host + */ +JNIEXPORT jint JNICALL +Java_gnu_java_net_PlainSocketImpl_read (JNIEnv * env, jobject this, + jarray buf, jint offset, jint len) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + return (_javanet_recvfrom (env, this, buf, offset, len, 0, 0)); +#else /* not WITHOUT_NETWORK */ + return 0; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Writes a buffer to the remote host + */ +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_write (JNIEnv * env, jobject this, + jarray buf, jint offset, jint len) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_sendto (env, this, buf, offset, len, 0, 0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_shutdownInput (JNIEnv * env, jobject this) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_shutdownInput (env, this); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +JNIEXPORT void JNICALL +Java_gnu_java_net_PlainSocketImpl_shutdownOutput (JNIEnv * env, jobject this) +{ +#ifndef WITHOUT_NETWORK + assert (env != NULL); + assert ((*env) != NULL); + + _javanet_shutdownOutput (env, this); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/* end of file */ diff --git a/libjava/classpath/native/jni/java-net/java_net_VMInetAddress.c b/libjava/classpath/native/jni/java-net/java_net_VMInetAddress.c new file mode 100644 index 00000000000..d33265cff7e --- /dev/null +++ b/libjava/classpath/native/jni/java-net/java_net_VMInetAddress.c @@ -0,0 +1,282 @@ +/* VMInetAddress.c - Native methods for InetAddress class + Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "javanet.h" + +#include "target_native.h" +#ifndef WITHOUT_NETWORK +#include "target_native_network.h" +#endif /* WITHOUT_NETWORK */ + +#include "java_net_VMInetAddress.h" + +/*************************************************************************/ + +/* + * Function to return the local hostname + */ +JNIEXPORT jstring JNICALL +Java_java_net_VMInetAddress_getLocalHostname (JNIEnv * env, + jclass class + __attribute__ ((__unused__))) +{ + char hostname[256]; + int result; + jstring retval; + + assert (env != NULL); + assert ((*env) != NULL); + +#ifndef WITHOUT_NETWORK + TARGET_NATIVE_NETWORK_GET_HOSTNAME (hostname, sizeof (hostname), result); + if (result != TARGET_NATIVE_OK) + { + strcpy (hostname, "localhost"); + } +#else /* not WITHOUT_NETWORK */ + strcpy (hostname, "localhost"); +#endif /* not WITHOUT_NETWORK */ + + retval = (*env)->NewStringUTF (env, hostname); + + return (retval); +} + +/*************************************************************************/ + +/* + * Returns the value of the special IP address INADDR_ANY + */ +JNIEXPORT jarray JNICALL +Java_java_net_VMInetAddress_lookupInaddrAny (JNIEnv * env, + jclass class + __attribute__ ((__unused__))) +{ + jarray IParray; + jbyte *octets; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Allocate an array for the IP address */ + IParray = (*env)->NewByteArray (env, 4); + if (IParray == NULL) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + return (jarray) NULL; + } + + /* Copy in the values */ + octets = (*env)->GetByteArrayElements (env, IParray, 0); + +#ifndef WITHOUT_NETWORK + TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (INADDR_ANY, + octets[0], + octets[1], + octets[2], octets[3]); + (*env)->ReleaseByteArrayElements (env, IParray, octets, 0); +#else /* not WITHOUT_NETWORK */ + octets[0] = 0; + octets[1] = 0; + octets[2] = 0; + octets[3] = 0; +#endif /* not WITHOUT_NETWORK */ + + return (IParray); +} + +/*************************************************************************/ + +/* + * Function to return the canonical hostname for a given IP address passed + * in as a byte array + */ +JNIEXPORT jstring JNICALL +Java_java_net_VMInetAddress_getHostByAddr (JNIEnv * env, + jclass class + __attribute__ ((__unused__)), + jarray arr) +{ +#ifndef WITHOUT_NETWORK + jbyte *octets; + jsize len; + int addr; + char hostname[255]; + int result; + jstring retval; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Grab the byte[] array with the IP out of the input data */ + len = (*env)->GetArrayLength (env, arr); + if (len != 4) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Bad IP Address"); + return (jstring) NULL; + } + + octets = (*env)->GetByteArrayElements (env, arr, 0); + if (!octets) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Bad IP Address"); + return (jstring) NULL; + } + + /* Convert it to a 32 bit address */ + TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets[0], + octets[1], + octets[2], octets[3], addr); + + /* Release some memory */ + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + + /* Resolve the address and return the name */ + TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_ADDRESS (addr, hostname, + sizeof (hostname), result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Bad IP address"); + return (jstring) NULL; + } + + retval = (*env)->NewStringUTF (env, hostname); + + return (retval); +#else /* not WITHOUT_NETWORK */ + return (jstring) NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +JNIEXPORT jobjectArray JNICALL +Java_java_net_VMInetAddress_getHostByName (JNIEnv * env, + jclass class + __attribute__ ((__unused__)), + jstring host) +{ +#ifndef WITHOUT_NETWORK + const char *hostname; +/* FIXME: limitation of max. 64 addresses - how to make it more flexibale? */ + int addresses[64]; + jsize addresses_count; + int result; + jclass arr_class; + jobjectArray addrs; + int i; + jbyte *octets; + jarray ret_octets; + int max_addresses; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Grab the hostname string */ + hostname = (*env)->GetStringUTFChars (env, host, 0); + if (!hostname) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Null hostname"); + return (jobjectArray) NULL; + } + + max_addresses = sizeof (addresses) / sizeof (addresses[0]); + TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_NAME (hostname, + addresses, + max_addresses, + addresses_count, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, (char *) hostname); + return (jobjectArray) NULL; + } + (*env)->ReleaseStringUTFChars (env, host, hostname); + + arr_class = (*env)->FindClass (env, "[B"); + if (!arr_class) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + return (jobjectArray) NULL; + } + + addrs = (*env)->NewObjectArray (env, addresses_count, arr_class, 0); + if (!addrs) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + return (jobjectArray) NULL; + } + + /* Now loop and copy in each address */ + for (i = 0; i < addresses_count; i++) + { + ret_octets = (*env)->NewByteArray (env, 4); + if (!ret_octets) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + return (jobjectArray) NULL; + } + + octets = (*env)->GetByteArrayElements (env, ret_octets, 0); + + TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (addresses[i], + octets[0], + octets[1], + octets[2], octets[3]); + + (*env)->ReleaseByteArrayElements (env, ret_octets, octets, 0); + + (*env)->SetObjectArrayElement (env, addrs, i, ret_octets); + } + + return (addrs); +#else /* not WITHOUT_NETWORK */ + return (jobjectArray) NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/* end of file */ diff --git a/libjava/classpath/native/jni/java-net/java_net_VMNetworkInterface.c b/libjava/classpath/native/jni/java-net/java_net_VMNetworkInterface.c new file mode 100644 index 00000000000..71f5e8927e5 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/java_net_VMNetworkInterface.c @@ -0,0 +1,66 @@ +/* VMNetworkInterface.c - Native methods for NetworkInterface class + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "java_net_VMNetworkInterface.h" + +#include "javanet.h" + +/* + * Returns all local network interfaces as vector + */ +JNIEXPORT jobject JNICALL +Java_java_net_VMNetworkInterface_getInterfaces (JNIEnv * env, + jclass class + __attribute__ ((__unused__))) +{ + JCL_ThrowException (env, IO_EXCEPTION, + "java.net.VMNetworkInterface.getInterfaces(): not implemented"); + return 0; +} + +/* end of file */ diff --git a/libjava/classpath/native/jni/java-net/javanet.c b/libjava/classpath/native/jni/java-net/javanet.c new file mode 100644 index 00000000000..fdc1c22ecbf --- /dev/null +++ b/libjava/classpath/native/jni/java-net/javanet.c @@ -0,0 +1,1577 @@ +/* javanet.c - Common internal functions for the java.net package + Copyright (C) 1998, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <jni.h> +#include <jcl.h> + +#include "javanet.h" + +#include "target_native.h" +#ifndef WITHOUT_NETWORK +#include "target_native_network.h" +#endif /* WITHOUT_NETWORK */ + +#ifndef WITHOUT_NETWORK +/* Need to have some value for SO_TIMEOUT */ +#ifndef SO_TIMEOUT +#ifndef SO_RCVTIMEO +#warning Neither SO_TIMEOUT or SO_RCVTIMEO are defined! +#warning This will cause all get/setOption calls with that value to throw an exception +#else +#define SO_TIMEOUT SO_RCVTIMEO +#endif /* not SO_RCVTIMEO */ +#endif /* not SO_TIMEOUT */ +#endif /* WITHOUT_NETWORK */ + +/*************************************************************************/ + +/* + * Sets an integer field in the specified object. + */ +static void +_javanet_set_int_field (JNIEnv * env, jobject obj, + const char *class, const char *field, int val) +{ + jclass cls; + jfieldID fid; + + assert (env != NULL); + assert ((*env) != NULL); + + cls = (*env)->FindClass (env, class); + if (cls == NULL) + return; + + fid = (*env)->GetFieldID (env, cls, field, "I"); + if (fid == NULL) + return; + + (*env)->SetIntField (env, obj, fid, val); + + return; +} + +/*************************************************************************/ + +/* + * Returns the value of the specified integer instance variable field or + * -1 if an error occurs. + */ +int +_javanet_get_int_field (JNIEnv * env, jobject obj, const char *field) +{ + jclass cls = 0; + jfieldID fid; + int fd; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_get_int_field(): Entered _javanet_get_int_field\n"); + + cls = (*env)->GetObjectClass (env, obj); + if (cls == NULL) + return -1; + + fid = (*env)->GetFieldID (env, cls, field, "I"); + if (fid == NULL) + return -1; + DBG ("_javanet_get_int_field(): Found field id\n"); + + fd = (*env)->GetIntField (env, obj, fid); + + return fd; +} + +/*************************************************************************/ + +/* + * Creates a FileDescriptor object in the parent class. It is not used + * by this implementation, but the docs list it as a variable, so we + * need to include it. + */ +static void +_javanet_create_localfd (JNIEnv * env, jobject this) +{ + jclass this_cls, fd_cls; + jfieldID fid; + jmethodID mid; + jobject fd_obj; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_create_localfd(): Entered _javanet_create_localfd\n"); + + /* Look up the fd field */ + this_cls = (*env)->FindClass (env, "java/net/SocketImpl"); + if (this_cls == NULL) + return; + + fid = (*env)->GetFieldID (env, this_cls, "fd", "Ljava/io/FileDescriptor;"); + if (fid == NULL) + return; + + DBG ("_javanet_create_localfd(): Found fd variable\n"); + + /* Create a FileDescriptor */ + fd_cls = (*env)->FindClass (env, "java/io/FileDescriptor"); + if (fd_cls == NULL) + return; + + DBG ("_javanet_create_localfd(): Found FileDescriptor class\n"); + + mid = (*env)->GetMethodID (env, fd_cls, "<init>", "()V"); + if (mid == NULL) + return; + + DBG ("_javanet_create_localfd(): Found FileDescriptor constructor\n"); + + fd_obj = (*env)->NewObject (env, fd_cls, mid); + if (fd_obj == NULL) + return; + + DBG ("_javanet_create_localfd(): Created FileDescriptor\n"); + + /* Now set the pointer to the new FileDescriptor */ + (*env)->SetObjectField (env, this, fid, fd_obj); + DBG ("_javanet_create_localfd(): Set fd field\n"); + + return; +} + +/*************************************************************************/ + +/* + * Returns a Boolean object with the specfied value + */ +static jobject +_javanet_create_boolean (JNIEnv * env, jboolean val) +{ + jclass cls; + jmethodID mid; + jobject obj; + + assert (env != NULL); + assert ((*env) != NULL); + + cls = (*env)->FindClass (env, "java/lang/Boolean"); + if (cls == NULL) + return NULL; + + mid = (*env)->GetMethodID (env, cls, "<init>", "(Z)V"); + if (mid == NULL) + return NULL; + + obj = (*env)->NewObject (env, cls, mid, val); + if (obj == NULL) + return NULL; + + return obj; +} + +/*************************************************************************/ + +/* + * Returns an Integer object with the specfied value + */ +static jobject +_javanet_create_integer (JNIEnv * env, jint val) +{ + jclass cls; + jmethodID mid; + jobject obj; + + assert (env != NULL); + assert ((*env) != NULL); + + cls = (*env)->FindClass (env, "java/lang/Integer"); + if (cls == NULL) + return NULL; + + mid = (*env)->GetMethodID (env, cls, "<init>", "(I)V"); + if (mid == NULL) + return NULL; + + obj = (*env)->NewObject (env, cls, mid, val); + if (obj == NULL) + return NULL; + + return obj; +} + +/*************************************************************************/ + +/* + * Builds an InetAddress object from a 32 bit address in host byte order + */ +static jobject +_javanet_create_inetaddress (JNIEnv * env, int netaddr) +{ +#ifndef WITHOUT_NETWORK + unsigned char octets[4]; + char buf[16]; + jclass ia_cls; + jmethodID mid; + jstring ip_str; + jobject ia; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Build a string IP address */ + TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (netaddr, + octets[0], + octets[1], + octets[2], octets[3]); + sprintf (buf, "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]); + DBG ("_javanet_create_inetaddress(): Created ip addr string\n"); + + /* Get an InetAddress object for this IP */ + ia_cls = (*env)->FindClass (env, "java/net/InetAddress"); + if (ia_cls == NULL) + { + return NULL; + } + + DBG ("_javanet_create_inetaddress(): Found InetAddress class\n"); + + mid = (*env)->GetStaticMethodID (env, ia_cls, "getByName", + "(Ljava/lang/String;)Ljava/net/InetAddress;"); + if (mid == NULL) + { + return NULL; + } + + DBG ("_javanet_create_inetaddress(): Found getByName method\n"); + + ip_str = (*env)->NewStringUTF (env, buf); + if (ip_str == NULL) + { + return NULL; + } + + ia = (*env)->CallStaticObjectMethod (env, ia_cls, mid, ip_str); + if (ia == NULL) + { + return NULL; + } + + DBG ("_javanet_create_inetaddress(): Called getByName method\n"); + + return ia; +#else /* not WITHOUT_NETWORK */ + return NULL; +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +static void +_javanet_set_remhost_addr (JNIEnv * env, jobject this, jobject ia) +{ + jclass this_cls; + jfieldID fid; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Set the variable in the object */ + this_cls = (*env)->FindClass (env, "java/net/SocketImpl"); + if (this_cls == NULL) + return; + + fid = + (*env)->GetFieldID (env, this_cls, "address", "Ljava/net/InetAddress;"); + if (fid == NULL) + return; + + DBG ("_javanet_set_remhost_addr(): Found address field\n"); + + (*env)->SetObjectField (env, this, fid, ia); + DBG ("_javanet_set_remhost_addr(): Set field\n"); +} + +/* + * Set's the value of the "addr" field in PlainSocketImpl with a new + * InetAddress for the specified addr + */ +static void +_javanet_set_remhost (JNIEnv * env, jobject this, int netaddr) +{ + jobject ia; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_set_remhost(): Entered _javanet_set_remhost\n"); + + /* Get an InetAddress object */ + ia = _javanet_create_inetaddress (env, netaddr); + if (ia == NULL) + return; + + _javanet_set_remhost_addr (env, this, ia); +} + + +/*************************************************************************/ + +/* + * Returns a 32 bit Internet address for the passed in InetAddress object + */ +int +_javanet_get_netaddr (JNIEnv * env, jobject addr) +{ +#ifndef WITHOUT_NETWORK + jclass cls = 0; + jmethodID mid; + jarray arr = 0; + jbyte *octets; + int netaddr, len; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_get_netaddr(): Entered _javanet_get_netaddr\n"); + + if (addr == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", + "Null address"); + return 0; + } + + /* Call the getAddress method on the object to retrieve the IP address */ + cls = (*env)->GetObjectClass (env, addr); + if (cls == NULL) + return 0; + + mid = (*env)->GetMethodID (env, cls, "getAddress", "()[B"); + if (mid == NULL) + return 0; + + DBG ("_javanet_get_netaddr(): Got getAddress method\n"); + + arr = (*env)->CallObjectMethod (env, addr, mid); + if (arr == NULL) + return 0; + + DBG ("_javanet_get_netaddr(): Got the address\n"); + + /* Turn the IP address into a 32 bit Internet address in network byte order */ + len = (*env)->GetArrayLength (env, arr); + if (len != 4) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal Error"); + return 0; + } + DBG ("_javanet_get_netaddr(): Length ok\n"); + + octets = (*env)->GetByteArrayElements (env, arr, 0); + if (octets == NULL) + return 0; + + DBG ("_javanet_get_netaddr(): Grabbed bytes\n"); + + TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets[0], + octets[1], + octets[2], + octets[3], netaddr); + + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + DBG ("_javanet_get_netaddr(): Done getting addr\n"); + + return netaddr; +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Creates a new stream or datagram socket + */ +void +_javanet_create (JNIEnv * env, jobject this, jboolean stream) +{ +#ifndef WITHOUT_NETWORK + int fd; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + if (stream) + { + /* create a stream socket */ + TARGET_NATIVE_NETWORK_SOCKET_OPEN_STREAM (fd, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + } + else + { + /* create a datagram socket, set broadcast option */ + TARGET_NATIVE_NETWORK_SOCKET_OPEN_DATAGRAM (fd, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_BROADCAST (fd, 1, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + } + + if (stream) + _javanet_set_int_field (env, this, "gnu/java/net/PlainSocketImpl", + "native_fd", fd); + else + _javanet_set_int_field (env, this, "gnu/java/net/PlainDatagramSocketImpl", + "native_fd", fd); + + if ((*env)->ExceptionOccurred (env)) + { + /* Try to make sure we close the socket since close() won't work. */ + do + { + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + if (result != TARGET_NATIVE_OK + && (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + return; + } + while (result != TARGET_NATIVE_OK); + return; + } + +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Close the socket. Any underlying streams will be closed by this + * action as well. + */ +void +_javanet_close (JNIEnv * env, jobject this, int stream) +{ +#ifndef WITHOUT_NETWORK + int fd; + int result; + int error = 0; + + assert (env != NULL); + assert ((*env) != NULL); + + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + return; + + if (stream) + _javanet_set_int_field (env, this, "gnu/java/net/PlainSocketImpl", + "native_fd", -1); + else + _javanet_set_int_field (env, this, "gnu/java/net/PlainDatagramSocketImpl", + "native_fd", -1); + do + { + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + if (result != TARGET_NATIVE_OK) + { + /* Only throw an error when a "real" error occurs. */ + error = TARGET_NATIVE_LAST_ERROR (); + if (error != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL + && error != ENOTCONN && error != ECONNRESET && error != EBADF) + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + } + } + while (error == TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL); + +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Connects to the specified destination. + */ +void +_javanet_connect (JNIEnv * env, jobject this, jobject addr, jint port) +{ +#ifndef WITHOUT_NETWORK + int netaddr, fd; + int result; + int local_address, local_port; + int remote_address, remote_port; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_connect(): Entered _javanet_connect\n"); + + /* Pre-process input variables */ + netaddr = _javanet_get_netaddr (env, addr); + if ((*env)->ExceptionOccurred (env)) + return; + + if (port == -1) + port = 0; + DBG ("_javanet_connect(): Got network address\n"); + + /* Grab the real socket file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_connect(): no native file descriptor"); + return; + } + DBG ("_javanet_connect(): Got native fd\n"); + + /* Connect up */ + do + { + TARGET_NATIVE_NETWORK_SOCKET_CONNECT (fd, netaddr, port, result); + if (result != TARGET_NATIVE_OK + && (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + } + while (result != TARGET_NATIVE_OK); + + DBG ("_javanet_connect(): Connected successfully\n"); + + /* Populate instance variables */ + TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (fd, local_address, local_port, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + + _javanet_create_localfd (env, this); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + DBG ("_javanet_connect(): Created fd\n"); + + _javanet_set_int_field (env, this, "java/net/SocketImpl", "localport", + local_port); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + DBG ("_javanet_connect(): Set the local port\n"); + + TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO (fd, remote_address, + remote_port, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + + if (remote_address == netaddr) + { + _javanet_set_remhost_addr (env, this, addr); + } + else + { + _javanet_set_remhost (env, this, remote_address); + } + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + DBG ("_javanet_connect(): Set the remote host\n"); + + _javanet_set_int_field (env, this, "java/net/SocketImpl", "port", + remote_port); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (fd, result); + return; + } + DBG ("_javanet_connect(): Set the remote port\n"); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * This method binds the specified address to the specified local port. + * Note that we have to set the local address and local + * port public instance variables. + */ +void +_javanet_bind (JNIEnv * env, jobject this, jobject addr, jint port, + int stream) +{ +#ifndef WITHOUT_NETWORK + jclass cls; + jmethodID mid; + jbyteArray arr = 0; + jbyte *octets; + jint fd; + int tmpaddr; + int result; + int local_address, local_port; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_bind(): Entering native bind()\n"); + + /* Get the address to connect to */ + cls = (*env)->GetObjectClass (env, addr); + if (cls == NULL) + return; + + mid = (*env)->GetMethodID (env, cls, "getAddress", "()[B"); + if (mid == NULL) + return; + + DBG ("_javanet_bind(): Past getAddress method id\n"); + + arr = (*env)->CallObjectMethod (env, addr, mid); + if ((arr == NULL) || (*env)->ExceptionOccurred (env)) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_bind()"); + return; + } + + DBG ("_javanet_bind(): Past call object method\n"); + + octets = (*env)->GetByteArrayElements (env, arr, 0); + if (octets == NULL) + return; + + DBG ("_javanet_bind(): Past grab array\n"); + + /* Get the native socket file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_bind(): no native file descriptor"); + return; + } + DBG ("_javanet_bind(): Past native_fd lookup\n"); + + /* XXX NYI ??? */ + _javanet_set_option (env, this, SOCKOPT_SO_REUSEADDR, + _javanet_create_boolean (env, JNI_TRUE)); + + + /* Bind the socket */ + TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets[0], + octets[1], + octets[2], + octets[3], tmpaddr); + TARGET_NATIVE_NETWORK_SOCKET_BIND (fd, tmpaddr, port, result); + + if (result != TARGET_NATIVE_OK) + { + char *errorstr = TARGET_NATIVE_LAST_ERROR_STRING (); + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + + JCL_ThrowException (env, BIND_EXCEPTION, + errorstr); + return; + } + DBG ("_javanet_bind(): Past bind\n"); + + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + + /* Update instance variables, specifically the local port number */ + TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (fd, local_address, local_port, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + if (stream) + _javanet_set_int_field (env, this, "java/net/SocketImpl", + "localport", local_port); + else + _javanet_set_int_field (env, this, "java/net/DatagramSocketImpl", + "localPort", local_port); + DBG ("_javanet_bind(): Past update port number\n"); + + return; +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Starts listening on a socket with the specified number of pending + * connections allowed. + */ +void +_javanet_listen (JNIEnv * env, jobject this, jint queuelen) +{ +#ifndef WITHOUT_NETWORK + int fd; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_listen(): no native file descriptor"); + return; + } + + /* Start listening */ + TARGET_NATIVE_NETWORK_SOCKET_LISTEN (fd, queuelen, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Accepts a new connection and assigns it to the passed in SocketImpl + * object. Note that we assume this is a PlainSocketImpl just like us + */ +void +_javanet_accept (JNIEnv * env, jobject this, jobject impl) +{ +#ifndef WITHOUT_NETWORK + int fd, newfd; + int result; + int local_address, local_port; + int remote_address, remote_port; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_accept(): no native file descriptor"); + return; + } + + /* Accept the connection */ + do + { + TARGET_NATIVE_NETWORK_SOCKET_ACCEPT (fd, newfd, result); + if (result != TARGET_NATIVE_OK + && (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_accept(): "); + return; + } + } + while (result != TARGET_NATIVE_OK); + + /* Populate instance variables */ + _javanet_set_int_field (env, impl, "gnu/java/net/PlainSocketImpl", + "native_fd", newfd); + + if ((*env)->ExceptionOccurred (env)) + { + /* Try to make sure we close the socket since close() won't work. */ + do + { + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + if (result != TARGET_NATIVE_OK + && (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + return; + } + while (result != TARGET_NATIVE_OK); + return; + } + + TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO (newfd, local_address, + local_port, result); + if (result != TARGET_NATIVE_OK) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + _javanet_create_localfd (env, impl); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } + + _javanet_set_int_field (env, impl, "java/net/SocketImpl", "localport", + local_port); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } + + TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO (newfd, remote_address, + remote_port, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } + + _javanet_set_remhost (env, impl, remote_address); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } + + _javanet_set_int_field (env, impl, "java/net/SocketImpl", "port", + remote_port); + if ((*env)->ExceptionOccurred (env)) + { + /* We don't care whether this succeeds. close() will cleanup later. */ + TARGET_NATIVE_NETWORK_SOCKET_CLOSE (newfd, result); + return; + } +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Receives a buffer from a remote host. The args are: + * + * buf - The byte array into which the data received will be written + * offset - Offset into the byte array to start writing + * len - The number of bytes to read. + * addr - Pointer to 32 bit net address of host to receive from. If null, + * this parm is ignored. If pointing to an address of 0, the + * actual address read is stored here + * port - Pointer to the port to receive from. If null, this parm is ignored. + * If it is 0, the actual remote port received from is stored here + * + * The actual number of bytes read is returned. + */ +int +_javanet_recvfrom (JNIEnv * env, jobject this, jarray buf, int offset, + int len, int *addr, int *port) +{ +#ifndef WITHOUT_NETWORK + int fd; + jbyte *p; + int from_address, from_port; + int received_bytes; + + assert (env != NULL); + assert ((*env) != NULL); + + DBG ("_javanet_recvfrom(): Entered _javanet_recvfrom\n"); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_recvfrom(): no native file descriptor"); + return 0; + } + DBG ("_javanet_recvfrom(): Got native_fd\n"); + + /* Get a pointer to the buffer */ + p = (*env)->GetByteArrayElements (env, buf, 0); + if (p == NULL) + return 0; + + DBG ("_javanet_recvfrom(): Got buffer\n"); + + /* Read the data */ + from_address = 0; + from_port = 0; + do + { + if (addr != NULL) + { + TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_WITH_ADDRESS_PORT (fd, + p + offset, + len, + from_address, + from_port, + received_bytes); + } + else + { + TARGET_NATIVE_NETWORK_SOCKET_RECEIVE (fd, p + offset, len, + received_bytes); + } + } + while ((received_bytes == -1) && + (TARGET_NATIVE_LAST_ERROR () == + TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)); + + if (received_bytes == -1) + { + if (TARGET_NATIVE_LAST_ERROR () == EAGAIN) + JCL_ThrowException (env, "java/net/SocketTimeoutException", "Timeout"); + else + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + + /* Cleanup and return. */ + (*env)->ReleaseByteArrayElements (env, buf, p, 0); + return 0; + } + + (*env)->ReleaseByteArrayElements (env, buf, p, 0); + + /* Handle return addr case */ + if (addr != NULL) + { + (*addr) = from_address; + if (port != NULL) + (*port) = from_port; + } + + return (received_bytes); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Sends a buffer to a remote host. The args are: + * + * buf - A byte array + * offset - Index into the byte array to start sendign + * len - The number of bytes to write + * addr - The 32bit address to send to (may be 0) + * port - The port number to send to (may be 0) + */ +void +_javanet_sendto (JNIEnv * env, jobject this, jarray buf, int offset, int len, + int addr, int port) +{ +#ifndef WITHOUT_NETWORK + int fd; + jbyte *p; + int bytes_sent; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_sendto(): no native file descriptor"); + return; + } + + /* Get a pointer to the buffer */ + p = (*env)->GetByteArrayElements (env, buf, 0); + if (p == NULL) + return; + + /* We must send all the data, so repeat till done. */ + while (len > 0) + { + /* Send the data */ + if (addr == 0) + { + DBG ("_javanet_sendto(): Sending....\n"); + TARGET_NATIVE_NETWORK_SOCKET_SEND (fd, p + offset, len, bytes_sent); + } + else + { + DBG ("_javanet_sendto(): Sending....\n"); + TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT (fd, p + offset, + len, addr, port, + bytes_sent); + } + + if (bytes_sent < 0) + { + if (TARGET_NATIVE_LAST_ERROR () + != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + break; + } + } + else + { + len -= bytes_sent; + addr += bytes_sent; + } + } + + (*env)->ReleaseByteArrayElements (env, buf, p, 0); + +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Sets the specified option for a socket + */ +void +_javanet_set_option (JNIEnv * env, jobject this, jint option_id, jobject val) +{ +#ifndef WITHOUT_NETWORK + int fd; + int optval; + jclass cls; + jmethodID mid; + int address; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option(): no native file descriptor"); + return; + } + + /* We need a class object for all cases below */ + cls = (*env)->GetObjectClass (env, val); + if (cls == NULL) + return; + + /* Process the option request */ + result = TARGET_NATIVE_ERROR; + switch (option_id) + { + /* TCP_NODELAY case. val is a Boolean that tells us what to do */ + case SOCKOPT_TCP_NODELAY: + mid = (*env)->GetMethodID (env, cls, "booleanValue", "()Z"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + /* Should be a 0 or a 1 */ + optval = (*env)->CallBooleanMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_TCP_NODELAY (fd, optval, + result); + break; + + /* SO_LINGER case. If val is a boolean, then it will always be set + to false indicating disable linger, otherwise it will be an + integer that contains the linger value */ + case SOCKOPT_SO_LINGER: + mid = (*env)->GetMethodID (env, cls, "booleanValue", "()Z"); + if (mid) + { + /* We are disabling linger */ + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER (fd, 1, 0, + result); + } + else + { + /* Clear exception if thrown for failure to do method lookup + above */ + if ((*env)->ExceptionOccurred (env)) + (*env)->ExceptionClear (env); + + mid = (*env)->GetMethodID (env, cls, "intValue", "()I"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + optval = (*env)->CallIntMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER (fd, 0, optval, + result); + } + break; + + /* SO_TIMEOUT case. Val will be an integer with the new value */ + /* Not writable on Linux */ + case SOCKOPT_SO_TIMEOUT: +#ifdef SO_TIMEOUT + mid = (*env)->GetMethodID (env, cls, "intValue", "()I"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + optval = (*env)->CallIntMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_TIMEOUT (fd, optval, result); +#else + result = TARGET_NATIVE_OK; +#endif + break; + + case SOCKOPT_SO_SNDBUF: + case SOCKOPT_SO_RCVBUF: + mid = (*env)->GetMethodID (env, cls, "intValue", "()I"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + + optval = (*env)->CallIntMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + if (option_id == SOCKOPT_SO_SNDBUF) + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_SNDBUF (fd, optval, + result); + else + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_RCDBUF (fd, optval, + result); + break; + + /* TTL case. Val with be an Integer with the new time to live value */ + case SOCKOPT_IP_TTL: + mid = (*env)->GetMethodID (env, cls, "intValue", "()I"); + if (!mid) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + optval = (*env)->CallIntMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_TTL (fd, optval, result); + break; + + /* Multicast Interface case - val is InetAddress object */ + case SOCKOPT_IP_MULTICAST_IF: + address = _javanet_get_netaddr (env, val); + + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_MULTICAST_IF (fd, address, + result); + break; + + case SOCKOPT_SO_REUSEADDR: + mid = (*env)->GetMethodID (env, cls, "booleanValue", "()Z"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + /* Should be a 0 or a 1 */ + optval = (*env)->CallBooleanMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_REUSE_ADDRESS (fd, optval, + result); + break; + + case SOCKOPT_SO_KEEPALIVE: + mid = (*env)->GetMethodID (env, cls, "booleanValue", "()Z"); + if (mid == NULL) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Internal error: _javanet_set_option()"); + return; + } + + /* Should be a 0 or a 1 */ + optval = (*env)->CallBooleanMethod (env, val, mid); + if ((*env)->ExceptionOccurred (env)) + return; + + TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_KEEP_ALIVE (fd, optval, result); + break; + + case SOCKOPT_SO_BINDADDR: + JCL_ThrowException (env, SOCKET_EXCEPTION, "This option cannot be set"); + break; + + default: + JCL_ThrowException (env, SOCKET_EXCEPTION, "Unrecognized option"); + return; + } + + /* Check to see if above operations succeeded */ + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +/*************************************************************************/ + +/* + * Retrieves the specified option values for a socket + */ +jobject +_javanet_get_option (JNIEnv * env, jobject this, jint option_id) +{ +#ifndef WITHOUT_NETWORK + int fd; + int flag, optval; + int address; + int result; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Internal error: _javanet_get_option(): no native file descriptor"); + return (0); + } + + /* Process the option requested */ + switch (option_id) + { + /* TCP_NODELAY case. Return a Boolean indicating on or off */ + case SOCKOPT_TCP_NODELAY: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_TCP_NODELAY (fd, optval, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + if (optval) + return (_javanet_create_boolean (env, JNI_TRUE)); + else + return (_javanet_create_boolean (env, JNI_FALSE)); + + break; + + /* SO_LINGER case. If disabled, return a Boolean object that represents + false, else return an Integer that is the value of SO_LINGER */ + case SOCKOPT_SO_LINGER: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_LINGER (fd, flag, optval, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + if (optval) + return (_javanet_create_integer (env, JNI_TRUE)); + else + return (_javanet_create_boolean (env, JNI_FALSE)); + + break; + + /* SO_TIMEOUT case. Return an Integer object with the timeout value */ + case SOCKOPT_SO_TIMEOUT: +#ifdef SO_TIMEOUT + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_TIMEOUT (fd, optval, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + return (_javanet_create_integer (env, optval)); +#else + JCL_ThrowException (env, SOCKET_EXCEPTION, + "SO_TIMEOUT not supported on this platform"); + return (0); +#endif /* not SO_TIMEOUT */ + break; + + case SOCKOPT_SO_SNDBUF: + case SOCKOPT_SO_RCVBUF: + if (option_id == SOCKOPT_SO_SNDBUF) + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_SNDBUF (fd, optval, + result); + else + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_RCDBUF (fd, optval, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + return (_javanet_create_integer (env, optval)); + break; + + /* The TTL case. Return an Integer with the Time to Live value */ + case SOCKOPT_IP_TTL: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_TTL (fd, optval, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + return (_javanet_create_integer (env, optval)); + break; + + /* Multicast interface case */ + case SOCKOPT_IP_MULTICAST_IF: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_MULTICAST_IF (fd, address, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + return (_javanet_create_inetaddress (env, address)); + break; + + case SOCKOPT_SO_BINDADDR: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BIND_ADDRESS (fd, address, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + return (_javanet_create_inetaddress (env, address)); + break; + + case SOCKOPT_SO_REUSEADDR: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_REUSE_ADDRESS (fd, optval, + result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + if (optval) + return (_javanet_create_boolean (env, JNI_TRUE)); + else + return (_javanet_create_boolean (env, JNI_FALSE)); + + break; + + case SOCKOPT_SO_KEEPALIVE: + TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_KEEP_ALIVE (fd, optval, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (0); + } + + if (optval) + return (_javanet_create_boolean (env, JNI_TRUE)); + else + return (_javanet_create_boolean (env, JNI_FALSE)); + + break; + + default: + JCL_ThrowException (env, SOCKET_EXCEPTION, "No such option"); + return (0); + } + + return (0); +#else /* not WITHOUT_NETWORK */ +#endif /* not WITHOUT_NETWORK */ +} + +void +_javanet_shutdownInput (JNIEnv * env, jobject this) +{ + int fd; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor. */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Internal error: _javanet_get_option(): no native file descriptor"); + return; + } + + /* Shutdown input stream of socket. */ + if (shutdown (fd, SHUT_RD) == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Can't shutdown input of socket"); + return; + } +} + +void +_javanet_shutdownOutput (JNIEnv * env, jobject this) +{ + int fd; + + assert (env != NULL); + assert ((*env) != NULL); + + /* Get the real file descriptor. */ + fd = _javanet_get_int_field (env, this, "native_fd"); + if (fd == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Internal error: _javanet_get_option(): no native file descriptor"); + return; + } + + /* Shutdown output stream of socket. */ + if (shutdown (fd, SHUT_WR) == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "Can't shutdown output of socket"); + return; + } +} + +/* end of file */ diff --git a/libjava/classpath/native/jni/java-net/javanet.h b/libjava/classpath/native/jni/java-net/javanet.h new file mode 100644 index 00000000000..7c77ea77f84 --- /dev/null +++ b/libjava/classpath/native/jni/java-net/javanet.h @@ -0,0 +1,109 @@ +/* javanet.h - Declarations for common functions for the java.net package + Copyright (C) 1998, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#ifndef _JAVANET_LOADED +#define _JAVANET_LOADED + +#include <jni.h> + +/*************************************************************************/ + +/* + * Defined constants + */ + +/* Exception Classes */ +#define BIND_EXCEPTION "java/net/BindException" +#define IO_EXCEPTION "java/io/IOException" +#define SOCKET_EXCEPTION "java/net/SocketException" +#define UNKNOWN_HOST_EXCEPTION "java/net/UnknownHostException" + +/* Socket Option Identifiers - Don't change or binary compatibility with + the JDK will be broken! These also need to + be kept compatible with java.net.SocketOptions */ +#define SOCKOPT_TCP_NODELAY 1 +#define SOCKOPT_SO_BINDADDR 15 +#define SOCKOPT_SO_LINGER 128 +#define SOCKOPT_SO_TIMEOUT 4102 +#define SOCKOPT_SO_SNDBUF 4097 +#define SOCKOPT_SO_RCVBUF 4098 +#define SOCKOPT_SO_REUSEADDR 4 +#define SOCKOPT_IP_MULTICAST_IF 16 +#define SOCKOPT_SO_KEEPALIVE 8 + +/* Internal option identifiers. Not needed for JDK compatibility */ +#define SOCKOPT_IP_TTL 7777 + +/*************************************************************************/ + +/* + * Macros + */ + +/* Simple debug macro */ +#ifdef DEBUG +#define DBG(x) fprintf(stderr, (x)); +#else +#define DBG(x) +#endif + +/*************************************************************************/ + +/* + * Function Prototypes + */ + +extern int _javanet_get_int_field(JNIEnv *, jobject, const char *); +extern int _javanet_get_netaddr(JNIEnv *, jobject); +extern void _javanet_create(JNIEnv *, jobject, jboolean); +extern void _javanet_close(JNIEnv *, jobject, int); +extern void _javanet_connect(JNIEnv *, jobject, jobject, jint); +extern void _javanet_bind(JNIEnv *, jobject, jobject, jint, int); +extern void _javanet_listen(JNIEnv *, jobject, jint); +extern void _javanet_accept(JNIEnv *, jobject, jobject); +extern int _javanet_recvfrom(JNIEnv *, jobject, jarray, int, int, int *, int *); +extern void _javanet_sendto(JNIEnv *, jobject, jarray, int, int, int, int); +extern jobject _javanet_get_option(JNIEnv *, jobject, jint); +extern void _javanet_set_option(JNIEnv *, jobject, jint, jobject); +extern void _javanet_shutdownInput (JNIEnv *, jobject); +extern void _javanet_shutdownOutput (JNIEnv *, jobject); + +/*************************************************************************/ + +#endif /* not _JAVANET_H_LOADED */ + diff --git a/libjava/classpath/native/jni/java-nio/.cvsignore b/libjava/classpath/native/jni/java-nio/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/java-nio/Makefile.am b/libjava/classpath/native/jni/java-nio/Makefile.am new file mode 100644 index 00000000000..9785fee6d9b --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/Makefile.am @@ -0,0 +1,16 @@ +pkglib_LTLIBRARIES = libjavanio.la + +libjavanio_la_SOURCES = gnu_java_nio_VMPipe.c \ + gnu_java_nio_VMSelector.c \ + gnu_java_nio_channels_FileChannelImpl.c \ + gnu_java_nio_charset_iconv_IconvDecoder.c \ + gnu_java_nio_charset_iconv_IconvEncoder.c \ + java_nio_MappedByteBufferImpl.c \ + java_nio_VMDirectByteBuffer.c + +libjavanio_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo \ + $(LTLIBICONV) + +AM_LDFLAGS = @CLASSPATH_MODULE@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@ diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMPipe.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMPipe.c new file mode 100644 index 00000000000..369c5a3d650 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMPipe.c @@ -0,0 +1,56 @@ +/* gnu_java_nio_VMPipe.c - Native methods for PipeImpl class + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include <config.h> +#include <errno.h> + +#include <jni.h> +#include <jcl.h> + +#include "gnu_java_nio_VMPipe.h" + +#define IO_EXCEPTION "java/io/IOException" + +JNIEXPORT void JNICALL +Java_gnu_java_nio_VMPipe_init (JNIEnv * env, + jclass cls __attribute__ ((__unused__)), + jobject self __attribute__ ((__unused__)), + jobject provider __attribute__ ((__unused__))) +{ + JCL_ThrowException (env, IO_EXCEPTION, + "gnu.java.nio.VMPipe.init(): not implemented"); +} diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMSelector.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMSelector.c new file mode 100644 index 00000000000..f8a40aa7a15 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMSelector.c @@ -0,0 +1,296 @@ +/* gnu_java_nio_VMSelector.c - Native methods for SelectorImpl class + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "config.h" + +/* <sys/types.h> needs to be included on OSX before <sys/select.h> */ +#if defined(HAVE_SYS_TYPES_H) +#include <sys/types.h> +#endif + +#include <sys/select.h> +#include <sys/time.h> + +#include <string.h> + +#include <errno.h> + +#include <jni.h> +#include <jcl.h> + +#include "gnu_java_nio_VMSelector.h" + +/* Amount of characters in the error message buffer for strerror_r. */ +#define BUF_SIZE 250 + +void helper_put_filedescriptors (JNIEnv *, jintArray, fd_set *, int *); + +void helper_get_filedescriptors (JNIEnv *, jintArray *, fd_set *); + +void helper_reset (JNIEnv *, jintArray *); + +int +helper_select (JNIEnv *, jclass, jmethodID, + int, fd_set *, fd_set *, fd_set *, struct timeval *); + +void +helper_put_filedescriptors (JNIEnv * env, jintArray fdArray, fd_set * fds, + int *max_fd) +{ + jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0); + int size = (*env)->GetArrayLength (env, fdArray); + int index, fd; + + for (index = 0; index < size; index++) + { + fd = tmpFDArray[index]; + + if (fd > 0) + { + FD_SET (tmpFDArray[index], fds); + + if (tmpFDArray[index] > (*max_fd)) + (*max_fd) = tmpFDArray[index]; + } + } +} + +void +helper_get_filedescriptors (JNIEnv * env, jintArray * fdArray, fd_set * fds) +{ + jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0); + int size = (*env)->GetArrayLength (env, fdArray); + int index, fd; + + for (index = 0; index < size; index++) + { + fd = tmpFDArray[index]; + if (fd < 0 || !FD_ISSET (fd, fds)) + tmpFDArray[index] = 0; + } +} + +void +helper_reset (JNIEnv * env, jintArray * fdArray) +{ + jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0); + int size = (*env)->GetArrayLength (env, fdArray); + int index; + + for (index = 0; index < size; index++) + tmpFDArray[index] = 0; +} + +/* A wrapper for select() which ignores EINTR. + * Taken from gclib's posix.cc + */ +int +helper_select (JNIEnv * env, jclass thread_class, + jmethodID thread_interrupted, int n, fd_set * readfds, + fd_set * writefds, fd_set * exceptfds, struct timeval *timeout) +{ +#ifdef HAVE_SYS_SELECT_H + /* If we have a timeout, compute the absolute ending time. */ + struct timeval end, delay, after; + int r; + + if (timeout) + { + gettimeofday (&end, NULL); + + end.tv_usec += timeout->tv_usec; + + if (end.tv_usec >= 1000000) + { + ++end.tv_sec; + end.tv_usec -= 1000000; + } + + end.tv_sec += timeout->tv_sec; + delay = *timeout; + } + else + { + /* Placate compiler. */ + delay.tv_sec = delay.tv_usec = 0; + } + + while (1) + { + r = select (n, readfds, writefds, exceptfds, timeout ? &delay : NULL); + + if (r < 0 && errno != EINTR) + return -errno; + else if (r >= 0) + return r; + + /* Here we know we got EINTR. */ + if ((*env)-> + CallStaticBooleanMethod (env, thread_class, thread_interrupted)) + { + return -EINTR; + } + + if (timeout) + { + gettimeofday (&after, NULL); + + /* Now compute new timeout argument. */ + delay.tv_usec = end.tv_usec - after.tv_usec; + delay.tv_sec = end.tv_sec - after.tv_sec; + + if (delay.tv_usec < 0) + { + --delay.tv_sec; + delay.tv_usec += 1000000; + } + + if (delay.tv_sec < 0) + { + /* We assume that the user wants a valid select() call + * more than precise timing. So if we get a series of + * EINTR we just keep trying with delay 0 until we get a + * valid result. + */ + delay.tv_sec = 0; + } + } + } +#else /* HAVE_SYS_SELECT_H */ + return 0; +#endif + +} + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMSelector_select (JNIEnv * env, + jclass obj __attribute__ ((__unused__)), + jintArray read, + jintArray write, + jintArray except, jlong timeout) +{ + jint result; + jclass thread_class = (*env)->FindClass (env, "java/lang/Thread"); + jmethodID thread_current_thread = + (*env)->GetStaticMethodID (env, thread_class, "currentThread", + "()Ljava/lang/Thread;"); + jmethodID thread_interrupt = + (*env)->GetMethodID (env, thread_class, "interrupt", "()V"); + jmethodID thread_interrupted = + (*env)->GetStaticMethodID (env, thread_class, "interrupted", "()Z"); + jobject current_thread; + int max_fd = 0; + fd_set read_fds; + fd_set write_fds; + fd_set except_fds; + struct timeval real_time_data; + struct timeval *time_data = NULL; + char message_buf[BUF_SIZE + 1]; + + /* If a legal timeout value isn't given, use NULL. + * This means an infinite timeout. The specification + * also says that a zero timeout should be treated + * as infinite. Otherwise (if the timeout value is legal), + * fill our timeval struct and use it for the select. + */ + if (timeout > 0) + { + real_time_data.tv_sec = timeout / 1000; + real_time_data.tv_usec = (timeout % 1000) * 1000; + time_data = &real_time_data; + } + + /* Reset all fd_set structures */ + FD_ZERO (&read_fds); + FD_ZERO (&write_fds); + FD_ZERO (&except_fds); + + /* Fill the fd_set data structures for the _Jv_select() call. */ + helper_put_filedescriptors (env, read, &read_fds, &max_fd); + helper_put_filedescriptors (env, write, &write_fds, &max_fd); + helper_put_filedescriptors (env, except, &except_fds, &max_fd); + + /* Actually do the select */ + result = + helper_select (env, thread_class, thread_interrupted, max_fd + 1, + &read_fds, &write_fds, &except_fds, time_data); + + if (result == -EINTR) + { + /* The behavior of JRE 1.4.1 is that no exception is thrown + * when the thread is interrupted, but the thread's interrupt + * status is set. Clear all of our select sets and return 0, + * indicating that nothing was selected. + */ + current_thread = + (*env)->CallStaticObjectMethod (env, thread_class, + thread_current_thread); + (*env)->CallVoidMethod (env, current_thread, thread_interrupt); + + helper_reset (env, read); + helper_reset (env, write); + helper_reset (env, except); + + return 0; + } + + if (result < 0) + { + + int errorcode = -result; + + if (strerror_r (errorcode, message_buf, BUF_SIZE)) + { + /* This would mean that message_buf was to small + * to hold the error message. + */ + JCL_ThrowException (env, "java/lang/InternalError", + "Not enough space in message buffer."); + return 0; + } + + JCL_ThrowException (env, "java/io/IOException", message_buf); + return 0; + } + + /* Set the file descriptors according to the values returned from select(). */ + helper_get_filedescriptors (env, read, &read_fds); + helper_get_filedescriptors (env, write, &write_fds); + helper_get_filedescriptors (env, except, &except_fds); + + return result; +} diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c new file mode 100644 index 00000000000..743e12a8f30 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c @@ -0,0 +1,793 @@ +/* gnu_java_nio_channels_FileChannelImpl.c - + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> +#include <errno.h> + +#include <jni.h> +#include <jcl.h> + +#include "target_native.h" +#ifndef WITHOUT_FILESYSTEM +#include "target_native_file.h" +#endif +#include "target_native_math_int.h" + +#include "gnu_java_nio_channels_FileChannelImpl.h" + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif /* HAVE_FCNTL_H */ + +/* These values must be kept in sync with FileChannelImpl.java. */ +#define FILECHANNELIMPL_READ 1 +#define FILECHANNELIMPL_WRITE 2 +#define FILECHANNELIMPL_APPEND 4 + +/* These values must be kept in sync with FileChannelImpl.java. */ +/* #define FILECHANNELIMPL_FILESEEK_SET 0 */ +/* #define FILECHANNELIMPL_FILESEEK_CUR 1 */ +/* #define FILECHANNELIMPL_FILESEEK_END 2 */ + +#define FILECHANNELIMPL_FILEOPEN_FLAG_READ 1 +#define FILECHANNELIMPL_FILEOPEN_FLAG_WRITE 2 +#define FILECHANNELIMPL_FILEOPEN_FLAG_APPEND 4 +#define FILECHANNELIMPL_FILEOPEN_FLAG_EXCL 8 +#define FILECHANNELIMPL_FILEOPEN_FLAG_SYNC 16 +#define FILECHANNELIMPL_FILEOPEN_FLAG_DSYNC 32 + +#define IO_EXCEPTION "java/io/IOException" + +/* FIXME: This can't be right. Need converter macros. */ +#define CONVERT_JLONG_TO_INT(x) TARGET_NATIVE_MATH_INT_INT64_TO_INT32(x) +#define CONVERT_INT_TO_JLONG(x) TARGET_NATIVE_MATH_INT_INT32_TO_INT64(x) + +/* FIXME: This can't be right. Need converter macros. */ +#define CONVERT_JLONG_TO_OFF_T(x) TARGET_NATIVE_MATH_INT_INT64_TO_INT32(x) +#define CONVERT_OFF_T_TO_JLONG(x) TARGET_NATIVE_MATH_INT_INT32_TO_INT64(x) + +/* FIXME: This can't be right. Need converter macros */ +#define CONVERT_JINT_TO_INT(x) ((int)(x & 0xFFFFFFFF)) +#define CONVERT_INT_TO_JINT(x) ((int)(x & 0xFFFFFFFF)) + +/* FIXME: This can't be right. Need converter macros. */ +#define CONVERT_SSIZE_T_TO_JINT(x) ((jint)(x & 0xFFFFFFFF)) +#define CONVERT_JINT_TO_SSIZE_T(x) (x) + +/* cached fieldID of gnu.java.nio.channels.FileChannelImpl.fd */ +static jfieldID native_fd_fieldID; + +static jint +get_native_fd (JNIEnv * env, jobject obj) +{ + return (*env)->GetIntField (env, obj, native_fd_fieldID); +} + +/* + * Library initialization routine. Called as part of java.io.FileDescriptor + * static initialization. + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_init (JNIEnv * env, jclass clazz) +{ + jclass clazz_fc; + jfieldID field; + jmethodID constructor; + jobject obj; + + /* Initialize native_fd_fieldID so we only compute it once! */ + clazz_fc = (*env)->FindClass (env, "gnu/java/nio/channels/FileChannelImpl"); + if (!clazz_fc) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error"); + return; + } + + field = (*env)->GetFieldID (env, clazz_fc, "fd", "I"); + if (!field) + { + JCL_ThrowException (env, IO_EXCEPTION, "Internal error"); + return; + } + + native_fd_fieldID = field; + + constructor = (*env)->GetMethodID (env, clazz, "<init>", "(II)V"); + if (!constructor) + return; + +#define INIT_FIELD(FIELDNAME, FDVALUE, MODE) \ + field = (*env)->GetStaticFieldID (env, clazz, FIELDNAME, \ + "Lgnu/java/nio/channels/FileChannelImpl;"); \ + if (! field) \ + return; \ + obj = (*env)->NewObject (env, clazz, constructor, FDVALUE, MODE); \ + if (! obj) \ + return; \ + (*env)->SetStaticObjectField (env, clazz, field, obj); \ + if ((*env)->ExceptionOccurred (env)) \ + return; + + INIT_FIELD ("in", 0, FILECHANNELIMPL_READ); + INIT_FIELD ("out", 1, FILECHANNELIMPL_WRITE); + INIT_FIELD ("err", 2, FILECHANNELIMPL_WRITE); + +#undef INIT_FIELD +} + +/* + * Open the specified file and return a native file descriptor + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_open (JNIEnv * env, + jobject obj + __attribute__ ((__unused__)), + jstring name, jint mode) +{ + const char *filename; + int flags; + int permissions; + int native_fd; + int result; + + filename = JCL_jstring_to_cstring (env, name); + if (filename == NULL) + return (-1); /* Exception will already have been thrown */ + + /* get file/permission flags for open() */ + if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_READ) + && (mode & FILECHANNELIMPL_FILEOPEN_FLAG_WRITE)) + { + /* read/write */ + flags = + TARGET_NATIVE_FILE_FILEFLAG_CREATE | + TARGET_NATIVE_FILE_FILEFLAG_READWRITE; + permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL; + } + else if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_READ)) + { + /* read */ + flags = TARGET_NATIVE_FILE_FILEFLAG_READ; + permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL; + } + else + { + /* write */ + flags = + TARGET_NATIVE_FILE_FILEFLAG_CREATE | + TARGET_NATIVE_FILE_FILEFLAG_WRITE; + if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_APPEND)) + { + flags |= TARGET_NATIVE_FILE_FILEFLAG_APPEND; + } + else + { + flags |= TARGET_NATIVE_FILE_FILEFLAG_TRUNCATE; + } + permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL; + } + + if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_SYNC)) + { + flags |= TARGET_NATIVE_FILE_FILEFLAG_SYNC; + } + + if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_DSYNC)) + { + flags |= TARGET_NATIVE_FILE_FILEFLAG_DSYNC; + } +#ifdef O_BINARY + flags |= TARGET_NATIVE_FILE_FILEFLAG_BINARY; +#endif + + TARGET_NATIVE_FILE_OPEN (filename, native_fd, flags, permissions, result); + JCL_free_cstring (env, name, filename); + + if (result != TARGET_NATIVE_OK) + { + /* We can only throw FileNotFoundException. */ + JCL_ThrowException (env, + "java/io/FileNotFoundException", + TARGET_NATIVE_LAST_ERROR_STRING ()); + return TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1; + } + + return native_fd; +} + +/* + * Closes the specified file descriptor and return status code. + * Exception on error + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_implCloseChannel (JNIEnv * env, + jobject obj) +{ + int native_fd; + int result; + + native_fd = get_native_fd (env, obj); + + TARGET_NATIVE_FILE_CLOSE (native_fd, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + } +} + +/* + * Return number of bytes that can be read from the file w/o blocking. + * Exception on error + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_available (JNIEnv * env, + jobject obj) +{ + int native_fd; + jlong bytes_available; + int result; + + native_fd = get_native_fd (env, obj); + + TARGET_NATIVE_FILE_AVAILABLE (native_fd, bytes_available, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return 0; + } + + /* FIXME NYI ??? why only jint and not jlong? */ + return TARGET_NATIVE_MATH_INT_INT64_TO_INT32 (bytes_available); +} + +JNIEXPORT jlong JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_size (JNIEnv * env, jobject obj) +{ + int native_fd; + jlong file_size; + int result; + + native_fd = get_native_fd (env, obj); + + TARGET_NATIVE_FILE_SIZE (native_fd, file_size, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1; + } + + return file_size; +} + +/* + * Return the current position of the file pointer + * Exception on error + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_implPosition (JNIEnv * env, + jobject obj) +{ + int native_fd; + jlong current_offset; + int result; + + native_fd = get_native_fd (env, obj); + + TARGET_NATIVE_FILE_TELL (native_fd, current_offset, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1; + } + + return current_offset; +} + +/* + * Wrapper around lseek call. Return new file position + * Exception on error + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_seek (JNIEnv * env, jobject obj, + jlong offset) +{ + int native_fd; + jlong new_offset; + int result; + + native_fd = get_native_fd (env, obj); + +#if 0 + /* Should there be such an exception? All native layer macros should + be accepting 64bit-values if needed. It some target is not able + to handle such values it should simply operate with 32bit-values + and convert 64bit-values appriopated. In this case I assume + problems should not occurre: if some specific target is not able + to handle 64bit-values the system is limited to 32bit at all, thus + the application can not do a seek() or something else beyond the + 32bit limit. It this true? + */ + + /* FIXME: What do we do if offset > the max value of off_t on this 32bit + * system? How do we detect that and what do we do? */ + if (CONVERT_OFF_T_TO_JLONG (native_offset) != offset) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Cannot represent position correctly on this system"); + } +#endif /* 0 */ + + result = TARGET_NATIVE_ERROR; + new_offset = TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1; + TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, offset, new_offset, result); + + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + } +} + +/* + * Set the length of the file + * Exception on error + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_implTruncate (JNIEnv * env, + jobject obj, + jlong len) +{ + int native_fd; + jlong file_size; + int bytes_written; + jlong save_offset, new_offset; + char data; + int result; + + native_fd = get_native_fd (env, obj); + +#if 0 + /* Should there be such an exception? All native layer macros should + be accepting 64bit-values if needed. It some target is not able + to handle such values it should simply operate with 32bit-values + and convert 64bit-values appriopated. In this case I assume + problems should not occurre: if some specific target is not able + to handle 64bit-values the system is limited to 32bit at all, thus + the application can not do a seek() or something else beyond the + 32bit limit. It this true? + */ + + /* FIXME: What do we do if len > the max value of off_t on this 32bit + * system? How do we detect that and what do we do? */ + if (CONVERT_OFF_T_TO_JLONG (native_len) != len) + { + JCL_ThrowException (env, IO_EXCEPTION, + "Cannot represent position correctly on this system"); + return; + } +#endif /* 0 */ + + /* get file size */ + TARGET_NATIVE_FILE_SIZE (native_fd, file_size, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + /* Save off current position */ + TARGET_NATIVE_FILE_TELL (native_fd, save_offset, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + if (TARGET_NATIVE_MATH_INT_INT64_LT (file_size, len)) + { + /* File is too short -- seek to one byte short of where we want, + * then write a byte */ + + /* move to position n-1 */ + TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, + TARGET_NATIVE_MATH_INT_INT64_SUB (len, + 1), + new_offset, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + /* write a byte + Note: This will fail if we somehow get here in read only mode + * That shouldn't happen */ + data = '\0'; + TARGET_NATIVE_FILE_WRITE (native_fd, &data, 1, bytes_written, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + + /* Reposition file pointer to where we started if not beyond new len. */ + if (TARGET_NATIVE_MATH_INT_INT64_LT (save_offset, len)) + { + TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, save_offset, + new_offset, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + } + } + else if (TARGET_NATIVE_MATH_INT_INT64_GT (file_size, len)) + { + /* File is too long - use ftruncate if available */ +#ifdef HAVE_FTRUNCATE + TARGET_NATIVE_FILE_TRUNCATE (native_fd, len, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } +#else /* HAVE_FTRUNCATE */ + /* FIXME: Probably operation isn't supported, but this exception + * is too harsh as it will probably crash the program without need + JCL_ThrowException(env, "java/lang/UnsupportedOperationException", + "not implemented - can't shorten files on this platform"); + */ + JCL_ThrowException (env, IO_EXCEPTION, "Unable to shorten file length"); +#endif /* HAVE_FTRUNCATE */ + + /* Reposition file pointer when it now is beyond the end of file. */ + if (TARGET_NATIVE_MATH_INT_INT64_GT (save_offset, len)) + { + TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, len, new_offset, result); + if (result != TARGET_NATIVE_OK) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + } + } +} + +JNIEXPORT jobject JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_mapImpl (JNIEnv * env, + jobject obj + __attribute__ ((__unused__)), jchar mode __attribute__ ((__unused__)), jlong position __attribute__ ((__unused__)), jint size __attribute__ ((__unused__))) +{ + JCL_ThrowException (env, IO_EXCEPTION, + "java.nio.FileChannelImpl.nio_mmap_file(): not implemented"); + return 0; +} + +/* + * Read a single byte from the file descriptor + * Return byte read or -1 on eof, exception on error + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_read__ (JNIEnv * env, jobject obj) +{ + int native_fd; + char data; + ssize_t bytes_read; + int result; + + native_fd = get_native_fd (env, obj); + + bytes_read = 0; + do + { + TARGET_NATIVE_FILE_READ (native_fd, &data, 1, bytes_read, result); + if ((result == TARGET_NATIVE_OK) && (bytes_read == 0)) + { + return (-1); + } + if ((result != TARGET_NATIVE_OK) + && (TARGET_NATIVE_LAST_ERROR () != + TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return (-1); + } + } + while (result != TARGET_NATIVE_OK); + + return ((jint) (data & 0xFF)); +} + +/* + * Reads to a byte buffer from the specified file descriptor + * Return number of bytes read or -1 on eof, exception on error + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_read___3BII (JNIEnv * env, + jobject obj, + jbyteArray buffer, + jint offset, + jint length) +{ + int native_fd; + jbyte *bufptr; + ssize_t bytes_read; + ssize_t n; + int result; + + native_fd = get_native_fd (env, obj); + + /* Must return 0 if an attempt is made to read 0 bytes. */ + if (length == 0) + return 0; + + if (offset < 0) + { + JCL_ThrowException (env, IO_EXCEPTION, "negative offset"); + return -1; + } + + bufptr = (*env)->GetByteArrayElements (env, buffer, 0); + if (!bufptr) + { + JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error"); + return (-1); + } + + if (length + offset > (*env)->GetArrayLength (env, buffer)) + { + JCL_ThrowException (env, IO_EXCEPTION, + "length + offset > buffer.length"); + return -1; + } + + bytes_read = 0; + do + { + TARGET_NATIVE_FILE_READ (native_fd, (bufptr + offset + bytes_read), + (length - bytes_read), n, result); + if ((result == TARGET_NATIVE_OK) && (n == 0)) + { + (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0); + if (bytes_read == 0) + return -1; /* Signal end of file to Java */ + else + return CONVERT_SSIZE_T_TO_JINT (bytes_read); + } + if ((result != TARGET_NATIVE_OK) + && (TARGET_NATIVE_LAST_ERROR () != + TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0); + return -1; + } + if (result == TARGET_NATIVE_OK) + bytes_read += n; + } + while (bytes_read < 1); + + (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0); + return CONVERT_SSIZE_T_TO_JINT (bytes_read); +} + +/* + * Writes a single byte to the specified file descriptor + * Return status code, exception on error + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_write__I (JNIEnv * env, + jobject obj, jint b) +{ + int native_fd; + char native_data; + ssize_t bytes_written; + int result; + + native_fd = get_native_fd (env, obj); + native_data = (char) (CONVERT_JINT_TO_INT (b) & 0xFF); + + do + { + TARGET_NATIVE_FILE_WRITE (native_fd, &native_data, 1, bytes_written, + result); + if ((result != TARGET_NATIVE_OK) + && (TARGET_NATIVE_LAST_ERROR () != + TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + return; + } + } + while (result != TARGET_NATIVE_OK); +} + +/* + * Copies all parts of a file to disk. + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_force (JNIEnv * env, + jobject obj) +{ + int native_fd; + int result; + native_fd = get_native_fd (env, obj); + TARGET_NATIVE_FILE_FSYNC (native_fd, result); + if (result != TARGET_NATIVE_OK) + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); +} + +/* + * Writes a byte buffer to the specified file descriptor + * Return status code, exception on error + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_write___3BII (JNIEnv * env, + jobject obj, + jbyteArray buffer, + jint offset, + jint length) +{ + int native_fd; + jbyte *bufptr; + ssize_t bytes_written; + ssize_t n; + int result; + + native_fd = get_native_fd (env, obj); + + /* Just return if an attempt is made to write 0 bytes. */ + if (length == 0) + return; + + bufptr = (*env)->GetByteArrayElements (env, buffer, 0); + if (!bufptr) + { + JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error"); + return; + } + + bytes_written = 0; + while (bytes_written < CONVERT_JINT_TO_SSIZE_T (length)) + { + TARGET_NATIVE_FILE_WRITE (native_fd, (bufptr + offset + bytes_written), + (length - bytes_written), n, result); + if ((result != TARGET_NATIVE_OK) + && (TARGET_NATIVE_LAST_ERROR () != + TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) + { + JCL_ThrowException (env, IO_EXCEPTION, + TARGET_NATIVE_LAST_ERROR_STRING ()); + (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0); + return; + } + if (result == TARGET_NATIVE_OK) + bytes_written += n; + } + + (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_lock (JNIEnv *env, jobject obj, + jlong position, jlong size, + jboolean shared, jboolean wait) +{ +#ifdef HAVE_FCNTL + int fd = get_native_fd (env, obj); + int cmd = wait ? F_SETLKW : F_SETLK; + struct flock flock; + int ret; + + flock.l_type = shared ? F_RDLCK : F_WRLCK; + flock.l_whence = SEEK_SET; + flock.l_start = (off_t) position; + flock.l_len = (off_t) size; + + ret = fcntl (fd, cmd, &flock); + if (ret) + { + /* Linux man pages for fcntl state that errno might be either + EACCES or EAGAIN if we try F_SETLK, and another process has + an overlapping lock. */ + if (errno != EACCES && errno != EAGAIN) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } + return JNI_FALSE; + } + return JNI_TRUE; +#else + (void) obj; + (void) position; + (void) size; + (void) shared; + (void) wait; + JCL_ThrowException (env, "java/lang/UnsupportedOperationException", + "file locks not implemented on this platform"); + return JNI_FALSE; +#endif /* HAVE_FCNTL */ +} + +JNIEXPORT void JNICALL +Java_gnu_java_nio_channels_FileChannelImpl_unlock (JNIEnv *env, + jobject obj, + jlong position, + jlong length) +{ +#ifdef HAVE_FCNTL + int fd = get_native_fd (env, obj); + struct flock flock; + int ret; + + flock.l_type = F_UNLCK; + flock.l_whence = SEEK_SET; + flock.l_start = (off_t) position; + flock.l_len = (off_t) length; + + ret = fcntl (fd, F_SETLK, &flock); + if (ret) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +#else + (void) obj; + (void) position; + (void) length; + JCL_ThrowException (env, "java/lang/UnsupportedOperationException", + "file locks not implemented on this platform"); +#endif /* HAVE_FCNTL */ +} diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvDecoder.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvDecoder.c new file mode 100644 index 00000000000..8c3f83accff --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvDecoder.c @@ -0,0 +1,219 @@ +/* gnu_java_nio_charset_iconv_IconvDecoder.c -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include <config.h> +#include <jcl.h> + +#include <stdio.h> +#include <assert.h> +#include <errno.h> + +#if defined(HAVE_ICONV) +#include <iconv.h> +#endif + +#include "gnu_java_nio_charset_iconv_IconvDecoder.h" + +static void createRawData (JNIEnv * env, jobject obj, void *ptr); +static void *getData (JNIEnv * env, jobject obj); + +static jfieldID infid = NULL; +static jfieldID outfid = NULL; + +/* Union used for type punning. */ +union char_union +{ + jbyte **jb; + jchar **jc; + char **c; +}; + +JNIEXPORT void JNICALL +Java_gnu_java_nio_charset_iconv_IconvDecoder_openIconv (JNIEnv * env, + jobject obj, + jstring jname) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object; + jclass cls; + + const char *name = JCL_jstring_to_cstring (env, jname); + if (name == NULL) + return; + + /* Cache fieldIDs for use in decode function. */ + if (infid == NULL || outfid == NULL) + { + cls = (*env)->GetObjectClass (env, obj); + infid = (*env)->GetFieldID (env, cls, "inremaining", "I"); + assert (infid != 0); + outfid = (*env)->GetFieldID (env, cls, "outremaining", "I"); + assert (outfid != 0); + } + + /* to java from "name", native java format depends on endianness */ +#ifdef WORDS_BIGENDIAN + iconv_object = iconv_open ("UTF-16BE", name); +#else + iconv_object = iconv_open ("UTF-16LE", name); +#endif + + JCL_free_cstring (env, jname, name); + if ((long) iconv_object == -1L) + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Charset not available"); + return; + } + createRawData (env, obj, (void *) iconv_object); +#else + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "iconv not available"); +#endif +} + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_charset_iconv_IconvDecoder_decode (JNIEnv * env, + jobject obj, + jbyteArray inArr, + jcharArray outArr, + jint posIn, jint remIn, + jint posOut, jint remOut) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object = getData (env, obj); + size_t retval; + union char_union in, out; + jbyte *input, *inputcopy; + jchar *output, *outputcopy; + size_t lenIn = (size_t) remIn; + size_t lenOut = (size_t) remOut * 2; + + inputcopy = input = (*env)->GetByteArrayElements (env, inArr, 0); + outputcopy = output = (*env)->GetCharArrayElements (env, outArr, 0); + + input += posIn; + output += posOut; + + in.jb = &input; + out.jc = &output; + retval = iconv (iconv_object, (ICONV_CONST char **) in.c, &lenIn, + out.c, &lenOut); + + /* XXX: Do we need to relase the input array? It's not modified. */ + (*env)->ReleaseByteArrayElements (env, inArr, inputcopy, 0); + (*env)->ReleaseCharArrayElements (env, outArr, outputcopy, 0); + + if (retval == (size_t) (-1)) + { + if (errno == EILSEQ || errno == EINVAL) + retval = 1; + else + retval = 0; + } + else + retval = 0; + + (*env)->SetIntField (env, obj, infid, (jint) lenIn); + (*env)->SetIntField (env, obj, outfid, (jint) (lenOut >> 1)); + + return (jint) retval; +#else + return -1; +#endif +} + +JNIEXPORT void JNICALL +Java_gnu_java_nio_charset_iconv_IconvDecoder_closeIconv (JNIEnv * env, + jobject obj) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object; + iconv_object = getData (env, obj); + iconv_close (iconv_object); +#endif +} + + +static void +createRawData (JNIEnv * env, jobject obj, void *ptr) +{ + jclass cls; + jmethodID method; + jobject data; + jfieldID data_fid; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/RawData;"); + assert (data_fid != 0); + +#ifdef POINTERS_ARE_64BIT + cls = (*env)->FindClass (env, "gnu/classpath/RawData64"); + method = (*env)->GetMethodID (env, cls, "<init>", "(J)V"); + data = (*env)->NewObject (env, cls, method, (jlong) ptr); +#else + cls = (*env)->FindClass (env, "gnu/classpath/RawData32"); + method = (*env)->GetMethodID (env, cls, "<init>", "(I)V"); + data = (*env)->NewObject (env, cls, method, (jint) ptr); +#endif + + (*env)->SetObjectField (env, obj, data_fid, data); +} + +static void * +getData (JNIEnv * env, jobject obj) +{ + jclass cls; + jfieldID field; + jfieldID data_fid; + jobject data; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/RawData;"); + assert (data_fid != 0); + data = (*env)->GetObjectField (env, obj, data_fid); + +#if SIZEOF_VOID_P == 8 + cls = (*env)->FindClass (env, "gnu/classpath/RawData64"); + field = (*env)->GetFieldID (env, cls, "data", "J"); + return (void *) (*env)->GetLongField (env, data, field); +#else + cls = (*env)->FindClass (env, "gnu/classpath/RawData32"); + field = (*env)->GetFieldID (env, cls, "data", "I"); + return (void *) (*env)->GetIntField (env, data, field); +#endif +} diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvEncoder.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvEncoder.c new file mode 100644 index 00000000000..cd5d48656f7 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvEncoder.c @@ -0,0 +1,219 @@ +/* gnu_java_nio_charset_iconv_IconvEncoder.c -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include <config.h> +#include <jcl.h> + +#include <stdio.h> +#include <assert.h> +#include <errno.h> + +#if defined(HAVE_ICONV) +#include <iconv.h> +#endif + +#include "gnu_java_nio_charset_iconv_IconvEncoder.h" + +static void createRawData (JNIEnv * env, jobject obj, void *ptr); +static void *getData (JNIEnv * env, jobject obj); + +static jfieldID infid = NULL; +static jfieldID outfid = NULL; + +/* Union used for type punning. */ +union char_union +{ + jbyte **jb; + jchar **jc; + char **c; +}; + +JNIEXPORT void JNICALL +Java_gnu_java_nio_charset_iconv_IconvEncoder_openIconv (JNIEnv * env, + jobject obj, + jstring jname) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object; + jclass cls; + + const char *name = JCL_jstring_to_cstring (env, jname); + if (name == NULL) + return; + + /* Cache fieldIDs for use in encode function. */ + if (infid == NULL || outfid == NULL) + { + cls = (*env)->GetObjectClass (env, obj); + infid = (*env)->GetFieldID (env, cls, "inremaining", "I"); + assert (infid != 0); + outfid = (*env)->GetFieldID (env, cls, "outremaining", "I"); + assert (outfid != 0); + } + + /* to "name" from java, native java format depends on endianness */ +#ifdef WORDS_BIGENDIAN + iconv_object = iconv_open (name, "UTF-16BE"); +#else + iconv_object = iconv_open (name, "UTF-16LE"); +#endif + + JCL_free_cstring (env, jname, name); + if ((long) iconv_object == -1L) + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Charset not available"); + return; + } + createRawData (env, obj, (void *) iconv_object); +#else + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "iconv not available"); +#endif +} + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_charset_iconv_IconvEncoder_encode (JNIEnv * env, + jobject obj, + jcharArray inArr, + jbyteArray outArr, + jint posIn, jint remIn, + jint posOut, jint remOut) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object = getData (env, obj); + size_t retval; + union char_union in, out; + jchar *input, *inputcopy; + jbyte *output, *outputcopy; + size_t lenIn = (size_t) remIn * 2; + size_t lenOut = (size_t) remOut; + + inputcopy = input = (*env)->GetCharArrayElements (env, inArr, 0); + outputcopy = output = (*env)->GetByteArrayElements (env, outArr, 0); + + input += posIn; + output += posOut; + + in.jc = &input; + out.jb = &output; + retval = iconv (iconv_object, (ICONV_CONST char **) in.c, &lenIn, + out.c, &lenOut); + + /* XXX: Do we need to relase the input array? It's not modified. */ + (*env)->ReleaseCharArrayElements (env, inArr, inputcopy, 0); + (*env)->ReleaseByteArrayElements (env, outArr, outputcopy, 0); + + if (retval == (size_t) (-1)) + { + if (errno == EILSEQ || errno == EINVAL) + retval = 1; + else + retval = 0; + } + else + retval = 0; + + (*env)->SetIntField (env, obj, infid, (jint) (lenIn >> 1)); + (*env)->SetIntField (env, obj, outfid, (jint) lenOut); + + return (jint) retval; +#else + return -1; +#endif +} + +JNIEXPORT void JNICALL +Java_gnu_java_nio_charset_iconv_IconvEncoder_closeIconv (JNIEnv * env, + jobject obj) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object; + iconv_object = getData (env, obj); + iconv_close (iconv_object); +#endif +} + + +static void +createRawData (JNIEnv * env, jobject obj, void *ptr) +{ + jclass cls; + jmethodID method; + jobject data; + jfieldID data_fid; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/RawData;"); + assert (data_fid != 0); + +#ifdef POINTERS_ARE_64BIT + cls = (*env)->FindClass (env, "gnu/classpath/RawData64"); + method = (*env)->GetMethodID (env, cls, "<init>", "(J)V"); + data = (*env)->NewObject (env, cls, method, (jlong) ptr); +#else + cls = (*env)->FindClass (env, "gnu/classpath/RawData32"); + method = (*env)->GetMethodID (env, cls, "<init>", "(I)V"); + data = (*env)->NewObject (env, cls, method, (jint) ptr); +#endif + + (*env)->SetObjectField (env, obj, data_fid, data); +} + +static void * +getData (JNIEnv * env, jobject obj) +{ + jclass cls; + jfieldID field; + jfieldID data_fid; + jobject data; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/RawData;"); + assert (data_fid != 0); + data = (*env)->GetObjectField (env, obj, data_fid); + +#if SIZEOF_VOID_P == 8 + cls = (*env)->FindClass (env, "gnu/classpath/RawData64"); + field = (*env)->GetFieldID (env, cls, "data", "J"); + return (void *) (*env)->GetLongField (env, data, field); +#else + cls = (*env)->FindClass (env, "gnu/classpath/RawData32"); + field = (*env)->GetFieldID (env, cls, "data", "I"); + return (void *) (*env)->GetIntField (env, data, field); +#endif +} diff --git a/libjava/classpath/native/jni/java-nio/java_nio.c b/libjava/classpath/native/jni/java-nio/java_nio.c new file mode 100644 index 00000000000..a25f38a6d2a --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/java_nio.c @@ -0,0 +1,328 @@ +/* java_nio.c - Native methods for gnu.java.nio.FileChannelImpl class + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#ifdef HAVE_MMAP +#include <sys/mman.h> +#endif + +#include <jni.h> +#include <jcl.h> + +#include "target_native.h" +#ifndef WITHOUT_NETWORK +#include "target_native_network.h" +#endif /* WITHOUT_NETWORK */ + +#include "java_nio_channels_FileChannelImpl.h" + +#include "javaio.h" + +#define NIO_DEBUG(X) /* no debug */ +//#define NIO_DEBUG(X) X + +/*************************************** + * + * File Channel implementation + * + *************/ + + +static char * +compare (int i, int lim, char *buffer) +{ + sprintf (buffer, "(%d >= %d)", i, lim); + return buffer; +} + +static inline int +convert_Int (int X) +{ + unsigned char *a = (unsigned char *) &X; + int res = + (((int) a[0]) << 24) + + (((int) a[1]) << 16) + (((int) a[2]) << 8) + (((int) a[3]) << 0); + return res; +} + +static inline jlong +convert_Long (jlong X) +{ + unsigned char *a = (unsigned char *) &X; + int res1 = + (((int) a[0]) << 24) + + (((int) a[1]) << 16) + (((int) a[2]) << 8) + (((int) a[3]) << 0); + int res2; + a += 4; + res2 = + (((int) a[0]) << 24) + + (((int) a[1]) << 16) + (((int) a[2]) << 8) + (((int) a[3]) << 0); + return ((jlong) res1) | ((jlong) res2) << 32LL; +} + +static inline short +convert_Short (short X) +{ + unsigned char *a = (unsigned char *) &X; + int res = (((int) a[2]) << 8) + (((int) a[3]) << 0); + return res; +} +static inline short +convert_Char (short X) +{ + unsigned char *a = (unsigned char *) &X; + int res = (((int) a[2]) << 8) + (((int) a[3]) << 0); + return res; +} + +static inline unsigned char +convert_Byte (unsigned char X) +{ + return X; +} + +static inline float +convert_Float (float X) +{ + return X; +} + +static inline double +convert_Double (double X) +{ + return X; +} + + +// Note: do to many get()'s on a buffer and you should throw a BufferUnderflowException +// Alas, I only found this out during testing.... + +#define READ_WRITE_MMAPED_FILE(TYPE,ELT) \ + \ +ELT Java_gnu_java_nio_MappedByteFileBuffer_nio_1read_1 ## TYPE ## _1file_1channel(JNIEnv *env, \ + jclass c, jobject b, \ + int index, int limit, jlong jaddress) \ +{ \ + char *address = *(void **) &jaddress; char buffer[128]; \ + if (index >= limit) JCL_ThrowException(env, "java/nio/BufferUnderflowException", compare(index,limit, buffer)); \ + NIO_DEBUG( fprintf(stderr, "READ:index = %d [0]=%c [1]=%c\n", index, address[0],address[1]); ) \ + address += index; \ + return convert_ ## TYPE (*(ELT *) address); \ +} \ + \ +void Java_gnu_java_nio_MappedByteFileBuffer_nio_1write_1 ## TYPE ## _1file_1channel(JNIEnv *env, \ + jclass c, jobject b, \ + int index, int limit, ELT value, jlong jaddress) \ +{ \ + \ + char *address = *(void **) &jaddress; char buffer[128]; \ + if (index >= limit) JCL_ThrowException(env, "java/nio/BufferUnderflowException", compare(index,limit, buffer)); \ +NIO_DEBUG( fprintf(stderr, "WRITE:index = %d [0]=%c [1]=%c\n", index, address[0],address[1]); ) \ + address += index; \ + *(ELT *) address = value; \ +} \ + \ +ELT Java_gnu_java_nio_MappedByteFileBuffer_nio_1get_1 ## TYPE(JNIEnv *env, jclass c, jobject b, \ + int index, int limit, jlong jaddress) \ +{ \ + fprintf(stderr, "unimplemented\n"); return 0; \ +} \ + \ +void Java_gnu_java_nio_MappedByteFileBuffer_nio_1put_1 ## TYPE(JNIEnv *env, jclass c, jobject b, \ + int index, int limit, \ + ELT value, jlong jaddress) \ +{ \ + fprintf(stderr, "unimplemented\n"); \ +} + +READ_WRITE_MMAPED_FILE (Byte, u_int8_t); +READ_WRITE_MMAPED_FILE (Char, u_int16_t); +READ_WRITE_MMAPED_FILE (Short, u_int16_t); +READ_WRITE_MMAPED_FILE (Int, u_int32_t); +READ_WRITE_MMAPED_FILE (Long, u_int64_t); +READ_WRITE_MMAPED_FILE (Float, float); +READ_WRITE_MMAPED_FILE (Double, double); + +u_int64_t +nio_mmap_file (jint fd, jlong pos, jint size, jint jflags) +{ +#ifdef HAVE_MMAP + u_int64_t ret = 0; + void *address; + + int flags = (jflags != 2) ? MAP_SHARED : MAP_PRIVATE; + int prot = PROT_READ; + + if (jflags == 1) + prot |= PROT_WRITE; + + // fprintf(stderr, "mapping file: %d\n", fd); + + address = mmap (0, size, prot, flags, fd, pos); + + if (address == (void *) -1) + { + perror ("mapping file failed"); + return 0; + } + + // fprintf(stderr, "address = %p, fd = %d, pos=%lld, size=%d\n", address, fd, pos, size); + + *(void **) &ret = address; + + return ret; +#else /* not HAVE_MMAP */ + return (TARGET_NATIVE_MATH_INT_INT64_CONST_0); +#endif /* not HAVE_MMAP */ +} + + +void +nio_msync (int fd, jlong jaddress, int size) +{ +#ifdef HAVE_MMAP + int res; + char *address = *(void **) &jaddress; + + // fprintf(stderr, "synchronizing with file (%p -> %d bytes (%s))\n", address, size, address); + + res = msync (address, size, MS_SYNC | MS_INVALIDATE); + + if (res == -1) + { + perror ("synchronize with file failed"); + } +#else /* not HAVE_MMAP */ +#endif /* not HAVE_MMAP */ +} + +void +nio_unmmap_file (int fd, jlong jaddress, int size) +{ +#ifdef HAVE_MMAP + int res = 0; + char *address = *(void **) &jaddress; + + // nio_msync(fd, jaddress, size); + + // fprintf(stderr, "unmapping (%p -> %d bytes)\n", address, size); + + res = munmap (address, size); + if (res == -1) + { + perror ("un-mapping file failed"); + } +#else /* not HAVE_MMAP */ +#endif /* not HAVE_MMAP */ +} + + +/*************************************** + * + * Socket Channel implementation + * + *************/ + +/*************************************************************************/ + +/* + * Returns a 32 bit Internet address for the passed in InetAddress object + * Ronald: This is a verbatim copy from javanet.c. + * It's a copy to avoid a link error in orp. + */ + +static int +socket_channel_get_net_addr (JNIEnv * env, jobject addr) +{ +#ifndef WITHOUT_NETWORK + jclass cls = 0; + jmethodID mid; + jarray arr = 0; + jbyte *octets; + int netaddr, len; + + DBG + ("socket_channel_get_net_addr(): Entered socket_channel_get_net_addr\n"); + + /* Call the getAddress method on the object to retrieve the IP address */ + cls = (*env)->GetObjectClass (env, addr); + if (cls == NULL) + return (0); + + mid = (*env)->GetMethodID (env, cls, "getAddress", "()[B"); + if (mid == NULL) + return (0); + + DBG ("socket_channel_get_net_addr(): Got getAddress method\n"); + + arr = (*env)->CallObjectMethod (env, addr, mid); + if (arr == NULL) + return (0); + + DBG ("socket_channel_get_net_addr(): Got the address\n"); + + /* Turn the IP address into a 32 bit Internet address in network byte order */ + len = (*env)->GetArrayLength (env, arr); + if (len != 4) + { + JCL_ThrowException (env, "java/io/IOException", + "Internal Error: invalid byte array length"); + return (0); + } + DBG ("socket_channel_get_net_addr(): Length ok\n"); + + octets = (*env)->GetByteArrayElements (env, arr, 0); + if (octets == NULL) + return (0); + + DBG ("socket_channel_get_net_addr(): Grabbed bytes\n"); + + TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets[0], + octets[1], + octets[2], + octets[3], netaddr); + + (*env)->ReleaseByteArrayElements (env, arr, octets, 0); + DBG ("socket_channel_get_net_addr(): Done getting addr\n"); + + return netaddr; +#else /* not WITHOUT_NETWORK */ + return (0); +#endif /* not WITHOUT_NETWORK */ +} diff --git a/libjava/classpath/native/jni/java-nio/java_nio_MappedByteBufferImpl.c b/libjava/classpath/native/jni/java-nio/java_nio_MappedByteBufferImpl.c new file mode 100644 index 00000000000..e1ba1e454f0 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/java_nio_MappedByteBufferImpl.c @@ -0,0 +1,83 @@ +/* java_nio_MappedByteBufferImpl.c - Native methods for MappedByteBufferImpl + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include <config.h> +#include <errno.h> + +#include <jni.h> +#include <jcl.h> + +#include "java_nio_MappedByteBufferImpl.h" + +#define IO_EXCEPTION "java/io/IOException" + +JNIEXPORT void JNICALL +Java_java_nio_MappedByteBufferImpl_unmapImpl (JNIEnv * env, + jclass class + __attribute__ ((__unused__))) +{ + JCL_ThrowException (env, IO_EXCEPTION, + "java.nio.MappedByteBufferImpl.unmapImpl(): not implemented"); +} + +JNIEXPORT jboolean JNICALL +Java_java_nio_MappedByteBufferImpl_isLoadedImpl (JNIEnv * env, + jclass class + __attribute__ ((__unused__))) +{ + JCL_ThrowException (env, IO_EXCEPTION, + "java.nio.MappedByteBufferImpl.isLoadedImpl(): not implemented"); + return 0; +} + +JNIEXPORT void JNICALL +Java_java_nio_MappedByteBufferImpl_loadImpl (JNIEnv * env, + jclass clazz + __attribute__ ((__unused__))) +{ + JCL_ThrowException (env, IO_EXCEPTION, + "java.nio.MappedByteBufferImpl.loadImpl(): not implemented"); +} + +JNIEXPORT void JNICALL +Java_java_nio_MappedByteBufferImpl_forceImpl (JNIEnv * env, + jclass class + __attribute__ ((__unused__))) +{ + JCL_ThrowException (env, IO_EXCEPTION, + "java.nio.MappedByteBufferImpl.forceImpl(): not implemented"); +} diff --git a/libjava/classpath/native/jni/java-nio/java_nio_VMDirectByteBuffer.c b/libjava/classpath/native/jni/java-nio/java_nio_VMDirectByteBuffer.c new file mode 100644 index 00000000000..3eb5677e646 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/java_nio_VMDirectByteBuffer.c @@ -0,0 +1,216 @@ +/* java_nio_VMDirectByteBuffer.c - Native methods for VMDirectByteBuffer + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include <config.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <jni.h> +#include <jcl.h> + +#include "java_nio_VMDirectByteBuffer.h" + +static jclass classRawData; +static jmethodID methodRawDataInit; +static jfieldID fieldNativePointer; + +static void *NIOGetPointer (JNIEnv *, jobject); +static jobject NIOGetRawData (JNIEnv *, void *pointer); + +static void * +NIOGetPointer (JNIEnv * env, jobject rawdata) +{ +#if SIZEOF_VOID_P == 4 + return (void *) (*env)->GetIntField (env, rawdata, fieldNativePointer); +#elif SIZEOF_VOID_P == 8 + return (void *) (*env)->GetLongField (env, rawdata, fieldNativePointer); +#else +#error unsupported pointer size +#endif +} + +static jobject +NIOGetRawData (JNIEnv * env, void *pointer) +{ +#if SIZEOF_VOID_P == 4 + return (*env)->NewObject (env, classRawData, methodRawDataInit, + (jint) pointer); +#elif SIZEOF_VOID_P == 8 + return (*env)->NewObject (env, classRawData, methodRawDataInit, + (jlong) pointer); +#else +#error unsupported pointer size +#endif +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_init + (JNIEnv * env, jclass clazz __attribute__ ((__unused__))) +{ +#if SIZEOF_VOID_P == 4 + classRawData = (*env)->FindClass (env, "gnu/classpath/RawData32"); + if (classRawData == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "unable to find internal class"); + return; + } + + methodRawDataInit = (*env)->GetMethodID (env, classRawData, + "<init>", "(I)V"); + if (methodRawDataInit == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "unable to find internal constructor"); + return; + } + + fieldNativePointer = (*env)->GetFieldID (env, classRawData, "data", "I"); + if (fieldNativePointer == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "unable to find internal field"); + return; + } +#elif SIZEOF_VOID_P == 8 + classRawData = (*env)->FindClass (env, "gnu/classpath/RawData64"); + if (classRawData == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "unable to find internal class"); + return; + } + + methodRawDataInit = (*env)->GetMethodID (env, classRawData, + "<init>", "(J)V"); + if (methodRawDataInit == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "unable to find internal constructor"); + return; + } + + fieldNativePointer = (*env)->GetFieldID (env, classRawData, "data", "J"); + if (fieldNativePointer == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "unable to find internal field"); + return; + } +#else +#error unsupported pointer size +#endif + + /* We need to wrap the jclass in global reference to make it persistent */ + if ((classRawData = (*env)->NewGlobalRef (env, classRawData)) == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "failed to create global reference"); + return; + } +} + +JNIEXPORT jobject JNICALL +Java_java_nio_VMDirectByteBuffer_allocate + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), jint capacity) +{ + void *buffer; + + buffer = malloc (capacity); + + if (buffer == NULL) + { + JCL_ThrowException (env, "java/lang/OutOfMemoryError", + "unable to allocate memory for direct byte buffer"); + return 0; + } + + return NIOGetRawData (env, buffer); +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_free + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), jobject address) +{ + free (NIOGetPointer (env, address)); +} + +JNIEXPORT jbyte JNICALL +Java_java_nio_VMDirectByteBuffer_get__Lgnu_classpath_RawData_2I + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint index) +{ + return ((jbyte *) NIOGetPointer (env, address))[index]; +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_put + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint index, jbyte value) +{ + jbyte *pointer = (jbyte *) NIOGetPointer (env, address) + index; + *pointer = value; +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_get__Lgnu_classpath_RawData_2I_3BII + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint index, jbyteArray dst, jint dst_offset, jint dst_len) +{ + jbyte *src = (jbyte *) NIOGetPointer (env, address) + index; + memcpy ((*env)->GetByteArrayElements (env, dst, NULL) + dst_offset, src, + dst_len); +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_shiftDown + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint dst_offset, jint src_offset, jint count) +{ + jbyte *dst = (jbyte *) NIOGetPointer (env, address) + dst_offset; + jbyte *src = (jbyte *) NIOGetPointer (env, address) + src_offset; + memmove (dst, src, count); +} + +JNIEXPORT jobject JNICALL +Java_java_nio_VMDirectByteBuffer_adjustAddress + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint offset) +{ + return NIOGetRawData (env, (jbyte *) NIOGetPointer (env, address) + offset); +} diff --git a/libjava/classpath/native/jni/java-util/.cvsignore b/libjava/classpath/native/jni/java-util/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/java-util/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/java-util/Makefile.am b/libjava/classpath/native/jni/java-util/Makefile.am new file mode 100644 index 00000000000..da617f6a2b8 --- /dev/null +++ b/libjava/classpath/native/jni/java-util/Makefile.am @@ -0,0 +1,7 @@ +pkglib_LTLIBRARIES = libjavautil.la + +libjavautil_la_SOURCES = java_util_VMTimeZone.c + +AM_LDFLAGS = @CLASSPATH_MODULE@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@ diff --git a/libjava/classpath/native/jni/java-util/java_util_VMTimeZone.c b/libjava/classpath/native/jni/java-util/java_util_VMTimeZone.c new file mode 100644 index 00000000000..a3a986d36bc --- /dev/null +++ b/libjava/classpath/native/jni/java-util/java_util_VMTimeZone.c @@ -0,0 +1,223 @@ +/* VMTimeZone.c - Native method for java.util.VMTimeZone + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "config.h" + +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <jni.h> + +#include "java_util_VMTimeZone.h" + +static size_t jint_to_charbuf (char *bufend, jint num); + +/** + * This method returns a time zone id string which is in the form + * (standard zone name) or (standard zone name)(GMT offset) or + * (standard zone name)(GMT offset)(daylight time zone name). The + * GMT offset can be in seconds, or where it is evenly divisible by + * 3600, then it can be in hours. The offset must be the time to + * add to the local time to get GMT. If a offset is given and the + * time zone observes daylight saving then the (daylight time zone + * name) must also be given (otherwise it is assumed the time zone + * does not observe any daylight savings). + * <p> + * The result of this method is given to getDefaultTimeZone(String) + * which tries to map the time zone id to a known TimeZone. See + * that method on how the returned String is mapped to a real + * TimeZone object. + */ +JNIEXPORT jstring JNICALL +Java_java_util_VMTimeZone_getSystemTimeZoneId (JNIEnv * env, + jclass clazz + __attribute__ ((__unused__))) +{ + struct tm tim; +#ifndef HAVE_LOCALTIME_R + struct tm *lt_tim; +#endif +#ifdef HAVE_TM_ZONE + int month; +#endif + time_t current_time; + long tzoffset; + const char *tz1, *tz2; + char tzoff[11]; + size_t tz1_len, tz2_len, tzoff_len; + char *tzid; + jstring retval; + + time (¤t_time); +#ifdef HAVE_LOCALTIME_R + localtime_r (¤t_time, &tim); +#else + /* Fall back on non-thread safe localtime. */ + lt_tim = localtime (¤t_time); + memcpy (&tim, lt_tim, sizeof (struct tm)); +#endif + mktime (&tim); + +#ifdef HAVE_STRUCT_TM_TM_ZONE + /* We will cycle through the months to make sure we hit dst. */ + month = tim.tm_mon; + tz1 = tz2 = NULL; + while (tz1 == NULL || tz2 == NULL) + { + if (tim.tm_isdst > 0) + tz2 = tim.tm_zone; + else if (tz1 == NULL) + { + tz1 = tim.tm_zone; + month = tim.tm_mon; + } + + if (tz1 == NULL || tz2 == NULL) + { + tim.tm_mon++; + tim.tm_mon %= 12; + } + + if (tim.tm_mon == month && tz2 == NULL) + tz2 = ""; + else + mktime (&tim); + } + /* We want to make sure the tm struct we use later on is not dst. */ + tim.tm_mon = month; + mktime (&tim); +#elif defined (HAVE_TZNAME) + /* If dst is never used, tzname[1] is the empty string. */ + tzset (); + tz1 = tzname[0]; + tz2 = tzname[1]; +#else + /* Some targets have no concept of timezones. Assume GMT without dst. */ + tz1 = "GMT"; + tz2 = ""; +#endif + +#ifdef STRUCT_TM_HAS_GMTOFF + /* tm_gmtoff is the number of seconds that you must add to GMT to get + local time, we need the number of seconds to add to the local time + to get GMT. */ + tzoffset = -1L * tim.tm_gmtoff; +#elif HAVE_UNDERSCORE_TIMEZONE + /* On some systems _timezone is actually defined as time_t. */ + tzoffset = (long) _timezone; +#elif HAVE_TIMEZONE + /* timezone is secs WEST of UTC. */ + tzoffset = timezone; +#else + /* FIXME: there must be another global if neither tm_gmtoff nor timezone + is available, esp. if tzname is valid. + Richard Earnshaw <rearnsha@arm.com> has suggested using difftime to + calculate between gmtime and localtime (and accounting for possible + daylight savings time) as an alternative. */ + tzoffset = 0L; +#endif + + if ((tzoffset % 3600) == 0) + tzoffset = tzoffset / 3600; + + tz1_len = strlen (tz1); + tz2_len = strlen (tz2); + tzoff_len = jint_to_charbuf (tzoff + 11, tzoffset); + tzid = (char *) malloc (tz1_len + tz2_len + tzoff_len + 1); /* FIXME alloc */ + memcpy (tzid, tz1, tz1_len); + memcpy (tzid + tz1_len, tzoff + 11 - tzoff_len, tzoff_len); + memcpy (tzid + tz1_len + tzoff_len, tz2, tz2_len); + tzid[tz1_len + tzoff_len + tz2_len] = '\0'; + + retval = (*env)->NewStringUTF (env, tzid); + free (tzid); + + return retval; +} + +/* Put printed (decimal) representation of NUM in a buffer. + BUFEND marks the end of the buffer, which must be at least 11 chars long. + Returns the COUNT of chars written. The result is in + (BUFEND - COUNT) (inclusive) upto (BUFEND) (exclusive). + + Note that libgcj has a slightly different version called _Jv_FormatInt + that works on jchar buffers. +*/ + +static size_t +jint_to_charbuf (char *bufend, jint num) +{ + register char *ptr = bufend; + jboolean isNeg; + if (num < 0) + { + isNeg = JNI_TRUE; + num = -(num); + if (num < 0) + { + /* Must be MIN_VALUE, so handle this special case. + FIXME use 'unsigned jint' for num. */ + *--ptr = '8'; + num = 214748364; + } + } + else + isNeg = JNI_FALSE; + + do + { + *--ptr = (char) ((int) '0' + (num % 10)); + num /= 10; + } + while (num > 0); + + if (isNeg) + *--ptr = '-'; + return bufend - ptr; +} diff --git a/libjava/classpath/native/jni/xmlj/.cvsignore b/libjava/classpath/native/jni/xmlj/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/xmlj/BUGS b/libjava/classpath/native/jni/xmlj/BUGS new file mode 100644 index 00000000000..801700cf1b0 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/BUGS @@ -0,0 +1,35 @@ +GNU Jaxp +------------------------------------------------------------------------ + +These bugs are for the gnu.xml.libxmlj package. + +CAVEAT: LibxmlJ's current incarnation is incomplete and partly +incorrect. Highly experimental. + +- Thread-safe, but effectively runs single-threaded. + +- Native code passes incorrect URIs to URIResolver.resolve. + +- Default output properties accessible through JAXP always assume XML + output (in violation of the XSLT 1.0 specification, section 16) + Correction: LibxmlJ always assumes XML output. + +- OutputProperties are not properly implemented, compare code and API + documentation. + +- TransformerFactory.getAttribute() and + TransformerFactory.setAttribute() not implemented, i.e. low-level + libxslt settings can currently not be accessed from Java. + +- TransformerFactory.getFeature() not implemented, i.e. currently no + low-level features of libxslt are advertised. + +FIXME: + +- Make LRU caching configurable. + +- Check whether <?xml encoding="..."?> headers are honored. + +- DefaultURIResolver uses naive approach. + +- TransformerFactory.getAssociatedStyleSheet() unfinished. diff --git a/libjava/classpath/native/jni/xmlj/Makefile.am b/libjava/classpath/native/jni/xmlj/Makefile.am new file mode 100644 index 00000000000..b0f1f9104de --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/Makefile.am @@ -0,0 +1,25 @@ +pkglib_LTLIBRARIES = libxmlj.la + +libxmlj_la_SOURCES = \ +xmlj_dom.c \ +xmlj_dom.h \ +xmlj_error.c \ +xmlj_error.h \ +xmlj_io.c \ +xmlj_io.h \ +xmlj_node.c \ +xmlj_node.h \ +xmlj_sax.c \ +xmlj_sax.h \ +xmlj_transform.c \ +xmlj_util.c \ +xmlj_util.h \ +xmlj_xpath.c + +AM_LDFLAGS = @CLASSPATH_MODULE@ @XML_LIBS@ @XSLT_LIBS@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ + +# Don't enable ERROR flags. Code isn't warning free yet. +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @XML_CFLAGS@ @XSLT_CFLAGS@ + +EXTRA_DIST = BUGS diff --git a/libjava/classpath/native/jni/xmlj/xmlj_dom.c b/libjava/classpath/native/jni/xmlj/xmlj_dom.c new file mode 100644 index 00000000000..b9bd372b17b --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_dom.c @@ -0,0 +1,2617 @@ +/* xmlj_dom.c - + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "xmlj_dom.h" +#include "xmlj_error.h" +#include "xmlj_io.h" +#include "xmlj_node.h" +#include "xmlj_sax.h" +#include "xmlj_util.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +JNIEnv *dom_cb_env; +jobject dom_cb_obj; + +typedef struct +{ + int index; + int count; + xmlNodePtr node; +} +xmljHashScanData; + +/* Prototypes for local functions */ + +void +xmljAddAttribute (xmlNodePtr node, xmlAttrPtr attr); + +void +xmljHashScanner (void *payload, void *vdata, xmlChar *name); + +xmlChar * +xmljGetNodeValue (xmlNodePtr node); + +/* + * Determines whether a child node is suitable for insertion in the list of + * children for a given parent node. + * Returns 0 on success, a DOMException code otherwise. + */ +void +xmljValidateChildNode (JNIEnv *env, xmlNodePtr parent, xmlNodePtr child) +{ + xmlNodePtr cur; + + if (child == NULL || parent == NULL) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return; + } + if (child->doc != parent->doc) + { + xmljThrowDOMException (env, 4, NULL); /* WRONG_DOCUMENT_ERR */ + return; + } + /* Check that new parent is of an allowed type */ + switch (parent->type) + { + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_TEXT_NODE: + case XML_ENTITY_NODE: + case XML_ENTITY_REF_NODE: + case XML_NOTATION_NODE: + case XML_PI_NODE: + /* these can't have any children */ + /* HIERARCHY_REQUEST_ERR */ + xmljThrowDOMException (env, 3, "parent type does not allow children"); + return; + case XML_ATTRIBUTE_NODE: + if (child->type != XML_TEXT_NODE && + child->type != XML_ENTITY_REF_NODE) + { + /* HIERARCHY_REQUEST_ERR */ + xmljThrowDOMException (env, 3, "attributes may only contain text or entity reference nodes"); + return; + } + break; + case XML_DOCUMENT_FRAG_NODE: + case XML_ELEMENT_NODE: + if (child->type == XML_DTD_NODE || + child->type == XML_DOCUMENT_TYPE_NODE || + child->type == XML_ENTITY_NODE || + child->type == XML_NOTATION_NODE || + child->type == XML_PI_NODE) + { + /* HIERARCHY_REQUEST_ERR */ + xmljThrowDOMException (env, 3, "parent type does not allow child of this type"); + return; + } + /* fall through */ + default: + if (child->type == XML_ATTRIBUTE_NODE || + child->type == XML_DOCUMENT_NODE || + child->type == XML_DOCUMENT_FRAG_NODE) + { + /* HIERARCHY_REQUEST_ERR */ + xmljThrowDOMException (env, 3, "node type may not be a child"); + return; + } + /* TODO others? */ + } + /* Check that new parent is not self or an ancestor */ + for (cur = parent; cur != NULL; cur = cur->parent) + { + if (cur == child) + { + /* HIERARCHY_REQUEST_ERR */ + xmljThrowDOMException (env, 3, "child cannot be an ancestor of itself"); + return; + } + } + /* Check that new parent does not add a second doctype or root element + * to a document parent */ + if (parent->type == XML_DOCUMENT_NODE) + { + cur = parent->children; + while (cur != NULL) + { + if (cur->type == XML_DTD_NODE || + cur->type == XML_DOCUMENT_TYPE_NODE || + (cur->type == XML_ELEMENT_NODE && + parent->type == XML_DOCUMENT_NODE)) + { + if (child->type == cur->type && child != cur) + { + /* HIERARCHY_REQUEST_ERR */ + xmljThrowDOMException (env, 3, "cannot add a second doctype or root element"); + return; + } + } + cur = cur->next; + } + } +} + +/* + * Adds the specified attribute node to the list of attributes for the given + * element. + */ +void +xmljAddAttribute (xmlNodePtr node, xmlAttrPtr attr) +{ + xmlAttrPtr cur = node->properties; + + if (cur == NULL) + { + node->properties = attr; + attr->prev = NULL; + attr->next = NULL; + attr->parent = node; + attr->doc = node->doc; + } + else + { + while (cur->next != NULL) + { + cur = cur->next; + } + cur->next = attr; + attr->prev = cur; + attr->next = NULL; + attr->parent = node; + attr->doc = node->doc; + } +} + +/* -- GnomeAttr -- */ + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeAttr_getSpecified (JNIEnv * env, jobject self) +{ + xmlAttrPtr attr; + + attr = (xmlAttrPtr) xmljGetNodeID (env, self); + return (attr->atype != 0); +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeAttr_getValue (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + xmlChar *text; + jstring ret; + + node = xmljGetNodeID (env, self); + text = xmlNodeGetContent (node); + ret = xmljNewString (env, (const xmlChar *) text); + if (text != NULL) + { + xmlFree (text); + } + return ret; +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeAttr_setValue (JNIEnv * env, + jobject self, jstring value) +{ + xmlNodePtr node; + const xmlChar *s_value; + + node = xmljGetNodeID (env, self); + s_value = xmljGetStringChars (env, value); + xmlNodeSetContent (node, s_value); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeAttr_xmljIsId (JNIEnv * env, jobject self) +{ + xmlAttrPtr attr; + + attr = (xmlAttrPtr) xmljGetNodeID (env, self); + return (attr->atype == XML_ATTRIBUTE_ID); +} + +/* -- GnomeDocument -- */ + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_free (JNIEnv * env, + jobject self + __attribute__ ((__unused__)), + jobject id) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljAsPointer (env, id); + xmljFreeDoc (env, doc); + xmlFree (doc); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_getDoctype (JNIEnv * env, jobject self) +{ + xmlDocPtr doc; + xmlDtdPtr dtd; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + dtd = doc->extSubset; + if (dtd == NULL) + { + dtd = doc->intSubset; + } + return xmljGetNodeInstance (env, (xmlNodePtr) dtd); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_getDocumentElement (JNIEnv * env, + jobject self) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + return xmljGetNodeInstance (env, xmlDocGetRootElement (doc)); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_createDocumentType (JNIEnv * env, + jobject self, + jstring name, + jstring publicId, + jstring systemId) +{ + xmlDocPtr doc; + xmlDtdPtr dtd; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + dtd = xmlNewDtd (doc, + xmljGetStringChars (env, name), + xmljGetStringChars (env, publicId), + xmljGetStringChars (env, systemId)); + return xmljGetNodeInstance (env, (xmlNodePtr) dtd); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_createDocumentFragment (JNIEnv * env, + jobject self) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + return xmljGetNodeInstance (env, xmlNewDocFragment (doc)); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_createTextNode (JNIEnv * env, + jobject self, + jstring data) +{ + xmlDocPtr doc; + xmlNodePtr text; + const xmlChar *s_data; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + s_data = xmljGetStringChars (env, data); + text = xmlNewDocText (doc, s_data); + return xmljGetNodeInstance (env, text); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_createComment (JNIEnv * env, + jobject self, + jstring data) +{ + xmlDocPtr doc; + xmlNodePtr comment; + const xmlChar *s_data; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + s_data = xmljGetStringChars (env, data); + comment = xmlNewDocComment (doc, s_data); + return xmljGetNodeInstance (env, comment); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_createCDATASection (JNIEnv * env, + jobject self, + jstring data) +{ + xmlDocPtr doc; + xmlNodePtr cdata; + const xmlChar *s_data; + int len; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + s_data = xmljGetStringChars (env, data); + len = xmlStrlen (s_data); + cdata = xmlNewCDataBlock (doc, s_data, len); + return xmljGetNodeInstance (env, cdata); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_createProcessingInstruction (JNIEnv * + env, + jobject + self, + jstring + target, + jstring + data) +{ + xmlDocPtr doc; + xmlNodePtr pi; + const xmlChar *s_target; + const xmlChar *s_data; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + s_target = xmljGetStringChars (env, target); + s_data = xmljGetStringChars (env, data); + pi = xmlNewPI (s_target, s_data); + pi->doc = doc; + return xmljGetNodeInstance (env, pi); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_createEntityReference (JNIEnv * env, + jobject self, + jstring name) +{ + xmlDocPtr doc; + xmlNodePtr ref; + const xmlChar *s_name; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + s_name = xmljGetStringChars (env, name); + ref = xmlNewReference (doc, s_name); + return xmljGetNodeInstance (env, ref); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_xmljImportNode (JNIEnv * env, + jobject self, + jobject importedNode, + jboolean deep) +{ + xmlDocPtr doc; + xmlNodePtr node; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + node = xmljGetNodeID (env, importedNode); + if (node == NULL) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return NULL; + } + if (node->type == XML_DOCUMENT_NODE || + node->type == XML_DOCUMENT_TYPE_NODE) + { + xmljThrowDOMException (env, 9, NULL); /* NOT_SUPPORTED_ERR */ + return NULL; + } + node = xmlDocCopyNode (node, doc, deep); + return xmljGetNodeInstance (env, node); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_createElementNS (JNIEnv * env, + jobject self, + jstring uri, + jstring qName) +{ + xmlDocPtr doc; + xmlNodePtr element; + xmlNsPtr ns = NULL; + const xmlChar *s_uri; + const xmlChar *s_qName; + const xmlChar *s_prefix; + const xmlChar *s_localName; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + s_qName = xmljGetStringChars (env, qName); + if (xmlValidateQName (s_qName, 0)) + { + xmljThrowDOMException (env, 5, NULL); /* INVALID_CHARACTER_ERR */ + return NULL; + } + if (uri != NULL) + { + s_uri = xmljGetStringChars (env, uri); + s_prefix = xmljGetPrefix (s_qName); + s_localName = xmljGetLocalName (s_qName); + ns = xmlNewNs ((xmlNodePtr) doc, s_uri, s_prefix); + } + element = xmlNewDocNode (doc, ns, s_qName, NULL); + return xmljGetNodeInstance (env, element); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_createAttributeNS (JNIEnv * env, + jobject self, + jstring uri, + jstring qName) +{ + xmlDocPtr doc; + xmlNodePtr attr; + xmlNsPtr ns = NULL; + const xmlChar *s_uri; + const xmlChar *s_qName; + const xmlChar *s_prefix; + const xmlChar *s_localName; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + s_qName = xmljGetStringChars (env, qName); + if (xmlValidateQName (s_qName, 0)) + { + xmljThrowDOMException (env, 5, NULL); /* INVALID_CHARACTER_ERR */ + return NULL; + } + if (uri != NULL) + { + s_uri = xmljGetStringChars (env, uri); + s_prefix = xmljGetPrefix (s_qName); + s_localName = xmljGetLocalName (s_qName); + ns = xmlNewNs ((xmlNodePtr) doc, s_uri, s_prefix); + } + attr = (xmlNodePtr) xmlNewNsProp ((xmlNodePtr) doc, ns, s_qName, NULL); + attr->parent = NULL; + return xmljGetNodeInstance (env, attr); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_xmljGetElementById (JNIEnv * env, + jobject self, + jstring elementId) +{ + xmlDocPtr doc; + xmlNodePtr ctx, tmp; + xmlAttrPtr attr; + const xmlChar *id; + const xmlChar *val; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + id = xmljGetStringChars (env, elementId); + + ctx = xmlDocGetRootElement (doc); + while (ctx && ctx != (xmlNodePtr) doc) + { + if (ctx->type == XML_ELEMENT_NODE) + { + for (attr = ctx->properties; attr; + attr = (xmlAttrPtr) attr->next) + { + if (xmlIsID (doc, ctx, attr)) + { + val = xmlGetProp (ctx, attr->name); + if (val && xmlStrEqual (id, val)) + { + return xmljGetNodeInstance (env, ctx); + } + } + } + } + if (ctx->children) + { + ctx = ctx->children; + } + else + { + tmp = ctx->next; + if (tmp) + { + ctx = tmp; + } + else + { + do + { + tmp = ctx->parent; + if (!tmp) + { + return NULL; + } + ctx = tmp; + tmp = ctx->next; + } + while (!tmp); + ctx = tmp; + } + } + } + return NULL; +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_getInputEncoding (JNIEnv * env, + jobject self) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + if (doc->encoding) + { + return xmljNewString (env, doc->encoding); + } + switch (doc->charset) + { + case XML_CHAR_ENCODING_ASCII: + return xmljNewString (env, BAD_CAST "US-ASCII"); + case XML_CHAR_ENCODING_UTF16LE: + return xmljNewString (env, BAD_CAST "UTF-16LE"); + case XML_CHAR_ENCODING_UTF16BE: + return xmljNewString (env, BAD_CAST "UTF-16BE"); + case XML_CHAR_ENCODING_8859_1: + return xmljNewString (env, BAD_CAST "ISO-8859-1"); + /* TODO others */ + default: + return xmljNewString (env, BAD_CAST "UTF-8"); + } +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_getXmlEncoding (JNIEnv * env, + jobject self) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + return (doc->encoding == NULL) ? + xmljNewString (env, BAD_CAST "UTF-8") : + xmljNewString (env, doc->encoding); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_getXmlStandalone (JNIEnv * env, + jobject self) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + return doc->standalone; +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_setXmlStandalone (JNIEnv * env, + jobject self, + jboolean xmlStandalone) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + doc->standalone = xmlStandalone; +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_getXmlVersion (JNIEnv * env, + jobject self) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + return (doc->version == NULL) ? + xmljNewString (env, BAD_CAST "1.0") : + xmljNewString (env, doc->version); +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_setXmlVersion (JNIEnv * env, + jobject self, + jstring xmlVersion) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + if (xmlVersion == NULL) + { + doc->version = NULL; + } + else + { + const xmlChar *version = xmljGetStringChars (env, xmlVersion); + if (!xmlStrEqual (version, BAD_CAST "1.0") && + !xmlStrEqual (version, BAD_CAST "1.1")) + { + xmljThrowDOMException (env, 9, NULL); /* NOT_SUPPORTED_ERR */ + return; + } + doc->version = version; + } +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_getDocumentURI (JNIEnv * env, + jobject self) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + return (doc->name == NULL) ? NULL : + xmljNewString (env, (const xmlChar *) doc->URL); +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_setDocumentURI (JNIEnv * env, + jobject self, + jstring documentURI) +{ + xmlDocPtr doc; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + if (documentURI == NULL) + { + doc->URL = NULL; + } + else + { + doc->URL = xmljGetStringChars (env, documentURI); + } +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_xmljAdoptNode (JNIEnv *env, + jobject self, + jobject jnode) +{ + xmlDocPtr doc; + xmlNodePtr node; + + doc = (xmlDocPtr) xmljGetNodeID (env, self); + node = xmljGetNodeID (env, jnode); + + if (node == NULL) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return NULL; + } + if (node->type == XML_DOCUMENT_NODE || + node->type == XML_DOCUMENT_TYPE_NODE || + node->type == XML_ENTITY_NODE || + node->type == XML_NOTATION_NODE) + { + xmljThrowDOMException (env, 9, NULL); /* NOT_SUPPORTED_ERR */ + return NULL; + } + xmlUnlinkNode (node); + node = xmlDocCopyNode (node, doc, 1); + return xmljGetNodeInstance (env, node); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_renameNode (JNIEnv * env, + jobject self + __attribute__ ((__unused__)), + jobject n + __attribute__ ((__unused__)), + jstring namespaceURI + __attribute__ ((__unused__)), + jstring qName + __attribute__ ((__unused__))) +{ + xmlNodePtr node; + xmlNsPtr ns; + const xmlChar *s_qName; + const xmlChar *href; + const xmlChar *prefix; + int *len; + + node = xmljGetNodeID (env, n); + if (node == NULL) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return NULL; + } + s_qName = xmljGetStringChars (env, qName); + if (xmlValidateQName (s_qName, 0)) + { + xmljThrowDOMException (env, 5, NULL); /* INVALID_CHARACTER_ERR */ + return NULL; + } + xmlNodeSetName (node, s_qName); + + href = xmljGetStringChars (env, namespaceURI); + len = (int *) malloc (sizeof (int)); + prefix = xmlSplitQName3 (s_qName, len); + ns = node->ns; + if (ns == NULL) + { + if (href != NULL) + { + ns = xmlNewNs (node, href, prefix); + xmlSetNs (node, ns); + } + } + else + { + node->ns = NULL; + /*xmlFreeNs (ns); FIXME this can segfault (?) */ + if (href != NULL) + { + ns = xmlNewNs (node, href, prefix); + xmlSetNs (node, ns); + } + } + free (len); + return n; +} + +/* -- GnomeDocumentBuilder -- */ + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocumentBuilder_parseStream (JNIEnv * env, + jobject self, + jobject in, + jbyteArray + detectBuffer, + jstring publicId, + jstring systemId, + jstring base, + jboolean validate, + jboolean coalesce, + jboolean + expandEntities, + jboolean + entityResolver, + jboolean + errorHandler) +{ + xmlDocPtr doc; + + doc = xmljParseDocument(env, + self, + in, + detectBuffer, + publicId, + systemId, + base, + validate, + coalesce, + expandEntities, + 0, + 0, + entityResolver, + errorHandler, + 0, + 0, + 1); + return xmljCreateDocument (env, self, doc); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocumentBuilder_createDocument +(JNIEnv * env, + jobject self, + jstring namespaceURI, + jstring qualifiedName, + jobject doctype) +{ + xmlDocPtr doc; + xmlNodePtr root; + xmlNsPtr ns; + const xmlChar *href; + const xmlChar *prefix; + const xmlChar *qName; + + qName = xmljGetStringChars (env, qualifiedName); + href = xmljGetStringChars (env, namespaceURI); + if (qName == NULL) + { + prefix = NULL; + } + else + { + int *len; + + len = (int *) malloc (sizeof (int)); + prefix = xmlSplitQName3 (qName, len); + free (len); + } + + /* Create the document node */ + doc = xmlNewDoc (BAD_CAST "1.0"); + + /* doctype */ + if (doctype != NULL) + { + jclass cls; + jmethodID method; + jstring ret; + const xmlChar *name; + const xmlChar *publicId; + const xmlChar *systemId; + const xmlChar *internalSubset; + xmlDtdPtr dtd; + + cls = (*env)->FindClass (env, "org/w3c/dom/DocumentType"); + if (cls == NULL) + { + return NULL; + } + /* name */ + method = (*env)->GetMethodID (env, cls, "getName", + "()Ljava/lang/String;"); + if (method == NULL) + { + return NULL; + } + ret = (jstring) (*env)->CallObjectMethod (env, doctype, method); + name = xmljGetStringChars (env, ret); + + /* publicId */ + method = (*env)->GetMethodID (env, cls, "getPublicId", + "()Ljava/lang/String;"); + if (method == NULL) + { + return NULL; + } + ret = (jstring) (*env)->CallObjectMethod (env, doctype, method); + publicId = xmljGetStringChars (env, ret); + + /* systemId */ + method = (*env)->GetMethodID (env, cls, "getSystemId", + "()Ljava/lang/String;"); + if (method == NULL) + { + return NULL; + } + ret = (jstring) (*env)->CallObjectMethod (env, doctype, method); + systemId = xmljGetStringChars (env, ret); + + /* internalSubset */ + method = (*env)->GetMethodID (env, cls, "getInternalSubset", + "()Ljava/lang/String;"); + if (method == NULL) + { + return NULL; + } + ret = (jstring) (*env)->CallObjectMethod (env, doctype, method); + internalSubset = xmljGetStringChars (env, ret); + + /* TODO notations */ + /* TODO entities */ + if (internalSubset == NULL) + { + dtd = xmlNewDtd (doc, name, publicId, systemId); + } + else + { + dtd = xmlCreateIntSubset (doc, name, publicId, systemId); + /* TODO parse internal subset? */ + xmljThrowDOMException (env, 9, NULL); /* NOT_SUPPORTED_ERR */ + return NULL; + } + } + + /* Create the root element */ + root = xmlNewNode (NULL, qName); + xmlDocSetRootElement (doc, root); + ns = xmlNewNs (root, href, prefix); + xmlSetNs (root, ns); + + return xmljCreateDocument (env, self, doc); +} + +/* -- GnomeDocumentType -- */ + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocumentType_getPublicId (JNIEnv * env, + jobject self) +{ + xmlDtdPtr dtd; + + dtd = (xmlDtdPtr) xmljGetNodeID (env, self); + return xmljNewString (env, dtd->ExternalID); +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocumentType_getSystemId (JNIEnv * env, + jobject self) +{ + xmlDtdPtr dtd; + + dtd = (xmlDtdPtr) xmljGetNodeID (env, self); + return xmljNewString (env, dtd->SystemID); +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocumentType_getInternalSubset (JNIEnv * env, + jobject self + __attribute__ ((__unused__))) +{ + /* TODO */ + xmljThrowDOMException (env, 9, NULL); /* NOT_SUPPORTED_ERR */ + return NULL; +} + +/* -- GnomeElement -- */ + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_getAttribute (JNIEnv * env, + jobject self, + jstring name) +{ + xmlNodePtr node; + const xmlChar *s_name; + const xmlChar *s_value; + + node = xmljGetNodeID (env, self); + s_name = xmljGetStringChars (env, name); + s_value = xmlGetProp (node, s_name); + xmlFree ((xmlChar *) s_name); + return (s_value == NULL) ? + xmljNewString (env, BAD_CAST "") : + xmljNewString (env, s_value); +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_setAttribute (JNIEnv * env, + jobject self, + jstring name, + jstring value) +{ + xmlNodePtr node; + const xmlChar *s_name; + const xmlChar *s_value; + + node = xmljGetNodeID (env, self); + s_name = xmljGetStringChars (env, name); + if (xmlValidateName (s_name, 0)) + { + xmljThrowDOMException (env, 5, NULL); /* INVALID_CHARACTER_ERR */ + return; + } + s_value = xmljGetStringChars (env, value); + xmlSetProp (node, s_name, s_value); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_getAttributeNode (JNIEnv * env, + jobject self, + jstring name) +{ + xmlNodePtr node; + const xmlChar *s_name; + xmlAttrPtr attr; + + node = xmljGetNodeID (env, self); + s_name = xmljGetStringChars (env, name); + attr = xmlHasProp (node, s_name); + if (attr == NULL) + { + return NULL; + } + xmlFree ((xmlChar *) s_name); + return xmljGetNodeInstance (env, (xmlNodePtr) attr); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_setAttributeNode (JNIEnv * env, + jobject self, + jobject newAttr) +{ + xmlNodePtr node; + xmlAttrPtr new_attr; + xmlAttrPtr old_attr; + + node = xmljGetNodeID (env, self); + new_attr = (xmlAttrPtr) xmljGetNodeID (env, newAttr); + if (new_attr->parent != NULL) + { + xmljThrowDOMException (env, 10, NULL); /* INUSE_ATTRIBUTE_ERR */ + return NULL; + } + if (new_attr->doc != node->doc) + { + xmljThrowDOMException (env, 4, NULL); /* WRONG_DOCUMENT_ERR */ + return NULL; + } + old_attr = xmlHasProp (node, new_attr->name); + if (old_attr) + { + xmlUnlinkNode ((xmlNodePtr) old_attr); + } + xmljAddAttribute (node, new_attr); + return xmljGetNodeInstance (env, (xmlNodePtr) old_attr); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_removeAttributeNode (JNIEnv * env, + jobject self + __attribute__ ((__unused__)), + jobject oldAttr) +{ + xmlNodePtr attr; + + attr = xmljGetNodeID (env, oldAttr); + xmlUnlinkNode (attr); + return oldAttr; +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_getAttributeNS (JNIEnv * env, + jobject self, + jstring uri, + jstring localName) +{ + xmlNodePtr node; + const xmlChar *s_uri; + const xmlChar *s_localName; + const xmlChar *s_value; + + node = xmljGetNodeID (env, self); + s_localName = xmljGetStringChars (env, localName); + if (uri == NULL) + { + s_value = xmlGetNoNsProp (node, s_localName); + } + else + { + s_uri = xmljGetStringChars (env, uri); + s_value = xmlGetNsProp (node, s_localName, s_uri); + xmlFree ((xmlChar *) s_uri); + } + xmlFree ((xmlChar *) s_localName); + return (s_value == NULL) ? + xmljNewString (env, BAD_CAST "") : + xmljNewString (env, s_value); +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_setAttributeNS (JNIEnv * env, + jobject self, + jstring uri, + jstring qName, + jstring value) +{ + xmlNodePtr node; + xmlNsPtr ns; + const xmlChar *s_uri; + const xmlChar *s_qName; + const xmlChar *s_prefix; + const xmlChar *s_localName; + const xmlChar *s_value; + + node = xmljGetNodeID (env, self); + s_qName = xmljGetStringChars (env, qName); + if (xmlValidateQName (s_qName, 0)) + { + xmljThrowDOMException (env, 5, NULL); /* INVALID_CHARACTER_ERR */ + return; + } + s_value = xmljGetStringChars (env, value); + if (uri == NULL) + { + xmlSetProp (node, s_qName, s_value); + } + else + { + s_prefix = xmljGetPrefix (s_qName); + s_localName = xmljGetLocalName (s_qName); + s_uri = xmljGetStringChars (env, uri); + ns = xmlNewNs (node, s_uri, s_prefix); + xmlSetNsProp (node, ns, s_localName, s_value); + } +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_getAttributeNodeNS (JNIEnv * env, + jobject self, + jstring uri, + jstring localName) +{ + xmlNodePtr node; + xmlAttrPtr attr; + const xmlChar *s_uri; + const xmlChar *s_localName; + + node = xmljGetNodeID (env, self); + attr = node->properties; + s_uri = xmljGetStringChars (env, uri); + s_localName = xmljGetStringChars (env, localName); + while (attr != NULL) + { + if (uri == NULL) + { + if (xmljMatch (s_localName, (xmlNodePtr) attr)) + break; + } + else + { + if (xmljMatchNS (s_uri, s_localName, (xmlNodePtr) attr)) + break; + } + attr = attr->next; + } + xmlFree ((xmlChar *) s_uri); + xmlFree ((xmlChar *) s_localName); + return xmljGetNodeInstance (env, (xmlNodePtr) attr); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_setAttributeNodeNS (JNIEnv * env, + jobject self, + jobject newAttr) +{ + xmlNodePtr node; + xmlAttrPtr new_attr; + xmlAttrPtr old_attr; + const xmlChar *uri; + + node = xmljGetNodeID (env, self); + new_attr = (xmlAttrPtr) xmljGetNodeID (env, newAttr); + if (new_attr->parent != NULL) + { + xmljThrowDOMException (env, 10, NULL); /* INUSE_ATTRIBUTE_ERR */ + return NULL; + } + if (new_attr->doc != node->doc) + { + xmljThrowDOMException (env, 4, NULL); /* WRONG_DOCUMENT_ERR */ + return NULL; + } + uri = (new_attr->ns != NULL) ? new_attr->ns->href : NULL; + old_attr = xmlHasNsProp (node, new_attr->name, uri); + if (old_attr) + { + xmlUnlinkNode ((xmlNodePtr) old_attr); + } + xmljAddAttribute (node, new_attr); + return xmljGetNodeInstance (env, (xmlNodePtr) old_attr); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_hasAttribute (JNIEnv * env, + jobject self, + jstring name) +{ + xmlNodePtr node; + const xmlChar *s_name; + const xmlChar *s_value; + + node = xmljGetNodeID (env, self); + s_name = xmljGetStringChars (env, name); + s_value = xmlGetProp (node, s_name); + xmlFree ((xmlChar *) s_name); + return (s_value != NULL); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_hasAttributeNS (JNIEnv * env, + jobject self, + jstring uri, + jstring localName) +{ + xmlNodePtr node; + const xmlChar *s_uri; + const xmlChar *s_localName; + const xmlChar *s_value; + + node = xmljGetNodeID (env, self); + s_localName = xmljGetStringChars (env, localName); + if (uri == NULL) + { + s_value = xmlGetNoNsProp (node, s_localName); + } + else + { + s_uri = xmljGetStringChars (env, uri); + s_value = xmlGetNsProp (node, s_localName, s_uri); + xmlFree ((xmlChar *) s_uri); + } + xmlFree ((xmlChar *) s_localName); + return (s_value != NULL); +} + +/* -- GnomeEntity -- */ + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeEntity_getPublicId (JNIEnv * env, jobject self) +{ + xmlEntityPtr entity; + + entity = (xmlEntityPtr) xmljGetNodeID (env, self); + return xmljNewString (env, entity->ExternalID); +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeEntity_getSystemId (JNIEnv * env, jobject self) +{ + xmlEntityPtr entity; + + entity = (xmlEntityPtr) xmljGetNodeID (env, self); + return xmljNewString (env, entity->SystemID); +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeEntity_getNotationName (JNIEnv * env, + jobject self + __attribute__ ((__unused__))) +{ + /* TODO */ + xmljThrowDOMException (env, 9, NULL); /* NOT_SUPPORTED_ERR */ + return NULL; +} + +/* -- GnomeNamedNodeMap -- */ + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNamedNodeMap_getNamedItem (JNIEnv * env, + jobject self, + jstring name) +{ + jclass cls; + jfieldID field; + jint type; + + cls = (*env)->GetObjectClass (env, self); + field = (*env)->GetFieldID (env, cls, "type", "I"); + type = (*env)->GetIntField (env, self, field); + + if (type == 0) + { + xmlAttrPtr attr; + + attr = xmljGetNamedItem (env, self, name); + return xmljGetNodeInstance (env, (xmlNodePtr) attr); + } + else + { + xmlDtdPtr dtd; + xmlHashTablePtr hash; + const xmlChar *s_name; + xmlNodePtr ret; + + dtd = (xmlDtdPtr) xmljGetNodeID (env, self); + hash = (xmlHashTablePtr) ((type == 1) ? dtd->entities : dtd->notations); + if (hash == NULL) + { + return NULL; + } + s_name = xmljGetStringChars (env, name); + ret = (xmlNodePtr) xmlHashLookup (hash, s_name); + xmlFree ((xmlChar *) s_name); + return xmljGetNodeInstance (env, ret); + } +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNamedNodeMap_setNamedItem (JNIEnv * env, + jobject self, + jobject arg) +{ + jclass cls; + jfieldID field; + jint type; + xmlNodePtr node; + xmlNodePtr argNode; + + cls = (*env)->GetObjectClass (env, self); + field = (*env)->GetFieldID (env, cls, "type", "I"); + type = (*env)->GetIntField (env, self, field); + + node = xmljGetNodeID (env, self); + argNode = xmljGetNodeID (env, arg); + + if (argNode->doc != node->doc) + { + xmljThrowDOMException (env, 4, NULL); /* WRONG_DOCUMENT_ERR */ + } + xmljValidateChildNode (env, node, argNode); + if ((*env)->ExceptionOccurred (env)) + { + return NULL; + } + if (type == 0) + { + if (argNode->parent != NULL) + { + xmljThrowDOMException (env, 10, NULL); /* INUSE_ATTRIBUTE_ERR */ + return NULL; + } + xmlAddChild (node, argNode); + } + else + { + xmlDtdPtr dtd; + xmlHashTablePtr hash; + + dtd = (xmlDtdPtr) xmljGetNodeID (env, self); + hash = (xmlHashTablePtr) ((type == 1) ? dtd->entities : dtd->notations); + if (hash == NULL) + { + hash = xmlHashCreate (10); + if (type == 1) + { + dtd->entities = hash; + } + else + { + dtd->notations = hash; + } + } + xmlHashAddEntry (hash, argNode->name, argNode); + } + return arg; +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNamedNodeMap_removeNamedItem (JNIEnv * env, + jobject self, + jstring name) +{ + jclass cls; + jfieldID field; + jint type; + + cls = (*env)->GetObjectClass (env, self); + field = (*env)->GetFieldID (env, cls, "type", "I"); + type = (*env)->GetIntField (env, self, field); + + if (type == 0) + { + xmlAttrPtr attr; + + attr = xmljGetNamedItem (env, self, name); + if (attr == NULL) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return NULL; + } + xmlUnlinkNode ((xmlNodePtr) attr); + return xmljGetNodeInstance (env, (xmlNodePtr) attr); + } + else + { + xmlDtdPtr dtd; + xmlHashTablePtr hash; + const xmlChar *s_name; + xmlNodePtr ret; + + dtd = (xmlDtdPtr) xmljGetNodeID (env, self); + hash = (xmlHashTablePtr) ((type == 1) ? dtd->entities : dtd->notations); + if (hash == NULL) + { + return NULL; + } + s_name = xmljGetStringChars (env, name); + ret = (xmlNodePtr) xmlHashLookup (hash, s_name); + if (ret != NULL) + { + xmlHashRemoveEntry (hash, s_name, NULL); + } + xmlFree ((xmlChar *) s_name); + return xmljGetNodeInstance (env, ret); + } +} + +void +xmljHashScanner (void *payload, void *vdata, xmlChar *name) +{ + xmljHashScanData *data; + + data = (xmljHashScanData *) vdata; + if (data->count <= data->index) + { + data->node = (xmlNodePtr) payload; + } + data->count++; +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNamedNodeMap_item (JNIEnv * env, + jobject self, jint index) +{ + jclass cls; + jfieldID field; + jint type; + + cls = (*env)->GetObjectClass (env, self); + field = (*env)->GetFieldID (env, cls, "type", "I"); + type = (*env)->GetIntField (env, self, field); + + if (type == 0) + { + xmlNodePtr node; + xmlAttrPtr attr; + jint count; + + node = xmljGetNodeID (env, self); + switch (node->type) + { + case XML_ELEMENT_NODE: + attr = node->properties; + for (count = 0; attr != NULL && count < index; count++) + { + attr = attr->next; + } + if (attr == NULL) + { + char msg[1024]; + sprintf (msg, "No attribute at index %d\n", (int) index); + xmljThrowException (env, "java/lang/NullPointerException", msg); + return NULL; + } + return xmljGetNodeInstance (env, (xmlNodePtr) attr); + default: + return NULL; + } + } + else + { + xmlDtdPtr dtd; + xmlHashTablePtr hash; + xmljHashScanData *data; + xmlNodePtr ret; + + dtd = (xmlDtdPtr) xmljGetNodeID (env, self); + hash = (xmlHashTablePtr) ((type == 1) ? dtd->entities : dtd->notations); + if (hash == NULL) + { + return NULL; + } + data = (xmljHashScanData *) malloc (sizeof (xmljHashScanData)); + if (data == NULL) + { + return NULL; + } + data->index = index; + data->count = 0; + data->node = NULL; + xmlHashScan (hash, xmljHashScanner, data); + ret = data->node; + free (data); + return xmljGetNodeInstance (env, ret); + } +} + +JNIEXPORT jint JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNamedNodeMap_getLength (JNIEnv * env, + jobject self) +{ + jclass cls; + jfieldID field; + jint type; + + cls = (*env)->GetObjectClass (env, self); + field = (*env)->GetFieldID (env, cls, "type", "I"); + type = (*env)->GetIntField (env, self, field); + + if (type == 0) + { + xmlNodePtr node; + xmlAttrPtr attr; + jint count; + + node = xmljGetNodeID (env, self); + switch (node->type) + { + case XML_ELEMENT_NODE: + count = 0; + attr = node->properties; + while (attr != NULL) + { + count++; + attr = attr->next; + } + return count; + default: + return -1; + } + } + else + { + xmlDtdPtr dtd; + xmlHashTablePtr hash; + xmljHashScanData *data; + jint ret; + + dtd = (xmlDtdPtr) xmljGetNodeID (env, self); + hash = (xmlHashTablePtr) ((type == 1) ? dtd->entities : dtd->notations); + if (hash == NULL) + { + return 0; + } + data = (xmljHashScanData *) malloc (sizeof (xmljHashScanData)); + if (data == NULL) + { + return 0; + } + data->index = -1; + data->count = 0; + data->node = NULL; + xmlHashScan (hash, xmljHashScanner, data); + ret = data->count; + free (data); + return ret; + } +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNamedNodeMap_getNamedItemNS (JNIEnv * env, + jobject self, + jstring uri, + jstring localName) +{ + jclass cls; + jfieldID field; + jint type; + + cls = (*env)->GetObjectClass (env, self); + field = (*env)->GetFieldID (env, cls, "type", "I"); + type = (*env)->GetIntField (env, self, field); + + if (type == 0) + { + xmlAttrPtr attr; + + attr = xmljGetNamedItemNS (env, self, uri, localName); + return xmljGetNodeInstance (env, (xmlNodePtr) attr); + } + else + { + return NULL; + } +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNamedNodeMap_setNamedItemNS (JNIEnv * env, + jobject self, + jobject arg) +{ + return Java_gnu_xml_libxmlj_dom_GnomeNamedNodeMap_setNamedItem (env, self, + arg); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNamedNodeMap_removeNamedItemNS (JNIEnv * env, + jobject self, + jstring uri, + jstring + localName) +{ + jclass cls; + jfieldID field; + jint type; + + cls = (*env)->GetObjectClass (env, self); + field = (*env)->GetFieldID (env, cls, "type", "I"); + type = (*env)->GetIntField (env, self, field); + + if (type == 0) + { + xmlAttrPtr attr; + + attr = xmljGetNamedItemNS (env, self, uri, localName); + if (attr == NULL) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return NULL; + } + else + { + xmlUnlinkNode ((xmlNodePtr) attr); + return xmljGetNodeInstance (env, (xmlNodePtr) attr); + } + } + else + { + return NULL; + } +} + +/* -- GnomeNode -- */ + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getNodeName (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + if (node == NULL) + { + return NULL; + } + return xmljNewString (env, node->name); +} + +xmlChar * +xmljGetNodeValue (xmlNodePtr node) +{ + /* If not character data, return null */ + switch (node->type) + { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_ATTRIBUTE_NODE: + return xmlNodeGetContent (node); + default: + return NULL; + } +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getNodeValue (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + xmlChar *text; + jstring ret; + + node = xmljGetNodeID (env, self); + text = xmljGetNodeValue (node); + ret = xmljNewString (env, (const xmlChar *) text); + if (text != NULL) + { + xmlFree (text); + } + return ret; +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_setNodeValue (JNIEnv * env, + jobject self, + jstring nodeValue) +{ + xmlNodePtr node; + const xmlChar *s_nodeValue; + + node = xmljGetNodeID (env, self); + + /* If not character data, return */ + if (node->type != XML_TEXT_NODE && + node->type != XML_CDATA_SECTION_NODE && node->type != XML_COMMENT_NODE) + return; + + s_nodeValue = xmljGetStringChars (env, nodeValue); + xmlNodeSetContent (node, s_nodeValue); +} + +JNIEXPORT jshort JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getNodeType (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + switch (node->type) + { + case XML_DTD_NODE: + return XML_DOCUMENT_TYPE_NODE; + case XML_ATTRIBUTE_DECL: + return XML_ATTRIBUTE_NODE; + case XML_ENTITY_DECL: + return XML_ENTITY_NODE; + default: + return node->type; + } +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getParentNode (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + return xmljGetNodeInstance (env, node->parent); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getFirstChild (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + return xmljGetNodeInstance (env, node->children); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getLastChild (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + return xmljGetNodeInstance (env, node->last); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getPreviousSibling (JNIEnv * env, + jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + return xmljGetNodeInstance (env, node->prev); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getNextSibling (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + return xmljGetNodeInstance (env, node->next); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getOwnerDocument (JNIEnv * env, + jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + return xmljGetNodeInstance (env, (xmlNodePtr) node->doc); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_xmljInsertBefore (JNIEnv * env, + jobject self, + jobject newChild, + jobject refChild) +{ + xmlNodePtr node; + xmlNodePtr newChildNode; + xmlNodePtr refChildNode; + + node = xmljGetNodeID (env, self); + newChildNode = xmljGetNodeID (env, newChild); + refChildNode = xmljGetNodeID (env, refChild); + + /* Is refChildNode a child of this node? */ + if (refChildNode == NULL || + refChildNode->parent == NULL || + refChildNode->parent != node) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return NULL; + } + /* Check new child */ + xmljValidateChildNode (env, node, newChildNode); + if ((*env)->ExceptionOccurred (env)) + { + return NULL; + } + + newChildNode = xmlAddPrevSibling (refChildNode, newChildNode); + return xmljGetNodeInstance (env, newChildNode); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_xmljReplaceChild (JNIEnv * env, + jobject self, + jobject newChild, + jobject oldChild) +{ + xmlNodePtr node; + xmlNodePtr newChildNode; + xmlNodePtr oldChildNode; + + node = xmljGetNodeID (env, self); + newChildNode = xmljGetNodeID (env, newChild); + oldChildNode = xmljGetNodeID (env, oldChild); + + /* Is oldChildNode a child of this node? */ + if (oldChildNode == NULL || + oldChildNode->parent == NULL || + oldChildNode->parent != node) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return NULL; + } + /* Check new child */ + xmljValidateChildNode (env, node, newChildNode); + if ((*env)->ExceptionOccurred (env)) + { + return NULL; + } + + newChildNode = xmlReplaceNode (oldChildNode, newChildNode); + return xmljGetNodeInstance (env, newChildNode); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_xmljRemoveChild (JNIEnv * env, + jobject self, + jobject oldChild) +{ + xmlNodePtr node; + xmlNodePtr oldChildNode; + + node = xmljGetNodeID (env, self); + oldChildNode = xmljGetNodeID (env, oldChild); + + if (oldChildNode == NULL || + oldChildNode->parent == NULL || + oldChildNode->parent != node) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return NULL; + } + xmlUnlinkNode (oldChildNode); + return oldChild; +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_xmljAppendChild (JNIEnv * env, + jobject self, + jobject newChild) +{ + xmlNodePtr node; + xmlNodePtr newChildNode; + + node = xmljGetNodeID (env, self); + newChildNode = xmljGetNodeID (env, newChild); + + /* Check new child */ + xmljValidateChildNode (env, node, newChildNode); + if ((*env)->ExceptionOccurred (env)) + { + return NULL; + } + + newChildNode = xmlAddChild (node, newChildNode); + return xmljGetNodeInstance (env, newChildNode); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_hasChildNodes (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + return (node->children != NULL); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_xmljCloneNode (JNIEnv * env, + jobject self, jboolean deep) +{ + xmlNodePtr node; + xmlNodePtr clone; + + node = xmljGetNodeID (env, self); + clone = xmlCopyNode (node, deep); + clone->parent = NULL; + clone->doc = node->doc; + return xmljGetNodeInstance (env, clone); +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_normalize (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + xmljNormalizeNode (node); +} + +void +xmljNormalizeNode (xmlNodePtr node) +{ + xmlNodePtr cur; + xmlNodePtr last = NULL; + + cur = node->children; + while (cur != NULL) + { + switch (cur->type) + { + case XML_CDATA_SECTION_NODE: + case XML_TEXT_NODE: + if (xmlIsBlankNode (cur)) + { + xmlNodePtr next = cur->next; + xmlUnlinkNode (cur); + xmlFreeNode (cur); + cur = next; + continue; + } + if (last != NULL) + { + last = xmlTextMerge (last, cur); + xmlUnlinkNode (cur); + xmlFreeNode (cur); + cur = last; + } + else + { + last = cur; + } + break; + default: + last = NULL; + xmljNormalizeNode (cur); + } + cur = cur->next; + } +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getNamespaceURI (JNIEnv * env, + jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + if (node->type != XML_ELEMENT_NODE && + node->type != XML_ATTRIBUTE_NODE) + { + return NULL; + } + if (node->ns == NULL) + { + return NULL; + } + return xmljNewString (env, node->ns->href); +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getPrefix (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + if (node->type != XML_ELEMENT_NODE && + node->type != XML_ATTRIBUTE_NODE) + { + return NULL; + } + if (node->ns == NULL) + { + return NULL; + } + return xmljNewString (env, node->ns->prefix); +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_setPrefix (JNIEnv * env, + jobject self, jstring prefix) +{ + xmlNodePtr node; + const xmlChar *s_prefix; + + s_prefix = xmljGetStringChars (env, prefix); + if (xmlValidateName (s_prefix, 0)) + { + xmljThrowDOMException (env, 5, NULL); /* INVALID_CHARACTER_ERR */ + } + node = xmljGetNodeID (env, self); + if (node->type != XML_ELEMENT_NODE && + node->type != XML_ATTRIBUTE_NODE) + { + xmljThrowDOMException (env, 3, NULL); /* HIERARCHY_REQUEST_ERR */ + return; + } + if (node->ns == NULL) + { + xmljThrowDOMException (env, 14, NULL); /* NAMESPACE_ERR */ + return; + } + node->ns->prefix = s_prefix; +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getLocalName (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + int *len; + jstring ret; + + node = xmljGetNodeID (env, self); + if (node->name == NULL) + { + return NULL; + } + len = (int *) malloc (sizeof (int)); + if (xmlSplitQName3 (node->name, len) != NULL) + { + ret = xmljNewString (env, node->name + (*len)); + } + else + { + ret = xmljNewString (env, node->name); + } + free (len); + return ret; +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_hasAttributes (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + + node = xmljGetNodeID (env, self); + return (node->properties != NULL); +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_getBaseURI (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + xmlChar *baseURI; + jstring ret; + + node = xmljGetNodeID (env, self); + baseURI = xmlNodeGetBase (node->doc, node); + ret = xmljNewString (env, (const xmlChar *) baseURI); + if (baseURI != NULL) + { + xmlFree (baseURI); + } + return ret; +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_lookupPrefix (JNIEnv * env, jobject self, + jstring namespaceURI) +{ + xmlNodePtr node; + xmlNsPtr ns; + xmlDocPtr doc; + const xmlChar *s_uri; + + node = xmljGetNodeID (env, self); + doc = node->doc; + /* If this is a document node, search from the root element */ + if (node->type == XML_DOCUMENT_NODE) + { + doc = (xmlDocPtr) node; + node = xmlDocGetRootElement (doc); + } + s_uri = xmljGetStringChars (env, namespaceURI); + ns = xmlSearchNsByHref (doc, node, s_uri); + xmlFree ((xmlChar *) s_uri); + if (ns == NULL) + { + return NULL; + } + return xmljNewString (env, ns->prefix); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_isDefaultNamespace (JNIEnv * env, + jobject self, + jstring namespaceURI) +{ + xmlNodePtr node; + xmlNsPtr ns; + const xmlChar *s_uri; + + node = xmljGetNodeID (env, self); + s_uri = xmljGetStringChars (env, namespaceURI); + ns = xmlSearchNsByHref (node->doc, node, s_uri); + xmlFree ((xmlChar *) s_uri); + if (ns == NULL) + { + return 0; + } + return (ns->prefix == NULL || xmlStrlen (ns->prefix) == 0); +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_lookupNamespaceURI (JNIEnv * env, + jobject self, + jstring prefix) +{ + xmlNodePtr node; + xmlDocPtr doc; + xmlNsPtr ns; + const xmlChar *s_prefix; + + node = xmljGetNodeID (env, self); + doc = node->doc; + /* If this is a document node, search from the root element */ + if (node->type == XML_DOCUMENT_NODE) + { + doc = (xmlDocPtr) node; + node = xmlDocGetRootElement (doc); + } + s_prefix = xmljGetStringChars (env, prefix); + ns = xmlSearchNs (doc, node, s_prefix); + xmlFree ((xmlChar *) s_prefix); + if (ns == NULL) + { + return NULL; + } + return xmljNewString (env, ns->href); +} + +JNIEXPORT jint JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_xmljCompareTo (JNIEnv * env, + jobject self, + jobject other) +{ + xmlNodePtr n1, n2, x; + int d1, d2, delta, c; + + n1 = xmljGetNodeID (env, self); + n2 = xmljGetNodeID (env, other); + if (n1->doc != n2->doc) + { + return 0; + } + if (n1->type == XML_ATTRIBUTE_NODE || n2->type == XML_ATTRIBUTE_NODE) + { + return 0; + } + d1 = 0; + for (x = n1->parent; x && x->type != XML_DOCUMENT_NODE; x = x->parent) + { + d1++; + } + d2 = 0; + for (x = n2->parent; x && x->type != XML_DOCUMENT_NODE; x = x->parent) + { + d2++; + } + delta = d1 - d2; + while (d1 > d2) + { + n1 = n1->parent; + d1--; + } + while (d2 > d1) + { + n2 = n2->parent; + d2--; + } + c = xmljCompare (n1, n2); + return (c != 0) ? c : delta; +} + +/* Compare at same level */ +int +xmljCompare (xmlNodePtr n1, xmlNodePtr n2) +{ + int c, i1, i2; + + if (n1->parent == NULL || n1->type == XML_DOCUMENT_NODE || + n2->parent == NULL || n2->type == XML_DOCUMENT_NODE || + n1 == n2) + { + return 0; + } + c = xmljCompare (n1->parent, n2->parent); + if (c != 0) + { + return c; + } + i1 = 0; + for (n1 = n1->prev; n1; n1 = n1->prev) + { + i1++; + } + i2 = 0; + for (n2 = n2->prev; n2; n2 = n2->prev) + { + i2++; + } + return i1 - i2; +} + +int +xmljIsEqualNodeList (xmlNodePtr node1, xmlNodePtr node2) +{ + while (node1 != NULL) + { + if (!xmljIsEqualNode (node1, node2)) + { + return 0; + } + node1 = node1->next; + node2 = node2->next; + } + return 1; +} + +int +xmljIsEqualNode (xmlNodePtr node1, xmlNodePtr node2) +{ + const xmlChar *val1; + const xmlChar *val2; + + if (node1 == node2) + { + return 1; + } + if (node1 == NULL || node2 == NULL) + { + return 0; + } + /* Check node type */ + if (node1->type != node2->type) + { + return 0; + } + /* Check node name */ + if (!xmlStrEqual (node1->name, node2->name)) + { + return 0; + } + /* Check node namespace */ + if (node1->type == XML_ELEMENT_NODE || + node1->type == XML_ATTRIBUTE_NODE) + { + xmlNsPtr ns1, ns2; + + ns1 = node1->ns; + if (ns1 != NULL) + { + ns2 = node2->ns; + if (ns2 == NULL) + { + return 0; + } + val1 = ns1->href; + val2 = ns2->href; + if (!xmlStrEqual (val1, val2)) + { + return 0; + } + } + } + /* Check node value */ + val1 = xmljGetNodeValue (node1); + val2 = xmljGetNodeValue (node2); + if (!xmlStrEqual (val1, val2)) + { + return 0; + } + /* Check attributes */ + if (node1->type == XML_ELEMENT_NODE && + !xmljIsEqualNodeList ((xmlNodePtr) node1->properties, + (xmlNodePtr) node2->properties)) + { + return 0; + } + /* Check doctype */ + if (node1->type == XML_DOCUMENT_NODE) + { + xmlDocPtr doc1 = (xmlDocPtr) node1; + xmlDocPtr doc2 = (xmlDocPtr) node2; + + if (!xmljIsEqualNode ((xmlNodePtr) doc1->intSubset, + (xmlNodePtr) doc2->intSubset) || + !xmljIsEqualNode ((xmlNodePtr) doc1->extSubset, + (xmlNodePtr) doc2->extSubset)) + { + return 0; + } + } + /* Check child nodes */ + if (!xmljIsEqualNodeList (node1->children, node2->children)) + { + return 0; + } + return 1; +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNode_isEqualNode (JNIEnv * env, + jobject self, + jobject arg) +{ + xmlNodePtr node1; + xmlNodePtr node2; + + node1 = xmljGetNodeID (env, self); + node2 = xmljGetNodeID (env, arg); + return xmljIsEqualNode (node1, node2); +} + +/* -- GnomeNodeList -- */ + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNodeList_item (JNIEnv * env, + jobject self, jint index) +{ + xmlNodePtr node; + jint count; + + node = xmljGetNodeID (env, self); + node = node->children; + count = 0; + for (count = 0; node != NULL && count < index; count++) + { + node = node->next; + } + return xmljGetNodeInstance (env, node); +} + +JNIEXPORT jint JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNodeList_getLength (JNIEnv * env, jobject self) +{ + xmlNodePtr node; + jint count; + + node = xmljGetNodeID (env, self); + count = 0; + node = node->children; + while (node != NULL) + { + count++; + node = node->next; + } + return count; +} + +/* -- GnomeNotation -- */ + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNotation_getPublicId (JNIEnv * env, + jobject self) +{ + xmlNotationPtr notation; + + notation = (xmlNotationPtr) xmljGetNodeID (env, self); + if (notation->PublicID == NULL) + { + return NULL; + } + return xmljNewString (env, notation->PublicID); +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeNotation_getSystemId (JNIEnv * env, + jobject self) +{ + xmlNotationPtr notation; + + notation = (xmlNotationPtr) xmljGetNodeID (env, self); + if (notation->SystemID == NULL) + { + return NULL; + } + return xmljNewString (env, notation->SystemID); +} + +/* -- GnomeProcessingInstruction -- */ + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeProcessingInstruction_getData (JNIEnv * env, + jobject self) +{ + xmlNodePtr node; + xmlChar *text; + jstring ret; + + node = xmljGetNodeID (env, self); + text = xmlNodeGetContent (node); + ret = xmljNewString (env, (const xmlChar *) text); + if (text != NULL) + { + xmlFree (text); + } + return ret; +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeProcessingInstruction_setData (JNIEnv * env, + jobject self, + jstring data) +{ + xmlNodePtr node; + const xmlChar *s_data; + + node = xmljGetNodeID (env, self); + s_data = xmljGetStringChars (env, data); + xmlNodeSetContent (node, s_data); +} + +/* -- GnomeTypeInfo -- */ + +xmlDtdPtr xmljGetDtd (xmlDocPtr doc) +{ + xmlNodePtr ctx; + + for (ctx = doc->children; ctx; ctx = ctx->next) + { + if (ctx->type == XML_DOCUMENT_TYPE_NODE) + { + return (xmlDtdPtr) ctx; + } + } + return NULL; +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeTypeInfo_getTypeName (JNIEnv *env, jobject self) +{ + xmlNodePtr node; + xmlDtdPtr dtd; + xmlAttributePtr attribute; + + node = xmljGetNodeID (env, self); + dtd = xmljGetDtd (node->doc); + if (dtd) + { + switch (node->type) + { + case XML_ATTRIBUTE_NODE: + attribute = xmlGetDtdAttrDesc (dtd, node->parent->name, node->name); + if (attribute) + { + switch (attribute->type) + { + case XML_ATTRIBUTE_CDATA: + return xmljNewString (env, BAD_CAST "CDATA"); + case XML_ATTRIBUTE_ID: + return xmljNewString (env, BAD_CAST "ID"); + case XML_ATTRIBUTE_IDREF: + return xmljNewString (env, BAD_CAST "IDREF"); + case XML_ATTRIBUTE_IDREFS: + return xmljNewString (env, BAD_CAST "IDREFS"); + case XML_ATTRIBUTE_ENTITY: + return xmljNewString (env, BAD_CAST "ENTITY"); + case XML_ATTRIBUTE_ENTITIES: + return xmljNewString (env, BAD_CAST "ENTITIES"); + case XML_ATTRIBUTE_NMTOKEN: + return xmljNewString (env, BAD_CAST "NMTOKEN"); + case XML_ATTRIBUTE_NMTOKENS: + return xmljNewString (env, BAD_CAST "NMTOKENS"); + default: + return NULL; + } + } + return NULL; + default: + return NULL; + } + } + /* TODO when XML Schema support is available */ + return NULL; +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeTypeInfo_getTypeNamespace (JNIEnv *env, + jobject self) +{ + xmlNodePtr node; + xmlDtdPtr dtd; + xmlAttributePtr attribute; + + node = xmljGetNodeID (env, self); + dtd = xmljGetDtd (node->doc); + if (dtd) + { + switch (node->type) + { + case XML_ATTRIBUTE_NODE: + attribute = xmlGetDtdAttrDesc (dtd, node->parent->name, node->name); + if (attribute) + { + return xmljNewString (env, + BAD_CAST "http://www.w3.org/TR/REC-xml"); + } + return NULL; + default: + return NULL; + } + } + /* TODO when XML Schema support is available */ + return NULL; +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeTypeInfo_isDerivedFrom (JNIEnv *env + __attribute__ ((__unused__)), + jobject self + __attribute__ ((__unused__)), + jstring typeNS + __attribute__ ((__unused__)), + jstring typeName + __attribute__ ((__unused__)), + jint method + __attribute__ ((__unused__))) +{ + /* TODO when XML Schema support is available */ + return 0; +} + +/* -- Utility -- */ + +/* + * Create GnomeDocument object from the given xmlDocPtr + */ +jobject +xmljCreateDocument (JNIEnv * env, jobject self, xmlDocPtr doc) +{ + jclass cls; + jfieldID field; + jobject ret; + + if (!doc) + { + return NULL; + } + + /* Get document object */ + ret = xmljGetNodeInstance (env, (xmlNodePtr) doc); + + /* Set DOM implementation field */ + cls = (*env)->FindClass (env, "gnu/xml/libxmlj/dom/GnomeDocument"); + field = (*env)->GetFieldID (env, cls, "dom", + "Lorg/w3c/dom/DOMImplementation;"); + (*env)->SetObjectField (env, ret, field, self); + return ret; +} + +xmlAttrPtr +xmljGetNamedItem (JNIEnv * env, jobject self, jstring name) +{ + xmlNodePtr node; + xmlAttrPtr attr; + const xmlChar *s_name; + + s_name = xmljGetStringChars (env, name); + + node = xmljGetNodeID (env, self); + attr = node->properties; + while (attr != NULL) + { + if (xmljMatch (s_name, (xmlNodePtr) attr)) + break; + attr = attr->next; + } + xmlFree ((xmlChar *) s_name); + + return attr; +} + +xmlAttrPtr +xmljGetNamedItemNS (JNIEnv * env, jobject self, jstring uri, jstring localName) +{ + xmlNodePtr node; + xmlAttrPtr attr; + const xmlChar *s_uri; + const xmlChar *s_localName; + + s_uri = xmljGetStringChars (env, uri); + s_localName = xmljGetStringChars (env, localName); + + node = xmljGetNodeID (env, self); + attr = node->properties; + while (attr != NULL) + { + if (xmljMatchNS (s_uri, s_localName, (xmlNodePtr) attr)) + break; + attr = attr->next; + } + xmlFree ((xmlChar *) s_uri); + xmlFree ((xmlChar *) s_localName); + + return attr; +} diff --git a/libjava/classpath/native/jni/xmlj/xmlj_dom.h b/libjava/classpath/native/jni/xmlj/xmlj_dom.h new file mode 100644 index 00000000000..d4a1dff420c --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_dom.h @@ -0,0 +1,70 @@ +/* xmlj_dom.h - + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef XMLJ_DOM_H +#define XMLJ_DOM_H + +#include "gnu_xml_libxmlj_dom_GnomeAttr.h" +#include "gnu_xml_libxmlj_dom_GnomeDocument.h" +#include "gnu_xml_libxmlj_dom_GnomeDocumentBuilder.h" +#include "gnu_xml_libxmlj_dom_GnomeDocumentType.h" +#include "gnu_xml_libxmlj_dom_GnomeElement.h" +#include "gnu_xml_libxmlj_dom_GnomeEntity.h" +#include "gnu_xml_libxmlj_dom_GnomeNamedNodeMap.h" +#include "gnu_xml_libxmlj_dom_GnomeNode.h" +#include "gnu_xml_libxmlj_dom_GnomeNodeList.h" +#include "gnu_xml_libxmlj_dom_GnomeNotation.h" +#include "gnu_xml_libxmlj_dom_GnomeProcessingInstruction.h" +#include "gnu_xml_libxmlj_dom_GnomeTypeInfo.h" + +#include <libxml/parser.h> +#include <libxml/valid.h> + +void xmljValidateChildNode (JNIEnv *env, xmlNodePtr parent, xmlNodePtr child); +int xmljIsEqualNode (xmlNodePtr node1, xmlNodePtr node2); +int xmljIsEqualNodeList (xmlNodePtr node1, xmlNodePtr node2); +void xmljNormalizeNode (xmlNodePtr node); +xmlDtdPtr xmljGetDtd (xmlDocPtr doc); +int xmljCompare (xmlNodePtr n1, xmlNodePtr n2); + +/* Utility */ +jobject xmljCreateDocument (JNIEnv * env, jobject self, xmlDocPtr doc); +xmlAttrPtr xmljGetNamedItem (JNIEnv * env, jobject self, jstring name); +xmlAttrPtr xmljGetNamedItemNS (JNIEnv * env, jobject self, jstring uri, + jstring localName); + +#endif /* !defined XMLJ_DOM_H */ diff --git a/libjava/classpath/native/jni/xmlj/xmlj_error.c b/libjava/classpath/native/jni/xmlj/xmlj_error.c new file mode 100644 index 00000000000..5dd90552c35 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_error.c @@ -0,0 +1,169 @@ +/* xmlj_error.c - + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "xmlj_error.h" +#include "xmlj_io.h" +#include "xmlj_util.h" + +void +xmljXsltErrorFunc (void *ctx, const char *msg, ...) +{ + if (NULL != ctx) + { + SAXParseContext *sax = ((SAXParseContext *) ctx); + + if (NULL != sax) + { + JNIEnv *env = sax->env; + + if (!(*env)->ExceptionOccurred (env)) + { + jobject target = sax->obj; + xmlChar *x_msg; + jstring j_msg; + va_list args; + + if (sax->error == NULL) + { + sax->error = + xmljGetMethodID (env, + target, + "error", + "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V"); + if (sax->error == NULL) + { + return; + } + } + + va_start (args, msg); + x_msg = (msg == NULL) ? NULL : xmlCharStrdup (msg); + va_end (args); + j_msg = xmljNewString (env, x_msg); + + (*env)->CallVoidMethod (env, + target, + sax->error, + j_msg, + -1, + -1, + NULL, + NULL); + } + } + } + else + { + va_list va; + va_start (va, msg); + fprintf (stderr, "libxslt error: "); + vfprintf (stderr, msg, va); + fflush (stderr); + va_end (va); + } +} + +void +xmljThrowException (JNIEnv *env, + const char *classname, + const char *message) +{ + jclass cls; + jmethodID method; + jthrowable ex; + jstring jmsg; + + /*fprintf(stderr, "Throwing exception %s %s\n", classname, message);*/ + cls = (*env)->FindClass (env, classname); + if (cls == NULL) + { + fprintf (stderr, "Can't find class %s\n", classname); + fflush (stderr); + return; + } + method = (*env)->GetMethodID (env, cls, "<init>", "(Ljava/lang/String;)V"); + if (method == NULL) + { + fprintf (stderr, "Can't find method %s.<init>\n", classname); + fflush (stderr); + return; + } + jmsg = (message == NULL) ? NULL : (*env)->NewStringUTF (env, message); + ex = (jthrowable) (*env)->NewObject (env, cls, method, jmsg); + if (ex == NULL) + { + fprintf (stderr, "Can't instantiate new %s\n", classname); + fflush (stderr); + return; + } + (*env)->Throw (env, ex); +} + +void +xmljThrowDOMException (JNIEnv *env, + int code, + const char *message) +{ + jclass cls; + jmethodID method; + jthrowable ex; + jstring jmsg; + + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + cls = (*env)->FindClass (env, "gnu/xml/libxmlj/dom/GnomeDOMException"); + if (cls == NULL) + { + fprintf (stderr, "Can't find DOMException class!\n"); + fflush (stderr); + return; + } + method = (*env)->GetMethodID (env, cls, "<init>", "(SLjava/lang/String;)V"); + if (method == NULL) + { + fprintf (stderr, "Can't find DOMException constructor!\n"); + fflush (stderr); + return; + } + jmsg = (message == NULL) ? NULL : (*env)->NewStringUTF (env, message); + ex = (jthrowable) (*env)->NewObject (env, cls, method, code, jmsg); + (*env)->Throw (env, ex); +} + diff --git a/libjava/classpath/native/jni/xmlj/xmlj_error.h b/libjava/classpath/native/jni/xmlj/xmlj_error.h new file mode 100644 index 00000000000..a0c9fcc8042 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_error.h @@ -0,0 +1,85 @@ +/* xmlj_error.h - + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef XMLJ_ERROR_H +#define XMLJ_ERROR_H + +#include <jni.h> +#include <libxml/xmlIO.h> + +/* +typedef struct SaxErrorContext_ +{ + JNIEnv * env; + jobject saxErrorAdapter; + jmethodID saxCommentMethodID; + jmethodID saxWarningMethodID; + jmethodID saxErrorMethodID; + jmethodID saxFatalErrorMethodID; + jclass sourceLocatorClass; + jmethodID sourceLocatorConstructor; + xmlSAXLocatorPtr locator; + jstring publicId; + jstring systemId; + const char *publicIdCstr; + const char *systemIdCstr; + jmethodID resolveURIMethodID; + jmethodID resolveURIAndOpenMethodID; + jmethodID getInputStreamMethodID; + jmethodID xsltGenericErrorMethodID; + jobject theTransformerException; + jmethodID getNativeHandleMethodID; +} SaxErrorContext; + +SaxErrorContext * xmljCreateSaxErrorContext (JNIEnv * env, + jobject errorContext, + jstring systemId, + jstring publicId); + +void xmljFreeSaxErrorContext (SaxErrorContext * errorContext); + +void xmljInitErrorHandling (xmlSAXHandler * saxHandler); +*/ + +void xmljXsltErrorFunc (void *ctx, const char *msg, ...); + +void xmljThrowException (JNIEnv *, const char *classname, const char *message); + +void xmljThrowDOMException (JNIEnv *, int code, const char *message); + +#endif /* !defined XMLJ_ERROR_H */ + diff --git a/libjava/classpath/native/jni/xmlj/xmlj_io.c b/libjava/classpath/native/jni/xmlj/xmlj_io.c new file mode 100644 index 00000000000..aa2964dc312 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_io.c @@ -0,0 +1,799 @@ +/* xmlj_io.c - + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "xmlj_io.h" +#include "xmlj_error.h" +#include "xmlj_node.h" +#include "xmlj_sax.h" +#include "xmlj_util.h" + +#include <math.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> + +#include <libxml/xmlIO.h> +#include <libxml/parserInternals.h> + +#include <pthread.h> + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define UNSIGN(a) (((a) < 0) ? ((a) + 0x100) : (a)) + +#define DETECT_BUFFER_SIZE 50 + +typedef struct _OutputStreamContext +{ + + JNIEnv *env; + jobject outputStream; + jmethodID outputStreamWriteFunc; + jmethodID outputStreamCloseFunc; + +} +OutputStreamContext; + +typedef struct _InputStreamContext +{ + + JNIEnv *env; + jobject inputStream; + jmethodID inputStreamReadFunc; + jmethodID inputStreamCloseFunc; + jobject bufferByteArray; + jint bufferLength; + +} +InputStreamContext; + +InputStreamContext *xmljNewInputStreamContext (JNIEnv * env, + jobject inputStream); + +void xmljFreeInputStreamContext (InputStreamContext * inContext); + +int xmljInputReadCallback (void *context, char *buffer, int len); + +int xmljInputCloseCallback (void *context); + +int xmljOutputWriteCallback (void *context, const char *buffer, int len); + +int xmljOutputCloseCallback (void *context); + +OutputStreamContext *xmljNewOutputStreamContext (JNIEnv * env, + jobject outputStream); + +void +xmljFreeOutputStreamContext (OutputStreamContext * outContext); + +xmlCharEncoding +xmljDetectCharEncoding (JNIEnv * env, jbyteArray buffer); + +int +xmljOutputWriteCallback (void *context, const char *buffer, int len) +{ + OutputStreamContext *outContext; + JNIEnv *env; + jbyteArray byteArray; + + outContext = (OutputStreamContext *) context; + env = outContext->env; + byteArray = (*env)->NewByteArray (env, len); + + if (0 != byteArray) + { + (*env)->SetByteArrayRegion (env, byteArray, 0, len, (jbyte *) buffer); + + (*env)->CallVoidMethod (env, + outContext->outputStream, + outContext->outputStreamWriteFunc, byteArray); + + (*env)->DeleteLocalRef (env, byteArray); + + return (*env)->ExceptionOccurred (env) ? -1 : len; + } + else + { + /* Out of memory, signal error */ + return -1; + } +} + +int +xmljOutputCloseCallback (void *context) +{ + OutputStreamContext *outContext; + JNIEnv *env; + + outContext = (OutputStreamContext *) context; + env = outContext->env; + (*env)->CallVoidMethod (env, + outContext->outputStream, + outContext->outputStreamCloseFunc); + + return (*env)->ExceptionOccurred (env) ? -1 : 0; +} + +int +xmljInputReadCallback (void *context, char *buffer, int len) +{ + InputStreamContext *inContext; + JNIEnv *env; + jint nread; + int offset; + + inContext = (InputStreamContext *) context; + env = inContext->env; + nread = 0; + + for (offset = 0; offset < len && nread >= 0;) + { + nread = (*env)->CallIntMethod (env, + inContext->inputStream, + inContext->inputStreamReadFunc, + inContext->bufferByteArray, + 0, MIN (len - offset, + inContext->bufferLength)); + + if (nread > 0) + { + (*env)->GetByteArrayRegion (env, + inContext->bufferByteArray, + 0, nread, ((jbyte *) buffer) + offset); + + offset += nread; + } + } + + return (*env)->ExceptionOccurred (env) ? -1 : offset; +} + +int +xmljInputCloseCallback (void *context) +{ + InputStreamContext *inContext; + JNIEnv *env; + + inContext = (InputStreamContext *) context; + env = inContext->env; + (*env)->CallVoidMethod (env, inContext->inputStream, + inContext->inputStreamCloseFunc); + + return (*env)->ExceptionOccurred (env) ? -1 : 0; +} + +InputStreamContext * +xmljNewInputStreamContext (JNIEnv * env, jobject inputStream) +{ + jclass inputStreamClass; + InputStreamContext *result; + + inputStreamClass = (*env)->FindClass (env, "java/io/InputStream"); + if (inputStreamClass == NULL) + { + return NULL; + } + result = (InputStreamContext *) malloc (sizeof (InputStreamContext)); + if (result == NULL) + { + return NULL; + } + + result->env = env; + result->inputStream = inputStream; + result->inputStreamReadFunc = + (*env)->GetMethodID (env, inputStreamClass, "read", "([BII)I"); + result->inputStreamCloseFunc = + (*env)->GetMethodID (env, inputStreamClass, "close", "()V"); + result->bufferLength = 4096; + result->bufferByteArray = (*env)->NewByteArray (env, result->bufferLength); + return result; +} + +void +xmljFreeInputStreamContext (InputStreamContext * inContext) +{ + JNIEnv *env; + + env = inContext->env; + (*env)->DeleteLocalRef (env, inContext->bufferByteArray); + free (inContext); +} + +OutputStreamContext * +xmljNewOutputStreamContext (JNIEnv * env, jobject outputStream) +{ + jclass outputStreamClass; + OutputStreamContext *result; + + outputStreamClass = (*env)->FindClass (env, "java/io/OutputStream"); + if (outputStreamClass == NULL) + { + return NULL; + } + result = (OutputStreamContext *) malloc (sizeof (OutputStreamContext)); + if (result == NULL) + { + return NULL; + } + + result->env = env; + result->outputStream = outputStream; + result->outputStreamWriteFunc = + (*env)->GetMethodID (env, outputStreamClass, "write", "([B)V"); + result->outputStreamCloseFunc = + (*env)->GetMethodID (env, outputStreamClass, "close", "()V"); + return result; +} + + +void +xmljFreeOutputStreamContext (OutputStreamContext * outContext) +{ + free (outContext); +} + +SAXParseContext * +xmljNewSAXParseContext (JNIEnv * env, jobject obj, xmlParserCtxtPtr ctx, + jstring publicId, jstring systemId) +{ + SAXParseContext *ret; + + ret = (SAXParseContext *) malloc (sizeof (SAXParseContext)); + ret->env = env; + ret->obj = obj; + ret->ctx = ctx; + ret->sax = ctx->sax; + ret->loc = NULL; + ret->publicId = publicId; + ret->systemId = systemId; + + ret->startDTD = NULL; + ret->externalEntityDecl = NULL; + ret->internalEntityDecl = NULL; + ret->resolveEntity = NULL; + ret->notationDecl = NULL; + ret->attributeDecl = NULL; + ret->elementDecl = NULL; + ret->unparsedEntityDecl = NULL; + ret->setDocumentLocator = NULL; + ret->startDocument = NULL; + ret->endDocument = NULL; + ret->startElement = NULL; + ret->endElement = NULL; + ret->characters = NULL; + ret->ignorableWhitespace = NULL; + ret->processingInstruction = NULL; + ret->comment = NULL; + ret->cdataBlock = NULL; + ret->warning = NULL; + ret->error = NULL; + ret->fatalError = NULL; + + ret->resolveURIAndOpen = NULL; + ret->stringClass = NULL; + return ret; +} + +void +xmljFreeSAXParseContext (SAXParseContext * saxCtx) +{ + free (saxCtx); +} + +xmlCharEncoding +xmljDetectCharEncoding (JNIEnv * env, jbyteArray buffer) +{ + xmlCharEncoding ret; + jint nread; + + if (buffer == NULL) + { + return XML_CHAR_ENCODING_ERROR; + } + nread = (*env)->GetArrayLength (env, buffer); + if (nread >= 5) + { + jbyte nativeBuffer[DETECT_BUFFER_SIZE + 1]; + unsigned char converted[DETECT_BUFFER_SIZE + 1]; + int i; + + memset (nativeBuffer, 0, DETECT_BUFFER_SIZE + 1); + (*env)->GetByteArrayRegion (env, buffer, 0, nread, nativeBuffer); + /* Convert from signed to unsigned */ + for (i = 0; i < DETECT_BUFFER_SIZE + 1; i++) + { + converted[i] = UNSIGN (nativeBuffer[i]); + } + ret = xmlDetectCharEncoding (converted, nread); + } + else + { + ret = XML_CHAR_ENCODING_NONE; + } + return ret; +} + +xmlParserCtxtPtr +xmljNewParserContext (JNIEnv * env, + jobject inputStream, + jbyteArray detectBuffer, + jstring publicId, + jstring systemId, + jstring base, + jboolean validate, + jboolean coalesce, + jboolean expandEntities, + jboolean loadEntities) +{ + InputStreamContext *inputContext; + xmlCharEncoding encoding; + xmlParserCtxtPtr ctx; + int options; + + encoding = xmljDetectCharEncoding (env, detectBuffer); + if (encoding != XML_CHAR_ENCODING_ERROR) + { + inputContext = xmljNewInputStreamContext (env, inputStream); + if (NULL != inputContext) + { + /* NOTE: userdata must be NULL for DOM to work */ + ctx = xmlCreateIOParserCtxt (NULL, + NULL, + xmljInputReadCallback, + xmljInputCloseCallback, + inputContext, + encoding); + if (NULL != ctx) + { + ctx->userData = ctx; + + /* Set parsing options */ + options = 0; + if (validate) + { + options |= XML_PARSE_DTDVALID; + } + if (coalesce) + { + options |= XML_PARSE_NOCDATA; + } + if (expandEntities) + { + options |= XML_PARSE_NOENT; + } + if (loadEntities) + { + options |= XML_PARSE_DTDLOAD; + } + if (xmlCtxtUseOptions (ctx, options)) + { + xmljThrowException (env, + "java/lang/RuntimeException", + "Unable to set xmlParserCtxtPtr options"); + } + if (base != NULL) + { + ctx->input->directory = + (*env)->GetStringUTFChars (env, base, 0); + } + return ctx; + } + xmljFreeInputStreamContext (inputContext); + } + } + return NULL; +} + +void +xmljFreeParserContext (xmlParserCtxtPtr ctx) +{ + InputStreamContext *inputStreamContext = NULL; + + if (ctx->input != NULL && ctx->input->buf != NULL) + { + inputStreamContext + = (InputStreamContext *) ctx->input->buf->context; + + } + xmlFreeParserCtxt (ctx); + if (inputStreamContext != NULL) + { + xmljFreeInputStreamContext (inputStreamContext); + } +} + +xmlDocPtr +xmljParseDocument (JNIEnv * env, + jobject self, + jobject in, + jbyteArray detectBuffer, + jstring publicId, + jstring systemId, + jstring base, + jboolean validate, + jboolean coalesce, + jboolean expandEntities, + jboolean contentHandler, + jboolean dtdHandler, + jboolean entityResolver, + jboolean errorHandler, + jboolean declarationHandler, + jboolean lexicalHandler, + int mode) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *saxCtx; + xmlSAXHandlerPtr sax; + + ctx = xmljNewParserContext (env, in, detectBuffer, publicId, systemId, base, + validate, coalesce, expandEntities, + entityResolver); + if (ctx != NULL) + { + saxCtx = xmljNewSAXParseContext (env, self, ctx, publicId, systemId); + if (saxCtx != NULL) + { + sax = xmljNewSAXHandler (contentHandler, + dtdHandler, + entityResolver, + errorHandler, + declarationHandler, + lexicalHandler); + if (sax != NULL) + { + return xmljParseDocument2 (env, + ctx, + saxCtx, + sax, + mode); + } + xmljFreeSAXParseContext (saxCtx); + } + xmljFreeParserContext (ctx); + } + if (!(*env)->ExceptionOccurred (env)) + { + xmljThrowException (env, "java/io/IOException", + "Unable to create parser context"); + } + return NULL; +} + +xmlDocPtr +xmljParseDocument2 (JNIEnv * env, + xmlParserCtxtPtr ctx, + SAXParseContext *saxCtx, + xmlSAXHandlerPtr sax, + int mode) +{ + xmlSAXHandlerPtr orig; + xmlDocPtr doc; + int ret; + + ctx->_private = saxCtx; + ctx->userData = ctx; + orig = ctx->sax; + ctx->sax = sax; + + xmljSetThreadContext (saxCtx); + + ret = xmlParseDocument (ctx); + doc = ctx->myDoc; + if (ret || !doc) + { + const char *msg = ctx->lastError.message; + switch (mode) + { + case 0: + xmljSAXFatalError (ctx, msg); + break; + case 1: + xmljThrowDOMException (env, ret, msg); + break; + case 2: + xmljThrowException (env, + "javax/xml/transform/TransformerException", + msg); + } + } + + xmljClearThreadContext (); + + ctx->sax = orig; + free(sax); + xmljFreeSAXParseContext (saxCtx); + xmljFreeParserContext (ctx); + xmljClearStringCache (); + return doc; +} + +xmlParserInputPtr +xmljNewParserInput (JNIEnv * env, + jobject inputStream, + jbyteArray detectBuffer, + xmlParserCtxtPtr parserContext) +{ + xmlParserInputPtr ret; + xmlParserInputBufferPtr input; + xmlCharEncoding encoding; + + encoding = xmljDetectCharEncoding (env, detectBuffer); + if (encoding != XML_CHAR_ENCODING_ERROR) + { + input = xmljNewParserInputBuffer (env, inputStream, encoding); + if (input != NULL) + { + ret = xmlNewIOInputStream (parserContext, input, encoding); + return ret; + } + xmlFreeParserInputBuffer (input); + } + return NULL; +} + +xmlParserInputBufferPtr +xmljNewParserInputBuffer (JNIEnv * env, + jobject inputStream, xmlCharEncoding encoding) +{ + xmlParserInputBufferPtr ret; + InputStreamContext *inputContext; + + inputContext = xmljNewInputStreamContext (env, inputStream); + if (NULL != inputContext) + { + ret = xmlParserInputBufferCreateIO (&xmljInputReadCallback, + &xmljInputCloseCallback, + inputContext, encoding); + if (ret != NULL) + return ret; + xmljFreeInputStreamContext (inputContext); + } + return NULL; +} + +void +xmljSaveFileToJavaOutputStream (JNIEnv * env, jobject outputStream, + xmlDocPtr tree, + const char *outputEncodingName) +{ + OutputStreamContext *outputContext = + xmljNewOutputStreamContext (env, outputStream); + + xmlCharEncoding outputEncoding = xmlParseCharEncoding (outputEncodingName); + + xmlOutputBufferPtr outputBuffer = + xmlOutputBufferCreateIO (xmljOutputWriteCallback, + xmljOutputCloseCallback, + outputContext, + xmlGetCharEncodingHandler (outputEncoding)); + + /* Write result to output stream */ + + xmlSaveFileTo (outputBuffer, tree, outputEncodingName); + + xmljFreeOutputStreamContext (outputContext); +} + +/* +jobject +xmljResolveURI (SaxErrorContext * saxErrorContext, + const char *URL, const char *ID) +{ + JNIEnv *env = saxErrorContext->env; + + jstring hrefString = (*env)->NewStringUTF (env, URL); + jstring baseString = saxErrorContext->systemId; + + jobject sourceWrapper = (*env)->CallObjectMethod (env, + saxErrorContext-> + saxErrorAdapter, + saxErrorContext-> + resolveURIMethodID, + hrefString, + baseString); + (*env)->DeleteLocalRef (env, hrefString); + + if (NULL == sourceWrapper) + { + return NULL; + } + else + { + jobject sourceInputStream = (*env)->CallObjectMethod (env, + sourceWrapper, + saxErrorContext-> + getInputStreamMethodID); + + (*env)->DeleteLocalRef (env, sourceWrapper); + + if ((*env)->ExceptionOccurred (env)) + { + -* Report to ErrorAdapter here? *- + return NULL; + } + + return sourceInputStream; + } +}*/ + +xmlDocPtr +xmljResolveURIAndOpen (SAXParseContext *saxContext, + const char *URL, + const char *ID) +{ + jobject libxmlDocument; + xmlDocPtr doc; + JNIEnv *env = saxContext->env; + + jstring hrefString = (*env)->NewStringUTF (env, URL); + jstring baseString = saxContext->systemId; + + if (saxContext->resolveURIAndOpen == NULL) + { + jclass cls = (*env)->GetObjectClass (env, saxContext->obj); + saxContext->resolveURIAndOpen = + (*env)->GetMethodID (env, cls, "resolveURIAndOpen", + "Ljava/lang/String;Ljava/lang/String)Lgnu/xml/libxmlj/transform/LibxmlDocument;"); + } + libxmlDocument = + (*env)->CallObjectMethod (env, + saxContext->obj, + saxContext->resolveURIAndOpen, + hrefString, + baseString); + + doc = (xmlDocPtr) xmljGetNodeID (env, libxmlDocument); + + (*env)->DeleteLocalRef (env, libxmlDocument); + + if ((*env)->ExceptionOccurred (env)) + { + /* Report to ErrorAdapter here? */ + return NULL; + } + else + { + return doc; + } +} + +/*xmlParserInputPtr +xmljLoadExternalEntity (const char *URL, const char *ID, + xmlParserCtxtPtr ctxt) +{ + SaxErrorContext *saxErrorContext = xmljGetThreadContext (); + + JNIEnv *env = saxErrorContext->env; + + jstring hrefString = (*env)->NewStringUTF (env, URL); + jstring baseString = saxErrorContext->systemId; + + jobject sourceWrapper = (*env)->CallObjectMethod (env, + saxErrorContext-> + saxErrorAdapter, + saxErrorContext-> + resolveURIMethodID, + hrefString, + baseString); + + (*env)->DeleteLocalRef (env, hrefString); + + if (NULL == sourceWrapper) + { + return NULL; + } + else + { + InputStreamContext *inputContext; + xmlParserInputBufferPtr inputBuffer; + xmlParserInputPtr inputStream; + + jobject sourceInputStream = (*env)->CallObjectMethod (env, + sourceWrapper, + saxErrorContext-> + getInputStreamMethodID); + + (*env)->DeleteLocalRef (env, sourceWrapper); + + if ((*env)->ExceptionOccurred (env)) + { + -* Report to ErrorAdapter *- + return NULL; + } + + inputContext = xmljNewInputStreamContext (env, sourceInputStream); + + inputBuffer + = xmlParserInputBufferCreateIO (xmljInputReadCallback, + xmljInputCloseCallback, + inputContext, XML_CHAR_ENCODING_NONE); + + inputStream = xmlNewInputStream (ctxt); + if (inputStream == NULL) + { + return (NULL); + } + + inputStream->filename = NULL; + inputStream->directory = NULL; + inputStream->buf = inputBuffer; + + inputStream->base = inputStream->buf->buffer->content; + inputStream->cur = inputStream->buf->buffer->content; + inputStream->end = &inputStream->base[inputStream->buf->buffer->use]; + if ((ctxt->directory == NULL) && (inputStream->directory != NULL)) + ctxt->directory = + (char *) xmlStrdup ((const xmlChar *) inputStream->directory); + return (inputStream); + } +}*/ + +/* Key for the thread-specific buffer */ +static pthread_key_t thread_context_key; + +/* Once-only initialisation of the key */ +static pthread_once_t thread_context_once = PTHREAD_ONCE_INIT; + +static void +thread_context_key_alloc (void); + +/* Allocate the key */ +static void +thread_context_key_alloc () +{ + pthread_key_create (&thread_context_key, NULL); +} + +void +xmljSetThreadContext (SAXParseContext * context) +{ + pthread_once (&thread_context_once, thread_context_key_alloc); + pthread_setspecific (thread_context_key, context); +} + +void +xmljClearThreadContext (void) +{ + pthread_setspecific (thread_context_key, NULL); +} + +/* Return the thread-specific buffer */ +SAXParseContext * +xmljGetThreadContext (void) +{ + return (SAXParseContext *) pthread_getspecific (thread_context_key); +} diff --git a/libjava/classpath/native/jni/xmlj/xmlj_io.h b/libjava/classpath/native/jni/xmlj/xmlj_io.h new file mode 100644 index 00000000000..871859aca51 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_io.h @@ -0,0 +1,170 @@ +/* xmlj_io.h - + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef XMLJ_IO_H +#define XMLJ_IO_H + +#include <jni.h> +#include <libxml/xmlIO.h> +#include "xmlj_error.h" + +typedef struct _SAXParseContext +{ + + JNIEnv *env; /* Current JNI environment */ + jobject obj; /* The gnu.xml.libxmlj.sax.GnomeXmlReader instance */ + xmlParserCtxtPtr ctx; /* libxml2 parser context */ + xmlSAXLocatorPtr loc; /* libxml2 SAX locator */ + xmlSAXHandlerPtr sax; /* pristine SAX handler */ + jstring publicId; + jstring systemId; + + jmethodID startDTD; + jmethodID externalEntityDecl; + jmethodID internalEntityDecl; + jmethodID resolveEntity; + jmethodID notationDecl; + jmethodID attributeDecl; + jmethodID elementDecl; + jmethodID unparsedEntityDecl; + jmethodID setDocumentLocator; + jmethodID startDocument; + jmethodID endDocument; + jmethodID startElement; + jmethodID endElement; + jmethodID characters; + jmethodID ignorableWhitespace; + jmethodID processingInstruction; + jmethodID comment; + jmethodID cdataBlock; + jmethodID warning; + jmethodID error; + jmethodID fatalError; + + jmethodID resolveURIAndOpen; /* JavaProxy */ + jclass stringClass; +} +SAXParseContext; + +SAXParseContext * +xmljNewSAXParseContext (JNIEnv * env, jobject obj, xmlParserCtxtPtr ctx, + jstring publicId, jstring systemId); + +void +xmljFreeSAXParseContext (SAXParseContext * saxCtx); + +xmlParserCtxtPtr +xmljNewParserContext (JNIEnv * env, + jobject inputStream, + jbyteArray detectBuffer, + jstring publicId, + jstring systemId, + jstring base, + jboolean validate, + jboolean coalesce, + jboolean expandEntities, + jboolean loadEntities); + +void +xmljFreeParserContext (xmlParserCtxtPtr parserContext); + +xmlDocPtr +xmljParseDocument (JNIEnv * env, + jobject self, + jobject in, + jbyteArray detectBuffer, + jstring publicId, + jstring systemId, + jstring base, + jboolean validate, + jboolean coalesce, + jboolean expandEntities, + jboolean contentHandler, + jboolean dtdHandler, + jboolean entityResolver, + jboolean errorHandler, + jboolean declarationHandler, + jboolean lexicalHandler, + int saxMode); + +xmlDocPtr +xmljParseDocument2 (JNIEnv * env, + xmlParserCtxtPtr ctx, + SAXParseContext *saxCtx, + xmlSAXHandlerPtr sax, + int saxMode); + +xmlParserInputPtr +xmljNewParserInput (JNIEnv * env, + jobject inputStream, + jbyteArray detectBuffer, + xmlParserCtxtPtr parserContext); + +xmlParserInputBufferPtr +xmljNewParserInputBuffer (JNIEnv * env, + jobject inputStream, + xmlCharEncoding encoding); + +void +xmljSaveFileToJavaOutputStream (JNIEnv * env, jobject outputStream, + xmlDocPtr tree, + const char *outputEncoding); + +/* +xmlParserInputPtr +xmljLoadExternalEntity (const char *URL, const char *ID, + xmlParserCtxtPtr ctxt); + +jobject +xmljResolveURI (SaxErrorContext * saxErrorContext, const char *URL, + const char *ID); +*/ +xmlDocPtr +xmljResolveURIAndOpen (SAXParseContext *saxContext, + const char *URL, const char *ID); + + +void +xmljSetThreadContext (SAXParseContext * ctxt); + +SAXParseContext * +xmljGetThreadContext (void); + +void +xmljClearThreadContext (void); + +#endif /* !defined XMLJ_IO_H */ diff --git a/libjava/classpath/native/jni/xmlj/xmlj_node.c b/libjava/classpath/native/jni/xmlj/xmlj_node.c new file mode 100644 index 00000000000..20832678a25 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_node.c @@ -0,0 +1,203 @@ +/* xmlj_node.c - + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "xmlj_error.h" +#include "xmlj_node.h" +#include "xmlj_util.h" +#include <libxml/xmlstring.h> + +/* + * Returns the node ID for the given GnomeNode object. + */ +xmlNodePtr +xmljGetNodeID (JNIEnv * env, jobject self) +{ + jclass cls; + jfieldID field; + jobject id; + xmlNodePtr node; + + if (self == NULL) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + return NULL; + } + cls = (*env)->GetObjectClass (env, self); + if (cls == NULL) + { + return NULL; + } + field = (*env)->GetFieldID (env, cls, "id", "Ljava/lang/Object;"); + if (field == NULL) + { + return NULL; + } + id = (*env)->GetObjectField (env, self, field); + node = (xmlNodePtr) xmljAsPointer (env, id); + if (node == NULL) + { + xmljThrowDOMException (env, 8, NULL); /* NOT_FOUND_ERR */ + } + return node; +} + +/* + * Returns the Java node instanced corresponding to the specified node ID. + */ +jobject +xmljGetNodeInstance (JNIEnv * env, xmlNodePtr node) +{ + jclass cls; + jmethodID method; + xmlElementType type; + + if (node == NULL) + return NULL; + + /* Invoke the GnomeNode.newInstance class method */ + cls = (*env)->FindClass (env, "gnu/xml/libxmlj/dom/GnomeNode"); + if (cls == NULL) + { + return NULL; + } + method = (*env)->GetStaticMethodID (env, cls, "newInstance", + "(Ljava/lang/Object;Ljava/lang/Object;I)Lgnu/xml/libxmlj/dom/GnomeNode;"); + + if (method == NULL) + { + return NULL; + } + type = node->type; + switch (type) + { + case XML_DTD_NODE: + type = XML_DOCUMENT_TYPE_NODE; + break; + case XML_ATTRIBUTE_DECL: + type = XML_ATTRIBUTE_NODE; + break; + case XML_ENTITY_DECL: + type = XML_ENTITY_NODE; + break; + default: + break; + } + return (*env)->CallStaticObjectMethod (env, cls, method, + xmljAsField (env, node->doc), + xmljAsField (env, node), + type); +} + +void +xmljFreeDoc (JNIEnv * env, xmlDocPtr doc) +{ + jclass cls; + jmethodID method; + + /* Invoke the GnomeNode.freeDocument class method */ + cls = (*env)->FindClass (env, "gnu/xml/libxmlj/dom/GnomeNode"); + if (cls == NULL) + { + return; + } + method = (*env)->GetStaticMethodID (env, cls, "freeDocument", + "(Ljava/lang/Object;)V"); + if (method == NULL) + { + return; + } + (*env)->CallStaticVoidMethod (env, cls, method, xmljAsField (env, doc)); +} + +int +xmljMatch (const xmlChar * name, xmlNodePtr node) +{ + switch (node->type) + { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + return xmlStrcmp (node->name, name); + default: + return 1; + } +} + +int +xmljMatchNS (const xmlChar * uri, const xmlChar * localName, xmlNodePtr node) +{ + xmlNsPtr ns; + const xmlChar *nodeLocalName; + int *len; + int ret; + + switch (node->type) + { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + len = (int *) malloc (sizeof (int)); + if (xmlSplitQName3 (node->name, len) != NULL) + { + nodeLocalName = node->name + (*len); + } + else + { + nodeLocalName = node->name; + } + free (len); + ns = node->ns; + if (ns == NULL || ns->href == NULL) + { + if (uri != NULL) + { + return 0; + } + ret = xmlStrcmp (localName, nodeLocalName); + } + else + { + if (uri == NULL) + { + return 0; + } + ret = (xmlStrcmp (localName, nodeLocalName) && + xmlStrcmp (uri, ns->href)); + } + return ret; + default: + return 1; + } +} diff --git a/libjava/classpath/native/jni/xmlj/xmlj_node.h b/libjava/classpath/native/jni/xmlj/xmlj_node.h new file mode 100644 index 00000000000..11f5e308b82 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_node.h @@ -0,0 +1,72 @@ +/* xmlj_node.h - + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef XMLJ_NODE_H +#define XMLJ_NODE_H + +#include <jni.h> +#include <libxml/tree.h> + +/* -- Utility method definitions -- */ + +/* + * Returns the node for the given Java node instance + */ +xmlNodePtr xmljGetNodeID (JNIEnv *, jobject); + +/* + * Returns the Java node instance for the given node + */ +jobject xmljGetNodeInstance (JNIEnv *, xmlNodePtr); + +/* + * Frees the specified document pointer, + * releasing all its nodes from the cache. + */ +void xmljFreeDoc (JNIEnv *, xmlDocPtr); + +/* + * Match a node name + */ +int xmljMatch (const xmlChar *, xmlNodePtr); + +/* + * Match a node name and namespace + */ +int xmljMatchNS (const xmlChar *, const xmlChar *, xmlNodePtr); + +#endif /* !defined XMLJ_NODE_H */ diff --git a/libjava/classpath/native/jni/xmlj/xmlj_sax.c b/libjava/classpath/native/jni/xmlj/xmlj_sax.c new file mode 100644 index 00000000000..78991bdad73 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_sax.c @@ -0,0 +1,1445 @@ +/* xmlj_sax.c - + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "xmlj_sax.h" +#include "xmlj_io.h" +#include "xmlj_util.h" +#include <unistd.h> +#include <string.h> + +xmlExternalEntityLoader defaultLoader = NULL; + +void +xmljDispatchError (xmlParserCtxtPtr ctx, + xmlSAXLocatorPtr loc, + JNIEnv *env, + jobject target, + jmethodID method, + const char *msg, + va_list args); + +/* -- GnomeLocator -- */ + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_sax_GnomeLocator_publicId (JNIEnv * env, + jobject self + __attribute__((__unused__)), + jobject j_ctx, + jobject j_loc) +{ + xmlParserCtxtPtr ctx; + xmlSAXLocatorPtr loc; + SAXParseContext *sax; + + ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx); + loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc); + sax = (SAXParseContext *) ctx->_private; + + return sax->publicId; +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_sax_GnomeLocator_systemId (JNIEnv * env, + jobject self + __attribute__((__unused__)), + jobject j_ctx, + jobject j_loc) +{ + xmlParserCtxtPtr ctx; + xmlSAXLocatorPtr loc; + SAXParseContext *sax; + + ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx); + loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc); + sax = (SAXParseContext *) ctx->_private; + + return sax->systemId; +} + +JNIEXPORT jint JNICALL +Java_gnu_xml_libxmlj_sax_GnomeLocator_lineNumber (JNIEnv * env, + jobject self + __attribute__((__unused__)), + jobject j_ctx, + jobject j_loc) +{ + xmlParserCtxtPtr ctx; + xmlSAXLocatorPtr loc; + + ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx); + loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc); + if (ctx == NULL || ctx->input == NULL) + { + return -1; + } + return ctx->input->line; +} + +JNIEXPORT jint JNICALL +Java_gnu_xml_libxmlj_sax_GnomeLocator_columnNumber (JNIEnv * env, + jobject self + __attribute__((__unused__)), + jobject j_ctx, + jobject j_loc) +{ + xmlParserCtxtPtr ctx; + xmlSAXLocatorPtr loc; + + ctx = (xmlParserCtxtPtr) xmljAsPointer (env, j_ctx); + loc = (xmlSAXLocatorPtr) xmljAsPointer (env, j_loc); + if (ctx == NULL || ctx->input == NULL) + { + return -1; + } + return ctx->input->col; +} + +/* -- GnomeXMLReader -- */ + +/* + * Entry point for SAX parsing. + */ +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_sax_GnomeXMLReader_parseStream (JNIEnv * env, + jobject self, + jobject in, + jbyteArray detectBuffer, + jstring publicId, + jstring systemId, + jstring base, + jboolean validate, + jboolean contentHandler, + jboolean dtdHandler, + jboolean entityResolver, + jboolean errorHandler, + jboolean + declarationHandler, + jboolean lexicalHandler) +{ + xmljParseDocument (env, + self, + in, + detectBuffer, + publicId, + systemId, + base, + validate, + 0, + 0, + contentHandler, + dtdHandler, + entityResolver, + errorHandler, + declarationHandler, + lexicalHandler, + 0); +} + +xmlParserInputPtr +xmljExternalEntityLoader (const char *url, const char *id, + xmlParserCtxtPtr ctx) +{ + const xmlChar *systemId; + const xmlChar *publicId; + xmlParserInputPtr ret; + + systemId = xmlCharStrdup (url); + publicId = xmlCharStrdup (id); + /* TODO convert systemId to absolute URI */ + ret = xmljSAXResolveEntity (ctx, publicId, systemId); + if (ret == NULL) + { + ret = defaultLoader (url, id, ctx); + } + return ret; +} + +/* + * Allocates and configures a SAX handler that can report the various + * classes of callback. + */ +xmlSAXHandlerPtr +xmljNewSAXHandler (jboolean contentHandler, + jboolean dtdHandler, + jboolean entityResolver, + jboolean errorHandler, + jboolean declarationHandler, + jboolean lexicalHandler) +{ + xmlSAXHandlerPtr sax; + + sax = (xmlSAXHandlerPtr) malloc (sizeof (xmlSAXHandler)); + if (sax == NULL) + { + return NULL; + } + memset (sax, 0, sizeof (xmlSAXHandler)); + xmlSAXVersion (sax, 1); /* TODO SAX2 */ + + if (dtdHandler) + { + sax->internalSubset = &xmljSAXInternalSubset; + } + if (defaultLoader == NULL) + { + defaultLoader = xmlGetExternalEntityLoader (); + xmlSetExternalEntityLoader (xmljExternalEntityLoader); + } + if (entityResolver) + { + sax->resolveEntity = &xmljSAXResolveEntity; + } + + if (declarationHandler) + { + sax->entityDecl = &xmljSAXEntityDecl; + sax->notationDecl = &xmljSAXNotationDecl; + sax->attributeDecl = &xmljSAXAttributeDecl; + sax->elementDecl = &xmljSAXElementDecl; + sax->unparsedEntityDecl = &xmljSAXUnparsedEntityDecl; + } + + /* We always listen for the locator callback */ + sax->setDocumentLocator = &xmljSAXSetDocumentLocator; + if (contentHandler) + { + sax->startDocument = &xmljSAXStartDocument; + sax->endDocument = &xmljSAXEndDocument; + sax->startElement = &xmljSAXStartElement; + sax->endElement = &xmljSAXEndElement; + sax->characters = &xmljSAXCharacters; + sax->ignorableWhitespace = &xmljSAXIgnorableWhitespace; + sax->processingInstruction = &xmljSAXProcessingInstruction; + } + + /* We always intercept getEntity */ + /* TODO this should only be if lexicalHandler */ + sax->getEntity = &xmljSAXGetEntity; + if (lexicalHandler) + { + sax->getEntity = &xmljSAXGetEntity; + sax->reference = &xmljSAXReference; + sax->comment = &xmljSAXComment; + sax->cdataBlock = &xmljSAXCDataBlock; + } + else if (contentHandler) + { + sax->cdataBlock = &xmljSAXCharacters; + } + + if (errorHandler) + { + sax->warning = &xmljSAXWarning; + sax->error = &xmljSAXError; + sax->fatalError = &xmljSAXFatalError; + } + + return sax; +} + +/* -- Callback functions -- */ + +void +xmljSAXInternalSubset (void *vctx, + const xmlChar * name, + const xmlChar * publicId, const xmlChar * systemId) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_name; + jstring j_publicId; + jstring j_systemId; + + xmlSAX2InternalSubset (vctx, name, publicId, systemId); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->startDTD == NULL) + { + sax->startDTD = + xmljGetMethodID (env, + target, + "startDTD", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (sax->startDTD == NULL) + { + return; + } + } + + j_name = xmljNewString (env, name); + j_publicId = xmljNewString (env, publicId); + j_systemId = xmljNewString (env, systemId); + + (*env)->CallVoidMethod (env, + target, + sax->startDTD, + j_name, + j_publicId, + j_systemId); +} + +xmlParserInputPtr +xmljSAXResolveEntity (void *vctx, + const xmlChar * publicId, const xmlChar * systemId) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_publicId; + jstring j_systemId; + jobject inputStream; + + /* xmlSAX2ResolveEntity (vctx, publicId, systemId); */ + + ctx = (xmlParserCtxtPtr) vctx; + if (ctx->_private == NULL) + { + /* Not in Kansas */ + return NULL; + } + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + if ((*env)->ExceptionOccurred (env)) + { + return NULL; + } + + if (sax->resolveEntity == NULL) + { + sax->resolveEntity = + xmljGetMethodID (env, + target, + "resolveEntity", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/io/InputStream;"); + if (sax->resolveEntity == NULL) + { + return NULL; + } + } + + j_publicId = xmljNewString (env, publicId); + j_systemId = xmljNewString (env, systemId); + + inputStream = (*env)->CallObjectMethod (env, + target, + sax->resolveEntity, + j_publicId, + j_systemId, + sax->systemId); + + /* Return an xmlParserInputPtr corresponding to the input stream */ + if (inputStream != NULL) + { + jbyteArray detectBuffer; + jmethodID getDetectBuffer; + + /* Get the detect buffer from the NamedInputStream */ + getDetectBuffer = xmljGetMethodID (env, inputStream, "getDetectBuffer", + "()[B"); + if (getDetectBuffer == NULL) + { + return NULL; + } + detectBuffer = (*env)->CallObjectMethod (env, inputStream, + getDetectBuffer); + + return xmljNewParserInput (env, inputStream, detectBuffer, ctx); + } + else + { + return NULL; + } +} + +xmlEntityPtr +xmljSAXGetEntity (void *vctx __attribute__((__unused__)), const xmlChar * name) +{ + xmlEntityPtr ret; + + /* TODO */ + /* ret = xmlSAX2GetEntity (vctx, name); */ + ret = NULL; + return ret; +} + +void +xmljSAXEntityDecl (void *vctx, + const xmlChar * name, + int type, + const xmlChar * publicId, + const xmlChar * systemId, + xmlChar * content) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_name; + jstring j_publicId; + jstring j_systemId; + jstring j_value; + + xmlSAX2EntityDecl (vctx, name, type, publicId, systemId, content); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + j_name = xmljNewString (env, name); + switch (type) + { + case XML_INTERNAL_GENERAL_ENTITY: + case XML_INTERNAL_PARAMETER_ENTITY: + case XML_INTERNAL_PREDEFINED_ENTITY: + if (sax->internalEntityDecl == NULL) + { + sax->internalEntityDecl = + xmljGetMethodID (env, + target, + "internalEntityDecl", + "(Ljava/lang/String;Ljava/lang/String;)V"); + if (sax->internalEntityDecl == NULL) + { + return; + } + } + j_value = xmljNewString (env, content); + (*env)->CallVoidMethod (env, + target, + sax->internalEntityDecl, + j_name, + j_value); + break; + default: + if (sax->externalEntityDecl == NULL) + { + sax->externalEntityDecl = + xmljGetMethodID (env, + target, + "externalEntityDecl", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (sax->externalEntityDecl == NULL) + { + return; + } + } + j_publicId = xmljNewString (env, publicId); + j_systemId = xmljNewString (env, systemId); + (*env)->CallVoidMethod (env, + target, + sax->externalEntityDecl, + j_name, + j_publicId, + j_systemId); + } +} + +void +xmljSAXNotationDecl (void *vctx, + const xmlChar * name, + const xmlChar * publicId, + const xmlChar * systemId) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_name; + jstring j_publicId; + jstring j_systemId; + + xmlSAX2NotationDecl (vctx, name, publicId, systemId); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->notationDecl == NULL) + { + sax->notationDecl = + xmljGetMethodID (env, + target, + "notationDecl", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (sax->notationDecl == NULL) + { + return; + } + } + + j_name = xmljNewString (env, name); + j_publicId = xmljNewString (env, publicId); + j_systemId = xmljNewString (env, systemId); + + /* Invoke the method */ + (*env)->CallVoidMethod (env, + target, + sax->notationDecl, + j_name, + j_publicId, + j_systemId); +} + +void +xmljSAXAttributeDecl (void *vctx, + const xmlChar * elem, + const xmlChar * fullName, + int type, + int def, + const xmlChar * defaultValue, + xmlEnumerationPtr tree) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_eName; + jstring j_aName; + jstring j_type; + jstring j_mode; + jstring j_value; + + xmlSAX2AttributeDecl (vctx, elem, fullName, type, def, defaultValue, tree); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->attributeDecl == NULL) + { + sax->attributeDecl = + xmljGetMethodID (env, + target, + "attributeDecl", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (sax->attributeDecl == NULL) + { + return; + } + } + + j_eName = xmljNewString (env, elem); + j_aName = xmljNewString (env, fullName); + j_type = xmljAttributeTypeName (env, type); + j_mode = xmljAttributeModeName (env, def); + j_value = xmljNewString (env, defaultValue); + + (*env)->CallVoidMethod (env, + target, + sax->attributeDecl, + j_eName, + j_aName, + j_type, + j_mode, + j_value); +} + +void +xmljSAXElementDecl (void *vctx, + const xmlChar * name, + int type, + xmlElementContentPtr content) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_name; + jstring j_model; + + xmlSAX2ElementDecl (vctx, name, type, content); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->elementDecl == NULL) + { + sax->elementDecl = + xmljGetMethodID (env, + target, + "elementDecl", + "(Ljava/lang/String;Ljava/lang/String;)V"); + if (sax->elementDecl == NULL) + { + return; + } + } + + j_name = xmljNewString (env, name); + j_model = NULL; /* TODO */ + + (*env)->CallVoidMethod (env, + target, + sax->elementDecl, + j_name, + j_model); +} + +void +xmljSAXUnparsedEntityDecl (void *vctx, + const xmlChar * name, + const xmlChar * publicId, + const xmlChar * systemId, + const xmlChar * notationName) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_name; + jstring j_publicId; + jstring j_systemId; + jstring j_notationName; + + xmlSAX2UnparsedEntityDecl (vctx, name, publicId, systemId, notationName); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->unparsedEntityDecl == NULL) + { + sax->unparsedEntityDecl = + xmljGetMethodID (env, + target, + "unparsedEntityDecl", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (sax->unparsedEntityDecl == NULL) + { + return; + } + } + + j_name = xmljNewString (env, name); + j_publicId = xmljNewString (env, publicId); + j_systemId = xmljNewString (env, systemId); + j_notationName = xmljNewString (env, notationName); + + (*env)->CallVoidMethod (env, + target, + sax->unparsedEntityDecl, + j_name, + j_publicId, + j_systemId, + j_notationName); +} + +void +xmljSAXSetDocumentLocator (void *vctx, xmlSAXLocatorPtr loc) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + + xmlSAX2SetDocumentLocator (vctx, loc); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + if (target == NULL) + { + /* No Java parse context */ + return; + } + + /* Update locator on sax context */ + sax->loc = loc; + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->setDocumentLocator == NULL) + { + sax->setDocumentLocator = xmljGetMethodID (env, + target, + "setDocumentLocator", + "(Ljava/lang/Object;Ljava/lang/Object;)V"); + if (sax->setDocumentLocator == NULL) + { + return; + } + } + + (*env)->CallVoidMethod (env, + target, + sax->setDocumentLocator, + xmljAsField (env, ctx), + xmljAsField (env, loc)); +} + +void +xmljSAXStartDocument (void *vctx) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + + xmlSAX2StartDocument (vctx); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->startDocument == NULL) + { + sax->startDocument = xmljGetMethodID (env, + target, + "startDocument", + "(Z)V"); + if (sax->startDocument == NULL) + { + return; + } + } + + (*env)->CallVoidMethod (env, + target, + sax->startDocument, + ctx->standalone); +} + +void +xmljSAXEndDocument (void *vctx) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + + xmlSAX2EndDocument (vctx); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->endDocument == NULL) + { + sax->endDocument = xmljGetMethodID (env, + target, + "endDocument", + "()V"); + if (sax->endDocument == NULL) + { + return; + } + } + + (*env)->CallVoidMethod (env, + target, + sax->endDocument); +} + +void +xmljSAXStartElement (void *vctx, + const xmlChar * name, + const xmlChar ** attrs) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_name; + jobjectArray j_attrs; + jstring j_attr; + jsize len; + + xmlSAX2StartElement (vctx, name, attrs); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->startElement == NULL) + { + sax->startElement = + xmljGetMethodID (env, + target, + "startElement", + "(Ljava/lang/String;[Ljava/lang/String;)V"); + if (sax->startElement == NULL) + { + return; + } + } + + j_name = xmljNewString (env, name); + /* build attributes array */ + len = 0; + for (len = 0; attrs && attrs[len]; len++) + { + } + if (len) + { + if (sax->stringClass == NULL) + { + sax->stringClass = (*env)->FindClass (env, "java/lang/String"); + if (sax->stringClass == NULL) + { + fprintf (stderr, "Can't find java.lang.String class!\n"); + return; + } + } + j_attrs = (*env)->NewObjectArray (env, len, sax->stringClass, NULL); + if (j_attrs == NULL) + { + fprintf (stderr, "Can't allocate attributes array!\n"); + return; + } + len = 0; + for (len = 0; attrs && attrs[len]; len++) + { + j_attr = xmljNewString (env, attrs[len]); + (*env)->SetObjectArrayElement (env, j_attrs, len, j_attr); + } + + (*env)->CallVoidMethod (env, + target, + sax->startElement, + j_name, + j_attrs); + (*env)->DeleteLocalRef (env, j_attrs); + } + else + { + (*env)->CallVoidMethod (env, + target, + sax->startElement, + j_name, + NULL); + + } +} + +void +xmljSAXEndElement (void *vctx, + const xmlChar * name) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_name; + + xmlSAX2EndElement (vctx, name); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->endElement == NULL) + { + sax->endElement = xmljGetMethodID (env, + target, + "endElement", + "(Ljava/lang/String;)V"); + if (sax->endElement == NULL) + { + return; + } + } + + j_name = xmljNewString (env, name); + + (*env)->CallVoidMethod (env, + target, + sax->endElement, + j_name); +} + +void +xmljSAXReference (void *vctx, + const xmlChar * name) +{ + xmlSAX2Reference (vctx, name); +} + +void +xmljSAXCharacters (void *vctx, + const xmlChar * ch, + int len) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_ch; + xmlChar *dup; + + xmlSAX2Characters (vctx, ch, len); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->characters == NULL) + { + sax->characters = xmljGetMethodID (env, + target, + "characters", + "(Ljava/lang/String;)V"); + if (sax->characters == NULL) + { + return; + } + } + + dup = xmlStrndup (ch, len); + j_ch = xmljNewString (env, dup); + + (*env)->CallVoidMethod (env, + target, + sax->characters, + j_ch); + xmlFree (dup); +} + +void +xmljSAXIgnorableWhitespace (void *vctx, + const xmlChar * ch, + int len) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_ch; + xmlChar *dup; + + xmlSAX2IgnorableWhitespace (vctx, ch, len); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->ignorableWhitespace == NULL) + { + sax->ignorableWhitespace = xmljGetMethodID (env, + target, + "ignorableWhitespace", + "(Ljava/lang/String;)V"); + if (sax->ignorableWhitespace == NULL) + { + return; + } + } + + dup = xmlStrndup (ch, len); + j_ch = xmljNewString (env, dup); + + (*env)->CallVoidMethod (env, + target, + sax->ignorableWhitespace, + j_ch); + xmlFree (dup); +} + +void +xmljSAXProcessingInstruction (void *vctx, + const xmlChar * targ, + const xmlChar * data) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_targ; + jstring j_data; + + xmlSAX2ProcessingInstruction (vctx, targ, data); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->processingInstruction == NULL) + { + sax->processingInstruction = + xmljGetMethodID (env, + target, + "processingInstruction", + "(Ljava/lang/String;Ljava/lang/String;)V"); + if (sax->processingInstruction == NULL) + { + return; + } + } + + j_targ = xmljNewString (env, targ); + j_data = xmljNewString (env, data); + + (*env)->CallVoidMethod (env, + target, + sax->processingInstruction, + j_targ, + j_data); +} + +void +xmljSAXComment (void *vctx, + const xmlChar * value) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_text; + + xmlSAX2Comment (vctx, value); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->comment == NULL) + { + sax->comment = + xmljGetMethodID (env, + target, + "comment", + "(Ljava/lang/String;)V"); + if (sax->comment == NULL) + { + return; + } + } + + j_text = xmljNewString (env, value); + + (*env)->CallVoidMethod (env, + target, + sax->comment, + j_text); +} + +void +xmljSAXCDataBlock (void *vctx, + const xmlChar * ch, + int len) +{ + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + JNIEnv *env; + jobject target; + jstring j_ch; + xmlChar *dup; + + xmlSAX2CDataBlock (vctx, ch, len); + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + env = sax->env; + target = sax->obj; + + xmljCheckWellFormed (ctx); + if ((*env)->ExceptionOccurred (env)) + { + return; + } + + if (sax->cdataBlock == NULL) + { + sax->cdataBlock = + xmljGetMethodID (env, + target, + "cdataBlock", + "(Ljava/lang/String;)V"); + if (sax->cdataBlock == NULL) + { + return; + } + } + + dup = xmlStrndup (ch, len); + j_ch = xmljNewString (env, dup); + + (*env)->CallVoidMethod (env, + target, + sax->cdataBlock, + j_ch); + xmlFree (dup); +} + +void +xmljDispatchError (xmlParserCtxtPtr ctx, + xmlSAXLocatorPtr loc, + JNIEnv *env, + jobject target, + jmethodID method, + const char *msg, + va_list args) +{ + jint lineNumber; + jint columnNumber; + jstring publicId; + jstring systemId; + char buffer[2048] = ""; + + if (msg != NULL) + { + vsnprintf (buffer, sizeof buffer, msg, args); + } + lineNumber = loc->getLineNumber (ctx); + columnNumber = loc->getColumnNumber (ctx); + publicId = xmljNewString (env, loc->getPublicId (ctx)); + systemId = xmljNewString (env, loc->getSystemId (ctx)); + (*env)->CallVoidMethod (env, + target, + method, + (*env)->NewStringUTF (env, buffer), + lineNumber, + columnNumber, + publicId, + systemId); +} + +void +xmljSAXWarning (void *vctx, + const char *msg, + ...) +{ + va_list args; + + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + xmlSAXLocatorPtr loc; + JNIEnv *env; + jobject target; + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + loc = (xmlSAXLocatorPtr) sax->loc; + env = sax->env; + target = sax->obj; + + if ((*env)->ExceptionOccurred (env)) + { + return; + } + if (sax->warning == NULL) + { + sax->warning = + xmljGetMethodID (env, + target, + "warning", + "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V"); + if (sax->warning == NULL) + { + return; + } + } + + va_start (args, msg); + /* xmlParserWarning (vctx, msg, args); */ + xmljDispatchError (ctx, loc, env, target, sax->warning, msg, args); + va_end (args); +} + +void +xmljSAXError (void *vctx, + const char *msg, + ...) +{ + va_list args; + + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + xmlSAXLocatorPtr loc; + JNIEnv *env; + jobject target; + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + loc = (xmlSAXLocatorPtr) sax->loc; + env = sax->env; + target = sax->obj; + + if ((*env)->ExceptionOccurred (env)) + { + return; + } + if (sax->error == NULL) + { + sax->error = + xmljGetMethodID (env, + target, + "error", + "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V"); + if (sax->error == NULL) + { + return; + } + } + + va_start (args, msg); + /* xmlParserError (vctx, msg, args); */ + xmljDispatchError (ctx, loc, env, target, sax->error, msg, args); + va_end (args); +} + +void +xmljSAXFatalError (void *vctx, + const char *msg, + ...) +{ + va_list args; + + xmlParserCtxtPtr ctx; + SAXParseContext *sax; + xmlSAXLocatorPtr loc; + JNIEnv *env; + jobject target; + + ctx = (xmlParserCtxtPtr) vctx; + sax = (SAXParseContext *) ctx->_private; + loc = (xmlSAXLocatorPtr) sax->loc; + env = sax->env; + target = sax->obj; + + if ((*env)->ExceptionOccurred (env)) + { + return; + } + if (sax->fatalError == NULL) + { + sax->fatalError = + xmljGetMethodID (env, + target, + "fatalError", + "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V"); + if (sax->fatalError == NULL) + { + return; + } + } + + va_start (args, msg); + /* xmlParserError (vctx, msg, args); */ + xmljDispatchError (ctx, loc, env, target, sax->fatalError, msg, args); + va_end (args); +} + +void +xmljCheckWellFormed (xmlParserCtxtPtr ctx) +{ + if (!ctx->wellFormed) + { + xmljSAXFatalError (ctx, "document is not well-formed"); + } + if (ctx->validate && !ctx->valid) + { + xmljSAXFatalError (ctx, "document is not valid"); + } +} + +/* + * Convert a libxml2 attribute type to a string. + */ +jstring +xmljAttributeTypeName (JNIEnv * env, int type) +{ + const char *text; + + switch (type) + { + case XML_ATTRIBUTE_CDATA: + text = "CDATA"; + break; + case XML_ATTRIBUTE_ID: + text = "ID"; + break; + case XML_ATTRIBUTE_IDREF: + text = "IDREF"; + break; + case XML_ATTRIBUTE_IDREFS: + text = "IDREFS"; + break; + case XML_ATTRIBUTE_NMTOKEN: + text = "NMTOKEN"; + break; + case XML_ATTRIBUTE_NMTOKENS: + text = "NMTOKENS"; + break; + case XML_ATTRIBUTE_ENTITY: + text = "ID"; + break; + case XML_ATTRIBUTE_ENTITIES: + text = "ID"; + break; + default: + return NULL; + } + + return (*env)->NewStringUTF (env, text); +} + +/* + * Convert a libxml2 attribute default value type to a string. + */ +jstring +xmljAttributeModeName (JNIEnv * env, int type) +{ + const char *text; + + switch (type) + { + case XML_ATTRIBUTE_IMPLIED: + text = "#IMPLIED"; + break; + case XML_ATTRIBUTE_REQUIRED: + text = "#REQUIRED"; + break; + case XML_ATTRIBUTE_FIXED: + text = "#FIXED"; + break; + default: + return NULL; + } + + return (*env)->NewStringUTF (env, text); +} diff --git a/libjava/classpath/native/jni/xmlj/xmlj_sax.h b/libjava/classpath/native/jni/xmlj/xmlj_sax.h new file mode 100644 index 00000000000..249929ce02a --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_sax.h @@ -0,0 +1,160 @@ +/* xmlj_sax.h - + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef XMLJ_SAX_H +#define XMLJ_SAX_H + +#include "gnu_xml_libxmlj_sax_GnomeLocator.h" +#include "gnu_xml_libxmlj_sax_GnomeXMLReader.h" + +#include <libxml/SAX.h> +#include <libxml/parser.h> + +xmlSAXHandlerPtr +xmljNewSAXHandler (jboolean contentHandler, + jboolean dtdHandler, + jboolean entityResolver, + jboolean errorHandler, + jboolean declarationHandler, + jboolean lexicalHandler); + +xmlParserInputPtr +xmljExternalEntityLoader (const char *systemId, const char *publicId, + xmlParserCtxtPtr context); + +/* -- Function declarations for callback functions -- */ + +void xmljSAXInternalSubset(void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId); + +xmlParserInputPtr xmljSAXResolveEntity(void *ctx, + const xmlChar *publicId, + const xmlChar *systemId); + +xmlEntityPtr xmljSAXGetEntity(void *ctx, + const xmlChar *name); + +void xmljSAXEntityDecl(void *ctx, + const xmlChar *name, + int type, + const xmlChar *publicId, + const xmlChar *systemId, + xmlChar *content); + +void xmljSAXNotationDecl(void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId); + +void xmljSAXAttributeDecl(void *ctx, + const xmlChar *elem, + const xmlChar *fullName, + int type, + int def, + const xmlChar *defaultValue, + xmlEnumerationPtr tree); + +void xmljSAXElementDecl(void *ctx, + const xmlChar *name, + int type, + xmlElementContentPtr content); + +void xmljSAXUnparsedEntityDecl(void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId, + const xmlChar *notationName); + +void xmljSAXSetDocumentLocator(void *ctx, + xmlSAXLocatorPtr loc); + +void xmljSAXStartDocument(void *ctx); + +void xmljSAXEndDocument(void *ctx); + +void xmljSAXStartElement(void *ctx, + const xmlChar *name, + const xmlChar **atts); + +void xmljSAXEndElement(void *ctx, + const xmlChar *name); + +void xmljSAXReference(void *ctx, + const xmlChar *name); + +void xmljSAXCharacters(void *ctx, + const xmlChar *ch, + int len); + +void xmljSAXIgnorableWhitespace(void *ctx, + const xmlChar *ch, + int len); + +void xmljSAXProcessingInstruction(void *ctx, + const xmlChar *target, + const xmlChar *data); + +void xmljSAXComment(void *ctx, + const xmlChar *value); + +void xmljSAXCDataBlock(void *ctx, + const xmlChar *ch, + int len); + +void xmljSAXWarning(void *ctx, + const char *msg, + ...); + +void xmljSAXError(void *ctx, + const char *msg, + ...); + +void xmljSAXFatalError(void *ctx, + const char *msg, + ...); + +void xmljCheckWellFormed(xmlParserCtxtPtr ctx); + +jstring xmljAttributeTypeName (JNIEnv *env, + int type); + +jstring xmljAttributeModeName (JNIEnv *env, + int type); + +#endif /* !defined XMLJ_SAX_H */ diff --git a/libjava/classpath/native/jni/xmlj/xmlj_transform.c b/libjava/classpath/native/jni/xmlj/xmlj_transform.c new file mode 100644 index 00000000000..075409ad10a --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_transform.c @@ -0,0 +1,868 @@ +/* xmlj_transform.c - + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "gnu_xml_libxmlj_transform_GnomeTransformerFactory.h" +#include "gnu_xml_libxmlj_transform_GnomeTransformer.h" + +#include "xmlj_dom.h" +#include "xmlj_io.h" +#include "xmlj_error.h" +#include "xmlj_node.h" +#include "xmlj_sax.h" +#include "xmlj_util.h" + +#include <math.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <libxml/xmlmemory.h> +#include <libxml/debugXML.h> +#include <libxml/xmlIO.h> +#include <libxml/xinclude.h> +#include <libxml/parser.h> +#include <libxml/catalog.h> +#include <libxslt/keys.h> +#include <libxslt/xslt.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/transform.h> +#include <libxslt/xsltutils.h> +#include <libxslt/functions.h> +#include <libxslt/extensions.h> +#include <libxslt/documents.h> + +/* Local function prototypes */ + +void +xmljDocumentFunction (xmlXPathParserContextPtr ctxt, int nargs); + +xsltStylesheetPtr +xmljGetStylesheetID (JNIEnv * env, jobject transformer); + +jobject +xmljGetTransformerProperties (JNIEnv *env, jobject transformer); + +const xmlChar * +xmljBooleanToString (int value); + +void +xmljSetOutputProperties (JNIEnv *env, jobject transformer, + xsltStylesheetPtr stylesheet); + +jobjectArray +xmljGetParameterArray (JNIEnv *env, jobject transformer); + +const char ** +xmljGetParameters (JNIEnv *env, jobjectArray pa); + +void +xmljFreeParameters (JNIEnv *env, jobjectArray pa, const char **parameters); + +xmlDocPtr +xmljTransform (JNIEnv *env, jobject transformer, xmlDocPtr source); + +void +xmljTransformToSAX (JNIEnv *env, jobject transformer, xmlDocPtr source, + jobject callback); + +xmlDocPtr +xmljDocLoader (const xmlChar *uri, xmlDictPtr dict, int options, + void *ctxt, xsltLoadType type); + +/* HACK: store stylesheet URL as context for resolving URIs in xmljDocLoader */ +static jstring stylesheetURL = NULL; + +/* + * -------------------------------------------------------------------------- + * + * Native implementation for class + * gnu.xml.libxmlj.transform.GnomeTransformer follows. + */ + +static void +xmljSetProperty (JNIEnv * env, jobject outputProperties, + jmethodID setPropertyMethodID, const char *name, + const xmlChar * value) +{ + if (NULL != value) + { + jstring nameString = (*env)->NewStringUTF (env, name); + jstring valueString = (*env)->NewStringUTF (env, (const char *) value); + + jobject prevValue = (*env)->CallObjectMethod (env, outputProperties, + setPropertyMethodID, + nameString, valueString); + if (NULL != prevValue) + { + (*env)->DeleteLocalRef (env, prevValue); + } + + (*env)->DeleteLocalRef (env, nameString); + (*env)->DeleteLocalRef (env, valueString); + } +} + +typedef struct CdataSectionScannerInfo_ +{ + JNIEnv *env; + jobject stringBuffer; + jmethodID appendMethodID; + int isFirst; +} CdataSectionScannerInfo; + +static void +cdataSectionScanner (void *payload, void *data, xmlChar * name) +{ + CdataSectionScannerInfo *info = (CdataSectionScannerInfo *) data; + JNIEnv *env = info->env; + jstring nameString = (*env)->NewStringUTF (env, (const char *) name); + jstring blankString = (*env)->NewStringUTF (env, " "); + jobject stringBuffer; + if (!info->isFirst) + { + stringBuffer + = (*env)->CallObjectMethod (env, + info->stringBuffer, + info->appendMethodID, blankString); + (*env)->DeleteLocalRef (env, stringBuffer); + } + info->isFirst = 0; + stringBuffer + = (*env)->CallObjectMethod (env, + info->stringBuffer, + info->appendMethodID, nameString); + (*env)->DeleteLocalRef (env, stringBuffer); + (*env)->DeleteLocalRef (env, blankString); + (*env)->DeleteLocalRef (env, nameString); +} + +void +xmljDocumentFunction (xmlXPathParserContextPtr ctxt, int nargs) +{ + xmlXPathObjectPtr obj, obj2 = NULL; + + if ((nargs < 1) || (nargs > 2)) + { + xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL, + "document() : invalid number of args %d\n", nargs); + ctxt->error = XPATH_INVALID_ARITY; + return; + } + if (ctxt->value == NULL) + { + xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL, + "document() : invalid arg value\n"); + ctxt->error = XPATH_INVALID_TYPE; + return; + } + + if (nargs == 2) + { + if (ctxt->value->type != XPATH_NODESET) + { + xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL, + "document() : invalid arg expecting a nodeset\n"); + ctxt->error = XPATH_INVALID_TYPE; + return; + } + + obj2 = valuePop (ctxt); + } + + if (ctxt->value->type == XPATH_NODESET) + { + int i; + xmlXPathObjectPtr newobj, ret; + + obj = valuePop (ctxt); + ret = xmlXPathNewNodeSet (NULL); + + if (obj->nodesetval) + { + for (i = 0; i < obj->nodesetval->nodeNr; i++) + { + valuePush (ctxt, + xmlXPathNewNodeSet (obj->nodesetval->nodeTab[i])); + xmlXPathStringFunction (ctxt, 1); + if (nargs == 2) + { + valuePush (ctxt, xmlXPathObjectCopy (obj2)); + } + else + { + valuePush (ctxt, + xmlXPathNewNodeSet (obj->nodesetval-> + nodeTab[i])); + } + xsltDocumentFunction (ctxt, 2); + newobj = valuePop (ctxt); + ret->nodesetval = xmlXPathNodeSetMerge (ret->nodesetval, + newobj->nodesetval); + xmlXPathFreeObject (newobj); + } + } + + xmlXPathFreeObject (obj); + if (obj2 != NULL) + { + xmlXPathFreeObject (obj2); + } + valuePush (ctxt, ret); + return; + } + /* + * Make sure it's converted to a string + */ + xmlXPathStringFunction (ctxt, 1); + if (ctxt->value->type != XPATH_STRING) + { + xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL, + "document() : invalid arg expecting a string\n"); + ctxt->error = XPATH_INVALID_TYPE; + if (obj2 != NULL) + xmlXPathFreeObject (obj2); + return; + } + obj = valuePop (ctxt); + if (obj->stringval == NULL) + { + valuePush (ctxt, xmlXPathNewNodeSet (NULL)); + } + else + { + + xsltTransformContextPtr tctxt; + + tctxt = xsltXPathGetTransformContext (ctxt); + + { + SAXParseContext *saxContext = + (SAXParseContext *) tctxt->style->_private; + + xmlDocPtr tree = xmljResolveURIAndOpen (saxContext, + (const char*)obj->stringval, + NULL); + + xsltNewDocument (tctxt, tree); /* FIXME - free at a later point */ + + valuePush (ctxt, xmlXPathNewNodeSet ((xmlNodePtr) tree)); + } + } + xmlXPathFreeObject (obj); + if (obj2 != NULL) { + xmlXPathFreeObject (obj2); + } +} + +/* + * Returns the stylesheet pointer for the given GnomeTransformer. + */ +xsltStylesheetPtr +xmljGetStylesheetID (JNIEnv * env, jobject transformer) +{ + jclass cls; + jfieldID field; + jobject id; + xsltStylesheetPtr stylesheet; + + if (transformer == NULL) + { + xmljThrowException (env, "javax/xml/transform/TransformerException", + "Transformer is null"); + return NULL; + } + cls = (*env)->GetObjectClass (env, transformer); + if (cls == NULL) + { + return NULL; + } + field = (*env)->GetFieldID (env, cls, "stylesheet", "Ljava/lang/Object;"); + if (field == NULL) + { + return NULL; + } + id = (*env)->GetObjectField (env, transformer, field); + stylesheet = (xsltStylesheetPtr) xmljAsPointer (env, id); + if (stylesheet == NULL) + { + xmljThrowException (env, "javax/xml/transform/TransformerException", + "Stylesheet is null"); + return NULL; + } + return stylesheet; +} + +jobject +xmljGetTransformerProperties (JNIEnv *env, jobject transformer) +{ + jclass cls; + jfieldID field; + + cls = (*env)->GetObjectClass (env, transformer); + if (cls == NULL) + { + return NULL; + } + field = (*env)->GetFieldID (env, cls, "outputProperties", + "Ljava/util/Properties;"); + if (field == NULL) + { + return NULL; + } + return (*env)->GetObjectField (env, transformer, field); +} + +const xmlChar * +xmljBooleanToString (int value) +{ + return value ? BAD_CAST "yes" : BAD_CAST "no"; +} + +/* + * Sets the output properties for the given transformer, + * based on its stylesheet. + */ +void +xmljSetOutputProperties (JNIEnv *env, jobject transformer, + xsltStylesheetPtr stylesheet) +{ + jobject outputProperties; + jclass propertiesClass; + jmethodID setPropertyMethod; + + outputProperties = xmljGetTransformerProperties (env, transformer); + if (outputProperties == NULL) + { + return; + } + propertiesClass = (*env)->FindClass (env, "java/util/Properties"); + if (propertiesClass == NULL) + { + return; + } + setPropertyMethod = + (*env)->GetMethodID (env, propertiesClass, "setProperty", + "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); + if (setPropertyMethod == NULL) + { + return; + } + + xmljSetProperty (env, outputProperties, setPropertyMethod, + "encoding", stylesheet->encoding); + + xmljSetProperty (env, outputProperties, setPropertyMethod, + "media-type", stylesheet->mediaType); + + xmljSetProperty (env, outputProperties, setPropertyMethod, + "doctype-public", stylesheet->doctypePublic); + + xmljSetProperty (env, outputProperties, setPropertyMethod, + "doctype-system", stylesheet->doctypeSystem); + + xmljSetProperty (env, outputProperties, setPropertyMethod, + "indent", xmljBooleanToString (stylesheet->indent)); + + xmljSetProperty (env, outputProperties, setPropertyMethod, + "method", stylesheet->method); + + xmljSetProperty (env, outputProperties, setPropertyMethod, + "standalone", xmljBooleanToString (stylesheet->standalone)); + + xmljSetProperty (env, outputProperties, setPropertyMethod, + "version", stylesheet->version); + + xmljSetProperty (env, outputProperties, setPropertyMethod, + "omit-xml-declaration", + xmljBooleanToString (stylesheet->omitXmlDeclaration)); + + { + CdataSectionScannerInfo info; + jclass stringBufferClass + = + (*env)->FindClass (env, + "java/lang/StringBuffer"); + jmethodID stringBufferConstructorID = + (*env)->GetMethodID (env, stringBufferClass, + "<init>", "()V"); + jmethodID toStringMethodID = + (*env)->GetMethodID (env, stringBufferClass, + "toString", + "()Ljava/lang/String;"); + info.env = env; + info.isFirst = 1; + info.stringBuffer + = (*env)->AllocObject (env, stringBufferClass); + (*env)->CallVoidMethod (env, info.stringBuffer, + stringBufferConstructorID); + info.appendMethodID = + (*env)->GetMethodID (env, stringBufferClass, + "append", + "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); + + xmlHashScan (stylesheet->cdataSection, + cdataSectionScanner, &info); + + { + jstring result = (jstring) + (*env)->CallObjectMethod (env, + info.stringBuffer, + toStringMethodID); + + jstring nameString = + (*env)->NewStringUTF (env, + "cdata-section-elements"); + + jobject prevValue + = + (*env)->CallObjectMethod (env, + outputProperties, + setPropertyMethod, + nameString, result); + if (NULL != prevValue) + { + (*env)->DeleteLocalRef (env, prevValue); + } + (*env)->DeleteLocalRef (env, nameString); + } + + (*env)->DeleteLocalRef (env, info.stringBuffer); + } +} + +/* + * Returns the parameter array for the given GnomeTransformer. + */ +jobjectArray +xmljGetParameterArray (JNIEnv *env, jobject transformer) +{ + jclass cls; + jmethodID method; + + cls = (*env)->GetObjectClass (env, transformer); + if (cls == NULL) + { + return NULL; + } + method = (*env)->GetMethodID (env, cls, "getParameterArray", + "()[Ljava/lang/String;"); + if (method == NULL) + { + return NULL; + } + return (jobjectArray) (*env)->CallObjectMethod (env, transformer, method); +} + +/* Convert parameter array to xmlChar ** */ +const char ** +xmljGetParameters (JNIEnv *env, jobjectArray pa) +{ + int i, len; + const char **parameters; + + len = (*env)->GetArrayLength (env, pa); + parameters = (const char **) malloc ((len + 2) * sizeof (const char *)); + if (parameters == NULL) + { + return NULL; + } + + for (i = 0; i < len; i++) + { + jstring string = (jstring) (*env)->GetObjectArrayElement (env, pa, i); + + if (string != NULL) + { + parameters[i] = (*env)->GetStringUTFChars (env, string, NULL); + } + else + { + parameters[i] = NULL; + } + } + + parameters[len] = 0; + parameters[len + 1] = 0; + return parameters; +} + +/* Release parameter strings */ +void +xmljFreeParameters (JNIEnv *env, jobjectArray pa, const char **parameters) +{ + int i, len; + + len = (*env)->GetArrayLength (env, pa); + for (i = 0; i < len; i++) + { + jstring string = (jstring) (*env)->GetObjectArrayElement (env, pa, i); + if (string != NULL) + { + (*env)->ReleaseStringUTFChars (env, string, parameters[i]); + } + } + + free (parameters); +} + +xmlDocPtr +xmljTransform (JNIEnv *env, jobject transformer, xmlDocPtr source) +{ + xsltStylesheetPtr stylesheet; + xmlDocPtr result; + jobjectArray pa; + const char **parameters; + + stylesheet = xmljGetStylesheetID (env, transformer); + pa = xmljGetParameterArray (env, transformer); + parameters = xmljGetParameters (env, pa); + if (parameters == NULL) + { + xmljThrowException (env, "javax/xml/transform/TransformerException", + "Couldn't allocate memory for parameters"); + return NULL; + } + result = xsltApplyStylesheet (stylesheet, source, parameters); + xmljFreeParameters (env, pa, parameters); + if (result == NULL) + { + xmljThrowException (env, "javax/xml/transform/TransformerException", + "XSLT transformation failed"); + } + return result; +} + +void +xmljTransformToSAX (JNIEnv *env, jobject transformer, xmlDocPtr source, + jobject callback) +{ + xsltStylesheetPtr stylesheet; + int ret; + jobjectArray pa; + const char **parameters; + xmlSAXHandlerPtr sax; + + stylesheet = xmljGetStylesheetID (env, transformer); + pa = xmljGetParameterArray (env, transformer); + parameters = xmljGetParameters (env, pa); + if (parameters == NULL) + { + xmljThrowException (env, "javax/xml/transform/TransformerException", + "Couldn't allocate memory for parameters"); + return; + } + sax = NULL; /* TODO link up sax and callback */ + ret = xsltRunStylesheet (stylesheet, source, parameters, NULL, sax, NULL); + xmljFreeParameters (env, pa, parameters); + if (ret == -1) + { + xmljThrowException (env, "javax/xml/transform/TransformerException", + "XSLT transformation failed"); + } +} + +xmlDocPtr +xmljDocLoader (const xmlChar *uri, xmlDictPtr dict, int options, + void *ctxt, xsltLoadType type) +{ + JNIEnv *env; + jclass xmljClass; + jclass inputStreamClass; + jmethodID getInputStream; + jmethodID getDetectBuffer; + jstring systemId; + jobject inputStream; + jbyteArray detectBuffer; + + fflush(stdout); + env = xmljGetJNIEnv (); + if (!env) + { + return NULL; + } + xmljClass = (*env)->FindClass (env, "gnu/xml/libxmlj/util/XMLJ"); + if (!xmljClass) + { + return NULL; + } + getInputStream = + (*env)->GetStaticMethodID (env, xmljClass, "xmljGetInputStream", + "(Ljava/lang/String;Ljava/lang/String;)Lgnu/xml/libxmlj/util/NamedInputStream;"); + if (!getInputStream) + { + return NULL; + } + systemId = xmljNewString (env, uri); + inputStream = (*env)->CallStaticObjectMethod (env, xmljClass, getInputStream, + stylesheetURL, systemId); + if (!inputStream) + { + return NULL; + } + inputStreamClass = (*env)->GetObjectClass (env, inputStream); + if (!inputStreamClass) + { + return NULL; + } + getDetectBuffer = (*env)->GetMethodID (env, inputStreamClass, + "getDetectBuffer", "()[B"); + if (!getDetectBuffer) + { + return NULL; + } + detectBuffer = (*env)->CallObjectMethod (env, inputStream, getDetectBuffer); + if (!detectBuffer) + { + return NULL; + } + return xmljParseDocument (env, NULL, inputStream, detectBuffer, + NULL, systemId, stylesheetURL, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2); +} + +/* GnomeTransformer.newStylesheet */ +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_newStylesheet (JNIEnv *env, + jobject self) +{ + xsltStylesheetPtr stylesheet; + jobject ret; + + stylesheetURL = NULL; + xsltSetLoaderFunc (xmljDocLoader); + stylesheet = xsltNewStylesheet (); + xmljSetOutputProperties (env, self, stylesheet); + ret = xmljAsField (env, stylesheet); + if (ret == NULL) + { + xmljThrowException (env, + "javax/xml/transform/TransformerConfigurationException", + "Can't create Java object for stylesheet"); + } + return ret; +} + +/* GnomeTransformer.newStylesheetFromStream */ +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_newStylesheetFromStream +(JNIEnv *env, jobject self, jobject in, jbyteArray detectBuffer, + jstring publicId, jstring systemId, jstring base, + jboolean entityResolver, jboolean errorHandler) +{ + xmlDocPtr doc; + xsltStylesheetPtr stylesheet; + jobject ret; + + doc = xmljParseDocument (env, self, in, detectBuffer, publicId, systemId, + base, 0, 0, 0, 0, 0, + entityResolver, errorHandler, 0, 0, 2); + if (doc == NULL) + { + return NULL; + } + stylesheetURL = systemId; + xsltSetLoaderFunc (xmljDocLoader); + stylesheet = xsltParseStylesheetDoc (doc); + if (stylesheet == NULL) + { + xmljThrowException (env, + "javax/xml/transform/TransformerConfigurationException", + "Error parsing XSLT stylesheet"); + return NULL; + } + xmljSetOutputProperties (env, self, stylesheet); + ret = xmljAsField (env, stylesheet); + if (ret == NULL) + { + xmljThrowException (env, + "javax/xml/transform/TransformerConfigurationException", + "Can't create Java object for stylesheet"); + } + return ret; +} + +/* GnomeTransformer.newStylesheetFromDoc */ +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_newStylesheetFromDoc +(JNIEnv *env, jobject self, jobject in) +{ + xmlDocPtr doc; + xsltStylesheetPtr stylesheet; + jobject ret; + + doc = (xmlDocPtr) xmljGetNodeID (env, in); + if (doc == NULL) + { + return NULL; + } + stylesheetURL = xmljNewString (env, doc->URL); + xsltSetLoaderFunc (xmljDocLoader); + stylesheet = xsltParseStylesheetDoc (doc); + if (stylesheet == NULL) + { + xmljThrowException (env, + "javax/xml/transform/TransformerConfigurationException", + "Error parsing XSLT stylesheet"); + } + xmljSetOutputProperties (env, self, stylesheet); + ret = xmljAsField (env, stylesheet); + if (ret == NULL) + { + xmljThrowException (env, + "javax/xml/transform/TransformerConfigurationException", + "Can't create Java object for stylesheet"); + } + return ret; +} + +/* GnomeTransformer.transformStreamToStream */ +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformStreamToStream +(JNIEnv *env, jobject self, jobject in, jbyteArray detectBuffer, + jstring publicId, jstring systemId, jstring base, + jboolean entityResolver, jboolean errorHandler, jobject out) +{ + xmlDocPtr source; + xmlDocPtr result; + + source = xmljParseDocument (env, self, in, detectBuffer, publicId, systemId, + base, 0, 0, 0, 0, 0, + entityResolver, errorHandler, 0, 0, 2); + result = xmljTransform (env, self, source); + xmljSaveFileToJavaOutputStream (env, out, result, + (const char*) result->encoding); + xmlFreeDoc (result); +} + +/* GnomeTransformer.transformStreamToDoc */ +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformStreamToDoc +(JNIEnv *env, jobject self, jobject in, jbyteArray detectBuffer, + jstring publicId, jstring systemId, jstring base, + jboolean entityResolver, jboolean errorHandler) +{ + xmlDocPtr source; + xmlDocPtr result; + + source = xmljParseDocument (env, self, in, detectBuffer, publicId, systemId, + base, 0, 0, 0, 0, 0, + entityResolver, errorHandler, 0, 0, 2); + result = xmljTransform (env, self, source); + return xmljGetNodeInstance (env, (xmlNodePtr) result); +} + +/* GnomeTransformer.transformStreamToSAX */ +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformStreamToSAX +(JNIEnv *env, jobject self, jobject in, jbyteArray detectBuffer, + jstring publicId, jstring systemId, jstring base, + jboolean entityResolver, jboolean errorHandler, jobject callback) +{ + xmlDocPtr source; + + source = xmljParseDocument (env, self, in, detectBuffer, publicId, systemId, + base, 0, 0, 0, 0, 0, + entityResolver, errorHandler, 0, 0, 2); + xmljTransformToSAX (env, self, source, callback); +} + +/* GnomeTransformer.transformDocToStream */ +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformDocToStream +(JNIEnv *env, jobject self, jobject doc, jobject out) +{ + xmlDocPtr source; + xmlDocPtr result; + + source = (xmlDocPtr) xmljGetNodeID (env, doc); + result = xmljTransform (env, self, source); + xmljSaveFileToJavaOutputStream (env, out, result, + (const char*) result->encoding); + xmlFreeDoc (result); +} + +/* GnomeTransformer.transformDocToDoc */ +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformDocToDoc +(JNIEnv *env, jobject self, jobject doc) +{ + xmlDocPtr source; + xmlDocPtr result; + + source = (xmlDocPtr) xmljGetNodeID (env, doc); + result = xmljTransform (env, self, source); + return xmljGetNodeInstance (env, (xmlNodePtr) result); +} + +/* GnomeTransformer.transformDocToSAX */ +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_transformDocToSAX +(JNIEnv *env, jobject self, jobject doc, jobject callback) +{ + xmlDocPtr source; + + source = (xmlDocPtr) xmljGetNodeID (env, doc); + xmljTransformToSAX (env, self, source, callback); +} + +/* GnomeTransformer.free */ +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformer_free (JNIEnv *env, + jobject self) +{ + xsltStylesheetPtr stylesheet; + + stylesheet = xmljGetStylesheetID (env, self); + xsltFreeStylesheet (stylesheet); +} + +/* + * -------------------------------------------------------------------------- + * Native implementation for class + * gnu.xml.libxmlj.transform.GnomeTransformerFactory follows. + */ + +/* GnomeTransformerFactory.freeLibxsltGlobal */ +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_transform_GnomeTransformerFactory_freeLibxsltGlobal ( + JNIEnv *env __attribute__((__unused__)), + jclass clazz __attribute__((__unused__))) +{ + xsltCleanupGlobals (); + xmlCleanupParser (); +} + diff --git a/libjava/classpath/native/jni/xmlj/xmlj_util.c b/libjava/classpath/native/jni/xmlj/xmlj_util.c new file mode 100644 index 00000000000..498cb70923c --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_util.c @@ -0,0 +1,301 @@ +/* xmlj_util.c + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "xmlj_util.h" +#include "xmlj_error.h" +#include <libxml/tree.h> +#include <unistd.h> + +/* xmlChar->jstring cache */ +#ifdef XMLJ_STRING_CACHE +#define XMLJ_STRING_CACHE_SIZE 1024 +xmlHashTablePtr xmljStringCache = NULL; + +void +xmljHashDeallocate (void *data, xmlChar *name); + +void +xmljHashDeallocate (void *data, xmlChar *name) +{ + /* NOOP */ +} +#endif /* XMLJ_STRING_CACHE */ + +jstring +xmljNewString (JNIEnv * env, const xmlChar * text) +{ + jstring ret; + + if (text == NULL || (*env)->ExceptionOccurred (env)) + { + return NULL; + } +#ifdef XMLJ_STRING_CACHE + if (xmljStringCache == NULL) /* Init cache */ + { + xmljStringCache = xmlHashCreate (XMLJ_STRING_CACHE_SIZE); + } + ret = (jstring) xmlHashLookup (xmljStringCache, text); + if (ret == NULL) + { + ret = (*env)->NewStringUTF (env, (char *) text); + if (ret == NULL) /* Why? */ + { + fprintf(stderr, "xmljNewString: ERROR: NewStringUTF returned null for \"%s\"\n", text); + fflush (stderr); + } + else + { + xmlHashAddEntry (xmljStringCache, text, ret); + } + } +#else + ret = (*env)->NewStringUTF (env, (char *) text); + if (ret == NULL) /* Why? */ + { + printf("xmljNewString: ERROR: NewStringUTF returned null for \"%s\"\n", text); + } +#endif /* XMLJ_STRING_CACHE */ + return ret; +} + +void +xmljClearStringCache () +{ +#ifdef XMLJ_STRING_CACHE + if (xmljStringCache != NULL) + { + xmlHashFree (xmljStringCache, &xmljHashDeallocate); + } +#endif /* XMLJ_STRING_CACHE */ +} + +const xmlChar * +xmljGetStringChars (JNIEnv * env, jstring text) +{ + const char *s_text; + xmlChar *x_text; + + if (text == NULL) + { + return NULL; + } + + s_text = (*env)->GetStringUTFChars (env, text, 0); + x_text = (s_text == NULL) ? NULL : xmlCharStrdup (s_text); + if (s_text != NULL && x_text == NULL) + { + /* TODO raise exception */ + } + (*env)->ReleaseStringUTFChars (env, text, s_text); + return x_text; +} + +const xmlChar * +xmljGetPrefix (const xmlChar * qName) +{ + const xmlChar *localName; + const xmlChar *ret; + xmlChar **prefix; + + prefix = (xmlChar **) malloc (sizeof (xmlChar *)); + localName = xmlSplitQName2 (qName, prefix); + if (localName == NULL) + { + return NULL; + } + ret = *prefix; + free (prefix); + return ret; +} + +const xmlChar * +xmljGetLocalName (const xmlChar * qName) +{ + const xmlChar *localName; + xmlChar **prefix; + + prefix = (xmlChar **) malloc (sizeof (xmlChar *)); + localName = xmlSplitQName2 (qName, prefix); + if (localName == NULL) + { + return qName; + } + free (prefix); + return localName; +} + +jmethodID xmljGetMethodID (JNIEnv *env, + jobject target, + const char *name, + const char *signature) +{ + jclass cls; + jmethodID ret; + + cls = (*env)->GetObjectClass (env, target); + if (cls == NULL) + { + xmljThrowException (env, + "java/lang/ClassNotFoundException", + NULL); + return NULL; + } + ret = (*env)->GetMethodID (env, + cls, + name, + signature); + if (ret == NULL) + { + jclass clscls; + jmethodID nm; + jstring clsname; + const char *c_clsName; + char cat[512] = "[method signature too long]"; + + clscls = (*env)->FindClass (env, "java/lang/Class"); + if (clscls == NULL) + { + return NULL; + } + nm = (*env)->GetMethodID (env, clscls, "getName", + "()Ljava/lang/String;"); + if (nm == NULL) + { + return NULL; + } + clsname = (jstring) (*env)->CallObjectMethod (env, + (jobject)cls, + nm); + if (clsname == NULL) + { + return NULL; + } + c_clsName = (*env)->GetStringUTFChars (env, clsname, 0); + sprintf (cat, "%s.%s %s", c_clsName, name, signature); + xmljThrowException (env, + "java/lang/NoSuchMethodException", + cat); + (*env)->ReleaseStringUTFChars (env, clsname, c_clsName); + } + return ret; +} + +void * +xmljAsPointer (JNIEnv *env, jobject ptr) +{ + jclass cls; + jfieldID field; + +#if defined XMLJ_64BIT_POINTER + cls = (*env)->FindClass (env, "gnu/classpath/RawData64"); + field = (*env)->GetFieldID (env, cls, "data", "J"); + return (void *) (*env)->GetLongField (env, ptr, field); +#else + cls = (*env)->FindClass (env, "gnu/classpath/RawData32"); + field = (*env)->GetFieldID (env, cls, "data", "I"); + return (void *) (*env)->GetIntField (env, ptr, field); +#endif +} + +jobject +xmljAsField (JNIEnv *env, void * ptr) +{ + jclass cls; + jmethodID method; + +#if defined XMLJ_64BIT_POINTER + cls = (*env)->FindClass (env, "gnu/classpath/RawData64"); + method = (*env)->GetMethodID (env, cls, "<init>", "(J)V"); + return (*env)->NewObject (env, cls, method, (jlong) ptr); +#else + cls = (*env)->FindClass (env, "gnu/classpath/RawData32"); + method = (*env)->GetMethodID (env, cls, "<init>", "(I)V"); + return (*env)->NewObject (env, cls, method, (jint) ptr); +#endif +} + +JNIEnv * +xmljGetJNIEnv () +{ + JavaVM **jvms; + jsize *jvm_count; + JavaVM *jvm; + JNIEnv **envs; + JNIEnv *env; + + jvms = (JavaVM **) malloc (sizeof (JavaVM *)); + if (!jvms) + { + return NULL; + } + jvm_count = (jsize *) malloc (sizeof (jsize)); + if (!jvm_count) + { + free (jvms); + return NULL; + } + if (JNI_GetCreatedJavaVMs (jvms, 1, jvm_count)) + { + free (jvms); + free (jvm_count); + return NULL; + } + jvm = *jvms; + envs = (JNIEnv **) malloc (sizeof (JNIEnv *)); + if (!envs) + { + free (jvms); + free (jvm_count); + return NULL; + } + (*jvm)->AttachCurrentThread (jvm, (void **) envs, NULL); + (*jvm)->GetEnv (jvm, (void **) envs, JNI_VERSION_1_2); + if (envs) + { + env = *envs; + free (envs); + } + else + { + env = NULL; + } + free (jvms); + free (jvm_count); + return env; +} + diff --git a/libjava/classpath/native/jni/xmlj/xmlj_util.h b/libjava/classpath/native/jni/xmlj/xmlj_util.h new file mode 100644 index 00000000000..7bbe78b8e1f --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_util.h @@ -0,0 +1,69 @@ +/* xmlj_util.h - + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef XMLJ_UTIL_H +#define XMLJ_UTIL_H + +#if defined __64BIT__ || defined __LP64 || defined _LP64 || defined __LP64__ || defined _ADDR64 +# define XMLJ_64BIT_POINTER 1 +#endif + +#include <jni.h> +#include <libxml/xmlstring.h> + +jstring xmljNewString (JNIEnv *, const xmlChar *); + +void xmljClearStringCache (void); + +const xmlChar *xmljGetStringChars (JNIEnv *, jstring); + +const xmlChar *xmljGetPrefix (const xmlChar * qName); + +const xmlChar *xmljGetLocalName (const xmlChar * qName); + +jmethodID xmljGetMethodID (JNIEnv *env, + jobject target, + const char *name, + const char *signature); + +void * xmljAsPointer (JNIEnv *env, jobject field); + +jobject xmljAsField (JNIEnv *env, void * ptr); + +JNIEnv * xmljGetJNIEnv (void); + +#endif /* !defined XMLJ_UTIL_H */ diff --git a/libjava/classpath/native/jni/xmlj/xmlj_xpath.c b/libjava/classpath/native/jni/xmlj/xmlj_xpath.c new file mode 100644 index 00000000000..6d014cefc91 --- /dev/null +++ b/libjava/classpath/native/jni/xmlj/xmlj_xpath.c @@ -0,0 +1,625 @@ +/* xmlj_xpath.c - + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#include "gnu_xml_libxmlj_dom_GnomeDocument.h" +#include "gnu_xml_libxmlj_dom_GnomeElement.h" +#include "gnu_xml_libxmlj_dom_GnomeXPathExpression.h" +#include "gnu_xml_libxmlj_dom_GnomeXPathNodeList.h" +#include "gnu_xml_libxmlj_dom_GnomeXPathNSResolver.h" +#include "gnu_xml_libxmlj_dom_GnomeXPathResult.h" +#include "xmlj_node.h" +#include "xmlj_util.h" +#include <libxml/xpath.h> + +/* Local function prototypes */ + +xmlXPathContextPtr +xmljCreateXPathContextPtr (xmlNodePtr node); + +jobject +xmljGetXPathResult (JNIEnv *env, xmlXPathObjectPtr obj); + +jobject +xmljGetXPathNodeList (JNIEnv *env, xmlXPathObjectPtr obj); + +xmlXPathObjectPtr +xmljGetXPathObjectID (JNIEnv *env, jobject obj); + +/** + * Creates an XPath context for the given node. + */ +xmlXPathContextPtr +xmljCreateXPathContextPtr (xmlNodePtr node) +{ + xmlXPathContextPtr ctx; + + ctx = xmlXPathNewContext (node->doc); + ctx->node = node; + return ctx; +} + +/** + * Converts an xmlXPathObjectPtr to a Java XPathResult. + */ +jobject +xmljGetXPathResult (JNIEnv *env, xmlXPathObjectPtr obj) +{ + jclass cls; + jmethodID method; + jobject ret; + jobject val; + + if (obj == NULL) + { + return NULL; + } + cls = (*env)->FindClass (env, "gnu/xml/libxmlj/dom/GnomeXPathResult"); + if (cls == NULL) + { + return NULL; + } + method = (*env)->GetMethodID (env, cls, "<init>", "(Ljava/lang/Object;)V"); + if (method == NULL) + { + return NULL; + } + val = xmljAsField (env, obj); + ret = (*env)->NewObject (env, cls, method, val); + + return ret; +} + +/** + * Converts an xmlXPathObjectPtr to a Java XPathNodeList. + */ +jobject +xmljGetXPathNodeList (JNIEnv *env, xmlXPathObjectPtr obj) +{ + jclass cls; + jmethodID method; + jobject ret; + jobject val; + + if (obj == NULL) + { + return NULL; + } + cls = (*env)->FindClass (env, "gnu/xml/libxmlj/dom/GnomeXPathNodeList"); + if (cls == NULL) + { + return NULL; + } + method = (*env)->GetMethodID (env, cls, "<init>", "(Ljava/lang/Object;)V"); + if (method == NULL) + { + return NULL; + } + val = xmljAsField (env, obj); + ret = (*env)->NewObject (env, cls, method, val); + + return ret; +} + +xmlXPathObjectPtr +xmljGetXPathObjectID (JNIEnv *env, jobject obj) +{ + jclass cls; + jfieldID field; + jobject val; + xmlXPathObjectPtr ret; + + cls = (*env)->GetObjectClass (env, obj); + if (cls == NULL) + { + return NULL; + } + field = (*env)->GetFieldID (env, cls, "obj", "Ljava/lang/Object;"); + if (field == NULL) + { + return NULL; + } + val = (*env)->GetObjectField (env, obj, field); + ret = (xmlXPathObjectPtr) xmljAsPointer (env, val); + + return ret; +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_evaluate (JNIEnv *env, + jobject self + __attribute__((__unused__)), + jstring expression, + jobject contextNode, + jobject resolver, + jshort type, + jobject result) +{ + const xmlChar *str; + xmlNodePtr node; + xmlXPathContextPtr ctx; + xmlXPathObjectPtr eval = NULL; + + str = xmljGetStringChars (env, expression); + node = xmljGetNodeID (env, contextNode); + if (node == NULL) + { + return NULL; + } + ctx = xmljCreateXPathContextPtr (node); + if (ctx != NULL) + { + eval = xmlXPathEval (str, ctx); + xmlXPathFreeContext (ctx); + } + xmlFree ((xmlChar *) str); + return xmljGetXPathResult (env, eval); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathExpression_init (JNIEnv *env, + jobject self + __attribute__((__unused__)), + jstring expression) +{ + const xmlChar *str; + xmlXPathCompExprPtr ptr; + + str = xmljGetStringChars (env, expression); + ptr = xmlXPathCompile (str); + xmlFree ((xmlChar *) str); + return xmljAsField (env, ptr); +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathExpression_free (JNIEnv *env, + jobject self + __attribute__((__unused__)), + jobject ptr) +{ + xmlXPathCompExprPtr expr; + + expr = (xmlXPathCompExprPtr) xmljAsPointer (env, ptr); + xmlXPathFreeCompExpr (expr); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathExpression_doEvaluate (JNIEnv *env, + jobject self + __attribute__((__unused__)), + jobject ptr, + jobject contextNode, + jshort type, + jobject result) +{ + xmlXPathCompExprPtr expr; + xmlNodePtr node; + xmlXPathContextPtr ctx; + xmlXPathObjectPtr eval = NULL; + + expr = (xmlXPathCompExprPtr) xmljAsPointer (env, ptr); + node = xmljGetNodeID (env, contextNode); + if (node == NULL) + { + return NULL; + } + ctx = xmljCreateXPathContextPtr (node); + if (ctx != NULL) + { + eval = xmlXPathCompiledEval (expr, ctx); + xmlXPathFreeContext (ctx); + } + return xmljGetXPathResult (env, eval); +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_free (JNIEnv *env, + jobject self + __attribute__((__unused__)), + jobject obj) +{ + xmlXPathFreeObject ((xmlXPathObjectPtr) xmljAsPointer (env, obj)); +} + +JNIEXPORT jshort JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getResultType (JNIEnv *env, + jobject self) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + switch (obj->type) + { + case XPATH_UNDEFINED: + return 0; /* ANY_TYPE */ + case XPATH_NUMBER: + return 1; /* NUMBER_TYPE */ + case XPATH_STRING: + return 2; /* STRING_TYPE */ + case XPATH_BOOLEAN: + return 3; /* BOOLEAN_TYPE */ + case XPATH_NODESET: + return 6; /* UNORDERED_NODE_SNAPSHOT_TYPE */ + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + case XPATH_USERS: + case XPATH_XSLT_TREE: + /* TODO */ + default: + return -1; /* TODO */ + } +} + +JNIEXPORT jdouble JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getNumberValue (JNIEnv *env, + jobject self) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + if (obj == NULL) + { + return 0.0; + } + return obj->floatval; +} + +JNIEXPORT jstring JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getStringValue (JNIEnv *env, + jobject self) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + if (obj == NULL) + { + return NULL; + } + return xmljNewString (env, obj->stringval); +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getBooleanValue (JNIEnv *env, + jobject self) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + return obj->boolval; +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getSingleNodeValue (JNIEnv *env, + jobject self) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + if (obj == NULL) + { + return NULL; + } + if (obj->nodesetval == NULL) + { + return NULL; + } + if (obj->nodesetval->nodeNr > 0) + { + return xmljGetNodeInstance (env, obj->nodesetval->nodeTab[0]); + } + else + { + return NULL; + } +} + +JNIEXPORT jboolean JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getInvalidIteratorState (JNIEnv *env, + jobject self) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + return 0; /* TODO */ +} + +JNIEXPORT jint JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_getSnapshotLength (JNIEnv *env, + jobject self) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + if (obj == NULL) + { + return -1; + } + if (obj->nodesetval == NULL) + { + return -1; + } + return obj->nodesetval->nodeNr; +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_iterateNext (JNIEnv *env, + jobject self) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + return NULL; /* TODO */ +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathResult_snapshotItem (JNIEnv *env, + jobject self, + jint index) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + if (obj == NULL) + { + return NULL; + } + if (obj->nodesetval == NULL) + { + return NULL; + } + if (obj->nodesetval->nodeNr > 0) + { + return xmljGetNodeInstance (env, obj->nodesetval->nodeTab[index]); + } + else + { + return NULL; + } +} + +/* -- GnomeXPathNodeList -- */ + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_getElementsByTagName (JNIEnv *env, + jobject self, + jstring name) +{ + return Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagName (env, + self, + name); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagName (JNIEnv *env, + jobject self, + jstring name) +{ + const xmlChar *s_name; + const xmlChar *format; + xmlChar expr[256]; + xmlNodePtr node; + xmlXPathContextPtr ctx; + xmlXPathObjectPtr eval = NULL; + + node = xmljGetNodeID (env, self); + if (node == NULL) + { + return NULL; + } + s_name = xmljGetStringChars (env, name); + if (xmlStrEqual (s_name, BAD_CAST "*")) + { + format = xmlCharStrdup ("descendant-or-self::*[node-type()=1]"); + if (xmlStrPrintf (expr, 256, format) == -1) + { + return NULL; + } + } + else + { + format = xmlCharStrdup ("descendant-or-self::*[name()='%s']"); + if (xmlStrPrintf (expr, 256, format, s_name) == -1) + { + return NULL; + } + } + xmlFree ((xmlChar *) s_name); + ctx = xmljCreateXPathContextPtr (node); + if (ctx != NULL) + { + eval = xmlXPathEval (expr, ctx); + xmlXPathFreeContext (ctx); + } + return xmljGetXPathNodeList (env, eval); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeDocument_getElementsByTagNameNS (JNIEnv *env, + jobject self, + jstring uri, + jstring localName) +{ + return Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagNameNS (env, + self, + uri, + localName); +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeElement_getElementsByTagNameNS (JNIEnv *env, + jobject self, + jstring uri, + jstring localName) +{ + const xmlChar *s_uri; + const xmlChar *s_localName; + const xmlChar *format; + xmlChar expr[256]; + xmlNodePtr node; + xmlXPathContextPtr ctx; + xmlXPathObjectPtr eval = NULL; + + node = xmljGetNodeID (env, self); + if (node == NULL) + { + return NULL; + } + s_uri = xmljGetStringChars (env, uri); + s_localName = xmljGetStringChars (env, localName); + if (uri == NULL) + { + /* namespace URI is empty */ + if (xmlStrEqual (s_localName, BAD_CAST "*")) + { + format = xmlCharStrdup ("descendant-or-self::*[namespace-uri()='' and node-type()=1]"); + if (xmlStrPrintf (expr, 256, format) == -1) + { + return NULL; + } + } + else + { + format = xmlCharStrdup ("descendant-or-self::*[namespace-uri()='' and local-name()='%s']"); + if (xmlStrPrintf (expr, 256, format, s_localName) == -1) + { + return NULL; + } + } + } + else if (xmlStrEqual (s_uri, BAD_CAST "*")) + { + /* matches all namespaces */ + if (xmlStrEqual (s_localName, BAD_CAST "*")) + { + format = xmlCharStrdup ("descendant-or-self::*[node-type()=1]"); + if (xmlStrPrintf (expr, 256, format) == -1) + { + return NULL; + } + } + else + { + format = xmlCharStrdup ("descendant-or-self::*[local-name()='%s']"); + if (xmlStrPrintf (expr, 256, format, s_localName) == -1) + { + return NULL; + } + } + } + else + { + if (xmlStrEqual (s_localName, BAD_CAST "*")) + { + format = xmlCharStrdup ("descendant-or-self::*[namespace-uri()='%s' and node-type()=1]"); + if (xmlStrPrintf (expr, 256, format, s_uri) == -1) + { + return NULL; + } + } + else + { + format = xmlCharStrdup ("descendant-or-self::*[namespace-uri()='%s' and local-name()='%s']"); + if (xmlStrPrintf (expr, 256, format, s_uri, s_localName) == -1) + { + return NULL; + } + } + } + xmlFree ((xmlChar *) s_uri); + xmlFree ((xmlChar *) s_localName); + ctx = xmljCreateXPathContextPtr (node); + if (ctx != NULL) + { + eval = xmlXPathEval (expr, ctx); + xmlXPathFreeContext (ctx); + } + return xmljGetXPathNodeList (env, eval); +} + +JNIEXPORT void JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathNodeList_free (JNIEnv *env, + jobject self + __attribute__((__unused__)), + jobject obj) +{ + xmlXPathFreeObject ((xmlXPathObjectPtr) xmljAsPointer (env, obj)); +} + +JNIEXPORT jint JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathNodeList_getLength (JNIEnv *env, + jobject self) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + if (obj == NULL) + { + return 0; + } + if (obj->nodesetval == NULL) + { + return 0; + } + return obj->nodesetval->nodeNr; +} + +JNIEXPORT jobject JNICALL +Java_gnu_xml_libxmlj_dom_GnomeXPathNodeList_item (JNIEnv *env, + jobject self, + jint index) +{ + xmlXPathObjectPtr obj; + + obj = xmljGetXPathObjectID (env, self); + if (obj == NULL) + { + return NULL; + } + if (obj->nodesetval == NULL) + { + return NULL; + } + if (obj->nodesetval->nodeNr > 0) + { + return xmljGetNodeInstance (env, obj->nodesetval->nodeTab[index]); + } + else + { + return NULL; + } +} + diff --git a/libjava/classpath/native/target/.cvsignore b/libjava/classpath/native/target/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/target/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/target/Linux/.cvsignore b/libjava/classpath/native/target/Linux/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/target/Linux/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/target/Linux/Makefile.am b/libjava/classpath/native/target/Linux/Makefile.am new file mode 100644 index 00000000000..bd267dc7f91 --- /dev/null +++ b/libjava/classpath/native/target/Linux/Makefile.am @@ -0,0 +1,10 @@ +## Input file for automake to generate the Makefile.in used by configure + +EXTRA_DIST = \ +target_native_io.h \ +target_native_misc.h \ +target_native.h \ +target_native_math_float.h \ +target_native_network.h \ +target_native_file.h \ +target_native_math_int.h diff --git a/libjava/classpath/native/target/Linux/target_native.h b/libjava/classpath/native/target/Linux/target_native.h new file mode 100644 index 00000000000..4e1d5136d55 --- /dev/null +++ b/libjava/classpath/native/target/Linux/target_native.h @@ -0,0 +1,79 @@ +/* ???.h - ??? + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: Linux target global defintions +Systems : all +*/ + +#ifndef __TARGET_NATIVE__ +#define __TARGET_NATIVE__ + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/* include rest of definitions from generic file (do not move it to + another position!) */ +#include "target_generic.h" + +#endif /* __TARGET_NATIVE__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/Linux/target_native_file.h b/libjava/classpath/native/target/Linux/target_native_file.h new file mode 100644 index 00000000000..0c40b4471b6 --- /dev/null +++ b/libjava/classpath/native/target/Linux/target_native_file.h @@ -0,0 +1,79 @@ +/* ???.h - ??? + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: Linux target defintions of file functions +Systems : all +*/ + +#ifndef __TARGET_NATIVE_FILE__ +#define __TARGET_NATIVE_FILE__ + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/* include rest of definitions from generic file (do not move it to + another position!) */ +#include "target_generic_file.h" + +#endif /* __TARGET_NATIVE_FILE__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/Linux/target_native_io.h b/libjava/classpath/native/target/Linux/target_native_io.h new file mode 100644 index 00000000000..03f43adf579 --- /dev/null +++ b/libjava/classpath/native/target/Linux/target_native_io.h @@ -0,0 +1,78 @@ +/* ???.h - ??? + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: Linux target defintions of miscellaneous functions +Systems : all +*/ + +#ifndef __TARGET_NATIVE_IO__ +#define __TARGET_NATIVE_IO__ + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/* include rest of definitions from generic file (do not move it to + another position!) */ +#include "target_generic_io.h" + +#endif /* __TARGET_NATIVE_MISC__ */ + +/* end of file */ diff --git a/libjava/classpath/native/target/Linux/target_native_math_float.h b/libjava/classpath/native/target/Linux/target_native_math_float.h new file mode 100644 index 00000000000..0f3455d2ae9 --- /dev/null +++ b/libjava/classpath/native/target/Linux/target_native_math_float.h @@ -0,0 +1,80 @@ +/* ???.h - ??? + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: Linux target defintions of float/double constants/ + macros/functions +Systems : all +*/ + +#ifndef __TARGET_NATIVE_MATH_FLOAT__ +#define __TARGET_NATIVE_MATH_FLOAT__ + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/* include rest of definitions from generic file (do not move it to + another position!) */ +#include "target_generic_math_float.h" + +#endif /* __TARGET_NATIVE_MATH_FLOAT__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/Linux/target_native_math_int.h b/libjava/classpath/native/target/Linux/target_native_math_int.h new file mode 100644 index 00000000000..4c5fc671d05 --- /dev/null +++ b/libjava/classpath/native/target/Linux/target_native_math_int.h @@ -0,0 +1,80 @@ +/* ???.h - ??? + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: Linux target defintions of int/int64 constants/ + macros/functions +Systems : all +*/ + +#ifndef __TARGET_NATIVE_MATH_INT__ +#define __TARGET_NATIVE_MATH_INT__ + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/* include rest of definitions from generic file (do not move it to + another position!) */ +#include "target_generic_math_int.h" + +#endif /* __TARGET_NATIVE_MATH_INT__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/Linux/target_native_misc.h b/libjava/classpath/native/target/Linux/target_native_misc.h new file mode 100644 index 00000000000..00bc7ac8da8 --- /dev/null +++ b/libjava/classpath/native/target/Linux/target_native_misc.h @@ -0,0 +1,79 @@ +/* ???.h - ??? + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: Linux target defintions of miscellaneous functions +Systems : all +*/ + +#ifndef __TARGET_NATIVE_MISC__ +#define __TARGET_NATIVE_MISC__ + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/* include rest of definitions from generic file (do not move it to + another position!) */ +#include "target_generic_misc.h" + +#endif /* __TARGET_NATIVE_MISC__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/Linux/target_native_network.h b/libjava/classpath/native/target/Linux/target_native_network.h new file mode 100644 index 00000000000..23f9d0a6286 --- /dev/null +++ b/libjava/classpath/native/target/Linux/target_native_network.h @@ -0,0 +1,79 @@ +/* ???.h - ??? + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: Linux target defintions of network functions +Systems : all +*/ + +#ifndef __TARGET_NATIVE_NETWORK__ +#define __TARGET_NATIVE_NETWORK__ + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include <config.h> + +#include <stdlib.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/* include rest of definitions from generic file (do not move it to + another position!) */ +#include "target_generic_network.h" + +#endif /* __TARGET_NATIVE_NETWORK__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/Makefile.am b/libjava/classpath/native/target/Makefile.am new file mode 100644 index 00000000000..ba0ad791919 --- /dev/null +++ b/libjava/classpath/native/target/Makefile.am @@ -0,0 +1,5 @@ +## Input file for automake to generate the Makefile.in used by configure + +SUBDIRS = Linux generic + +EXTRA_DIST = readme.txt diff --git a/libjava/classpath/native/target/generic/.cvsignore b/libjava/classpath/native/target/generic/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/target/generic/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/target/generic/Makefile.am b/libjava/classpath/native/target/generic/Makefile.am new file mode 100644 index 00000000000..bc8413c3a75 --- /dev/null +++ b/libjava/classpath/native/target/generic/Makefile.am @@ -0,0 +1,10 @@ +## Input file for automake to generate the Makefile.in used by configure + +EXTRA_DIST = \ +target_generic_io.h \ +target_generic_misc.h \ +target_generic.h \ +target_generic_math_float.h \ +target_generic_network.h \ +target_generic_file.h \ +target_generic_math_int.h diff --git a/libjava/classpath/native/target/generic/target_generic.h b/libjava/classpath/native/target/generic/target_generic.h new file mode 100644 index 00000000000..e4ddf5c3bfa --- /dev/null +++ b/libjava/classpath/native/target/generic/target_generic.h @@ -0,0 +1,171 @@ +/* generic_math_int64.h - Native methods for 64bit math operations + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: generic target global defintions +Systems : all +*/ + +#ifndef __TARGET_GENERIC__ +#define __TARGET_GENERIC__ + +/* check if target_native_network.h included */ +#ifndef __TARGET_NATIVE__ + #error Do NOT INCLUDE generic target files! Include the corresponding native target files instead! +#endif + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include "config.h" + +#include <stdlib.h> +#include <errno.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ +#define TARGET_NATIVE_OK 1 +#define TARGET_NATIVE_ERROR 0 + +#ifndef TARGET_NATIVE_ERROR_PERMISION_DENIED + #define TARGET_NATIVE_ERROR_PERMISION_DENIED EACCES +#endif +#ifndef TARGET_NATIVE_ERROR_BAD_FILE_DESCRIPTOR + #define TARGET_NATIVE_ERROR_BAD_FILE_DESCRIPTOR EBADF +#endif +#ifndef TARGET_NATIVE_ERROR_FILE_EXISTS + #define TARGET_NATIVE_ERROR_FILE_EXISTS EEXIST +#endif +#ifndef TARGET_NATIVE_ERROR_INPUT_OUTPUT + #define TARGET_NATIVE_ERROR_INPUT_OUTPUT EIO +#endif +#ifndef TARGET_NATIVE_ERROR_TOO_MANY_OPEN_FILES + #define TARGET_NATIVE_ERROR_TOO_MANY_OPEN_FILES EMFILE +#endif +#ifndef TARGET_NATIVE_ERROR_FILENAME_TO_LONG + #define TARGET_NATIVE_ERROR_FILENAME_TO_LONG ENAMETOOLONG +#endif +#ifndef TARGET_NATIVE_ERROR_NO_SUCH_DEVICE + #define TARGET_NATIVE_ERROR_NO_SUCH_DEVICE ENODEV +#endif +#ifndef TARGET_NATIVE_ERROR_NO_SUCH_FILE + #define TARGET_NATIVE_ERROR_NO_SUCH_FILE ENOENT +#endif +#ifndef TARGET_NATIVE_ERROR_NO_SPACE_LEFT + #define TARGET_NATIVE_ERROR_NO_SPACE_LEFT ENOSPC +#endif +#ifndef TARGET_NATIVE_ERROR_DIRECTORY_NOT_EMPTY + #define TARGET_NATIVE_ERROR_DIRECTORY_NOT_EMPTY ENOTEMPTY +#endif +#ifndef TARGET_NATIVE_ERROR_OPERATION_NOT_PERMITTED + #define TARGET_NATIVE_ERROR_OPERATION_NOT_PERMITTED EPERM +#endif +#ifndef TARGET_NATIVE_ERROR_READ_ONLY_FILE_SYSTEM + #define TARGET_NATIVE_ERROR_READ_ONLY_FILE_SYSTEM EROFS +#endif +#ifndef TARGET_NATIVE_ERROR_INVALID_SEEK + #define TARGET_NATIVE_ERROR_INVALID_SEEK ESPIPE +#endif +#ifndef TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL + #define TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL EINTR +#endif + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***********************************************************************\ +* Name : TARGET_NATIVE_LAST_ERROR +* Purpose : return last error code +* Input : - +* Output : - +* Return : error code +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_LAST_ERROR + #include <errno.h> + #define TARGET_NATIVE_LAST_ERROR() \ + errno +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_LAST_ERROR_STRING +* Purpose : return last error string +* Input : - +* Output : - +* Return : error string (read only!) +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_LAST_ERROR_STRING + #include <string.h> + #include <errno.h> + #define TARGET_NATIVE_LAST_ERROR_STRING() \ + strerror(errno) +#endif + +#ifndef TARGET_NATIVE_LAST_ERROR_STRING_FORMAT + #include <string.h> + #include <errno.h> + #define TARGET_NATIVE_LAST_ERROR_STRING_FORMAT(buffer,bufferSize,format) \ + do { \ + sprintf(buffer,format); \ + strcat(" (error: "); \ + strcat(strerror(errno)); \ + strcat(")"); \ + } while (0) +#endif + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TARGET_GENERIC__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/generic/target_generic_file.h b/libjava/classpath/native/target/generic/target_generic_file.h new file mode 100644 index 00000000000..cd90e733ced --- /dev/null +++ b/libjava/classpath/native/target/generic/target_generic_file.h @@ -0,0 +1,844 @@ +/* target_generic_file - Native methods for file operations + Copyright (C) 1998, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: generic target defintions of file functions +Systems : all +*/ + +#ifndef __TARGET_GENERIC_FILE__ +#define __TARGET_GENERIC_FILE__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* check if target_native_file.h included */ +#ifndef __TARGET_NATIVE_FILE__ + #error Do NOT INCLUDE generic target files! Include the corresponding native target files instead! +#endif + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include "config.h" + +#include <stdlib.h> +#include <assert.h> +#include <fcntl.h> + +#include "target_native.h" +#include "target_native_math_int.h" + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ +#ifndef TARGET_NATIVE_FILE_FILEFLAG_NONE + #define TARGET_NATIVE_FILE_FILEFLAG_NONE 0 +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_CREATE + #define TARGET_NATIVE_FILE_FILEFLAG_CREATE O_CREAT +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_CREATE_FORCE + #define TARGET_NATIVE_FILE_FILEFLAG_CREATE_FORCE (O_CREAT|O_EXCL) +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_READ + #define TARGET_NATIVE_FILE_FILEFLAG_READ O_RDONLY +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_WRITE + #define TARGET_NATIVE_FILE_FILEFLAG_WRITE O_WRONLY +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_READWRITE + #define TARGET_NATIVE_FILE_FILEFLAG_READWRITE O_RDWR +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_TRUNCATE + #define TARGET_NATIVE_FILE_FILEFLAG_TRUNCATE O_TRUNC +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_APPEND + #define TARGET_NATIVE_FILE_FILEFLAG_APPEND O_APPEND +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_SYNC + #if !defined (O_SYNC) && defined (O_FSYNC) + #define TARGET_NATIVE_FILE_FILEFLAG_SYNC O_FSYNC + #else + #define TARGET_NATIVE_FILE_FILEFLAG_SYNC O_SYNC + #endif +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_DSYNC + #ifdef O_DSYNC + #define TARGET_NATIVE_FILE_FILEFLAG_DSYNC 0 + #else + #define TARGET_NATIVE_FILE_FILEFLAG_DSYNC TARGET_NATIVE_FILE_FILEFLAG_SYNC + #endif +#endif +#ifndef TARGET_NATIVE_FILE_FILEFLAG_BINARY + #define TARGET_NATIVE_FILE_FILEFLAG_BINARY O_BINARY +#endif + +#ifndef TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL + #define TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) +#endif + +#ifndef TARGET_NATIVE_FILE_FILEPERMISSION_PRIVATE + #define TARGET_NATIVE_FILE_FILEPERMISSION_PRIVATE (S_IRUSR | S_IWUSR) +#endif + +#ifndef TARGET_NATIVE_FILE_FILEPERMISSION_READONLY + #define TARGET_NATIVE_FILE_FILEPERMISSION_READONLY (~(S_IWRITE|S_IWGRP|S_IWOTH)) +#endif + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_OPEN +* Purpose : open a file +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : file is created if it does not exist +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_OPEN + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + #define TARGET_NATIVE_FILE_OPEN(filename,filedescriptor,flags,permissions,result) \ + do { \ + filedescriptor=open(filename, \ + flags, \ + permissions \ + ); \ + if (filedescriptor >= 0) \ + fcntl (filedescriptor,F_SETFD,FD_CLOEXEC); \ + result=(filedescriptor>=0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_OPEN_CREATE +* Purpose : create a file +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : file is created if it does not exist +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_OPEN_CREATE + #define TARGET_NATIVE_FILE_OPEN_CREATE(filename,filedescriptor,result) \ + TARGET_NATIVE_FILE_OPEN(filename,\ + filedescriptor,\ + TARGET_NATIVE_FILE_FILEFLAG_CREATE_FORCE, \ + TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL, \ + result \ + ) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_OPEN_READ +* Purpose : open an existing file for reading +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_OPEN_READ + #define TARGET_NATIVE_FILE_OPEN_READ(filename,filedescriptor,result) \ + TARGET_NATIVE_FILE_OPEN(filename, \ + filedescriptor,\ + TARGET_NATIVE_FILE_FILEFLAG_READ, \ + TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL, \ + result \ + ) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_OPEN_WRITE +* Purpose : open an existing file for writing +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_OPEN_WRITE + #define TARGET_NATIVE_FILE_OPEN_WRITE(filename,filedescriptor,result) \ + TARGET_NATIVE_FILE_OPEN(filename, \ + filedescriptor, \ + TARGET_NATIVE_FILE_FILEFLAG_WRITE, \ + TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL, \ + result \ + ) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_OPEN_READWRITE +* Purpose : create/open a file for reading/writing +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : file is created if it does not exist +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_OPEN_READWRITE + #define TARGET_NATIVE_FILE_OPEN_READWRITE(filename,filedescriptor,result) \ + TARGET_NATIVE_FILE_OPEN(filename, \ + filedescriptor, \ + TARGET_NATIVE_FILE_FILEFLAG_READWRITE, \ + TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL, \ + result \ + ) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_OPEN_READWRITE +* Purpose : create/open a file for append +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : file is created if it does not exist +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_OPEN_APPEND + #define TARGET_NATIVE_FILE_OPEN_APPEND(filename,filedescriptor,result) \ + TARGET_NATIVE_FILE_OPEN_APPEND(filename, \ + filedescriptor, \ + TARGET_NATIVE_FILE_FILEFLAG_CREATE_FORCE|TARGET_NATIVE_FILE_FILEFLAG_APPEND, \ + TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL, \ + result \ + ) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_CLOSE +* Purpose : close a file +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_CLOSE + #include <unistd.h> + #define TARGET_NATIVE_FILE_CLOSE(filedescriptor,result) \ + do { \ + result=(close(filedescriptor)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_VALID_FILE_DESCRIPTOR +* Purpose : check if file-descriptor is valid +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_VALID_FILE_DESCRIPTOR + #if defined(HAVE_FCNTL) + #include <unistd.h> + #include <fcntl.h> + #define TARGET_NATIVE_FILE_VALID_FILE_DESCRIPTOR(filedescriptor,result) \ + do { \ + result=(fcntl(filedescriptor,F_GETFL,0)!=-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while(0) + #elif defined(HAVE_FSTAT) + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_VALID_FILE_DESCRIPTOR(filedescriptor,result) \ + do { \ + struct stat __stat; \ + \ + result=(fstat(filedescriptor,&__stat)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while(0) + #else + #error fcntl() nor fstat() available for checking if file descriptor is valid + #endif +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_TELL +* Purpose : get current file position +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_TELL + #include <sys/types.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_TELL(filedescriptor,offset,result) \ + do { \ + offset=lseek(filedescriptor,TARGET_NATIVE_MATH_INT_INT64_CONST_0,SEEK_CUR); \ + result=((offset)!=(off_t)-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_SEEK_BEGIN|CURRENT|END +* Purpose : set file position relativ to begin/current/end +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_SEEK_BEGIN + #include <sys/types.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_SEEK_BEGIN(filedescriptor,offset,newoffset,result) \ + do { \ + newoffset=lseek(filedescriptor,offset,SEEK_SET); \ + result=((newoffset)!=(off_t)-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif +#ifndef TARGET_NATIVE_FILE_SEEK_CURRENT + #include <sys/types.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_SEEK_CURRENT(filedescriptor,offset,newoffset,result) \ + do { \ + newoffset=lseek(filedescriptor,offset,SEEK_CUR); \ + result=((newoffset)!=(off_t)-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif +#ifndef TARGET_NATIVE_FILE_SEEK_END + #include <sys/types.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_SEEK_END(filedescriptor,offset,newoffset,result) \ + do { \ + newoffset=lseek(filedescriptor,offset,SEEK_END); \ + result=((newoffset)!=(off_t)-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_TRUNCATE +* Purpose : truncate a file +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_TRUNCATE + #include <unistd.h> + #define TARGET_NATIVE_FILE_TRUNCATE(filedescriptor,offset,result) \ + do { \ + result=(ftruncate(filedescriptor,offset)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_SIZE +* Purpose : get size of file (in bytes) +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_SIZE + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_SIZE(filedescriptor,length,result) \ + do { \ + struct stat __statBuffer; \ + \ + result=(fstat(filedescriptor,&__statBuffer)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + length=TARGET_NATIVE_MATH_INT_INT32_TO_INT64(__statBuffer.st_size); \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_AVAILABLE +* Purpose : get available bytes for read +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_AVAILABLE + #ifdef HAVE_SYS_IOCTL_H + #define BSD_COMP /* Get FIONREAD on Solaris2 */ + #include <sys/ioctl.h> + #endif + #ifdef HAVE_SYS_FILIO_H /* Get FIONREAD on Solaris 2.5 */ + #include <sys/filio.h> + #endif + #if defined (FIONREAD) + #define TARGET_NATIVE_FILE_AVAILABLE(filedescriptor,length,result) \ + do { \ + ssize_t __n; \ + \ + result=(ioctl(filedescriptor,FIONREAD,(char*)&__n)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + length=TARGET_NATIVE_MATH_INT_INT32_TO_INT64(__n); \ + } while (0) + #elif defined(HAVE_FSTAT) + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_AVAILABLE(filedescriptor,length,result) \ + do { \ + struct stat __statBuffer; \ + off_t __n; \ + \ + length=0; \ + \ + if ((fstat(filedescriptor,&__statBuffer)==0) && S_ISREG(__statBuffer.st_mode)) \ + { \ + __n=(lseek(filedescriptor,0,SEEK_CUR)); \ + if (__n!=-1) \ + { \ + length=TARGET_NATIVE_MATH_INT_INT32_TO_INT64(__statBuffer.st_size-__n); \ + result=TARGET_NATIVE_OK; \ + } \ + else \ + { \ + result=TARGET_NATIVE_ERROR; \ + } \ + } \ + else \ + { \ + result=TARGET_NATIVE_ERROR; \ + } \ + } while (0) + #elif defined(HAVE_SELECT) + #include <string.h> + #include <sys/select.h> + #define TARGET_NATIVE_FILE_AVAILABLE(filedescriptor,length,result) \ + do { \ + fd_set __filedescriptset; \ + struct timeval __timeval; \ + \ + length=0; \ + \ + FD_ZERO(&__filedescriptset); \ + FD_SET(filedescriptor,&__filedescriptset); \ + memset(&__timeval,0,sizeof(__timeval)); \ + switch (select(filedescriptor+1,&__filedescriptset,NULL,NULL,&__timeval)==0) \ + { \ + case -1: result=TARGET_NATIVE_ERROR; break; \ + case 0: length=JNI_JLONG_CONST_0; result=TARGET_NATIVE_OK; break; \ + default: length=JNI_JLONG_CONST_1; result=TARGET_NATIVE_OK; break; \ + } \ + } while (0) + #else + #define TARGET_NATIVE_FILE_AVAILABLE(filedescriptor,length,result) \ + do { \ + errno=TARGET_NATIVE_ERROR_OPERATION_NOT_PERMITTED; \ + length=0; \ + result=TARGET_NATIVE_ERROR; \ + } while (0) + #endif +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_READ|WRITE +* Purpose : read/write from/to frile +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_READ + #include <unistd.h> + #define TARGET_NATIVE_FILE_READ(filedescriptor,buffer,length,bytesRead,result) \ + do { \ + bytesRead=read(filedescriptor,buffer,length); \ + result=(bytesRead!=-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif +#ifndef TARGET_NATIVE_FILE_WRITE + #include <unistd.h> + #define TARGET_NATIVE_FILE_WRITE(filedescriptor,buffer,length,bytesWritten,result) \ + do { \ + bytesWritten=write(filedescriptor,buffer,length); \ + result=(bytesWritten!=-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_SET_MODE_READONLY +* Purpose : set file mode to read-only +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_SET_MODE_READONLY + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_SET_MODE_READONLY(filename,result) \ + do { \ + struct stat __statBuffer; \ + \ + if (stat(filename,&__statBuffer)==0) { \ + result=(chmod(filename,__statBuffer.st_mode & TARGET_NATIVE_FILE_FILEPERMISSION_READONLY)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } else { \ + result=TARGET_NATIVE_ERROR; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_EXISTS +* Purpose : check if file exists +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_EXISTS + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_EXISTS(filename,result) \ + do { \ + struct stat __statBuffer; \ + \ + result=(stat(filename,&__statBuffer)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_IS_FILE +* Purpose : check if directory entry is a file +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_IS_FILE + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_IS_FILE(filename,result) \ + do { \ + struct stat __statBuffer; \ + \ + result=((stat(filename,&__statBuffer)==0) && (S_ISREG(__statBuffer.st_mode)))?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_IS_DIRECTORY +* Purpose : check if directory entry is a directory +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_IS_DIRECTORY + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_IS_DIRECTORY(filename,result) \ + do { \ + struct stat __statBuffer; \ + \ + result=((stat(filename,&__statBuffer)==0) && (S_ISDIR(__statBuffer.st_mode)))?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_GET_LAST_MODIFIED +* Purpose : get last modification time of file (milliseconds) +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_GET_LAST_MODIFIED + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h> + #define TARGET_NATIVE_FILE_GET_LAST_MODIFIED(filename,time,result) \ + do { \ + struct stat __statBuffer; \ + \ + time=TARGET_NATIVE_MATH_INT_INT64_CONST_0; \ + if (stat(filename,&__statBuffer)==0) { \ + time=TARGET_NATIVE_MATH_INT_INT64_MUL(TARGET_NATIVE_MATH_INT_INT32_TO_INT64(__statBuffer.st_mtime), \ + TARGET_NATIVE_MATH_INT_INT32_TO_INT64(1000) \ + ); \ + result=TARGET_NATIVE_OK; \ + } else { \ + result=TARGET_NATIVE_ERROR; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_SET_LAST_MODIFIED +* Purpose : set last modification time of file (milliseconds) +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_SET_LAST_MODIFIED + #include <sys/types.h> + #include <sys/stat.h> + #include <unistd.h> + #ifdef HAVE_UTIME_H + #include <utime.h> + #elif HAVE_SYS_UTIME_H + #include <sys/utime.h> + #else + #error utime.h not found. Please check configuration. + #endif + #define TARGET_NATIVE_FILE_SET_LAST_MODIFIED(filename,time,result) \ + do { \ + struct stat __statBuffer; \ + struct utimbuf __utimeBuffer; \ + \ + if (stat(filename,&__statBuffer)==0) { \ + __utimeBuffer.actime =__statBuffer.st_atime; \ + __utimeBuffer.modtime=TARGET_NATIVE_MATH_INT_INT64_TO_INT32(TARGET_NATIVE_MATH_INT_INT64_DIV(time, \ + TARGET_NATIVE_MATH_INT_INT32_TO_INT64(1000) \ + ) \ + ); \ + result=(utime(filename,&__utimeBuffer)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } else { \ + result=TARGET_NATIVE_ERROR; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_DELETE +* Purpose : delete a file,link or directory +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_DELETE + #define TARGET_NATIVE_FILE_DELETE(filename,result) \ + do { \ + result=((unlink(filename)==0) || (rmdir(filename)==0))?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_RENAME +* Purpose : delete a file, link or directory +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_RENAME + #define TARGET_NATIVE_FILE_RENAME(oldfilename,newfilename,result) \ + do { \ + result=(rename(oldfilename,newfilename)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_MAKE_DIR +* Purpose : create new directory +* Input : name - directory name +* Output : result - 1 if successful, 0 otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_MAKE_DIR + #include <sys/stat.h> + #define TARGET_NATIVE_FILE_MAKE_DIR(name,result) \ + do { \ + result=((mkdir(name,(S_IRWXO|S_IRWXG|S_IRWXU))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR); \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_GET_CWD +* Purpose : get current working directory +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_GET_CWD + #include <unistd.h> + #define TARGET_NATIVE_FILE_GET_CWD(path,maxPathLength,result) \ + do {\ + result=(getcwd(path,maxPathLength)!=NULL)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_OPEN_DIR +* Purpose : open directory for reading entries. +* Input : - +* Output : handle - handle if not error, NULL otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_OPEN_DIR + #include <sys/types.h> + #include <dirent.h> + #define TARGET_NATIVE_FILE_OPEN_DIR(filename,handle,result) \ + do { \ + handle=(void*)opendir(filename); \ + result=(handle!=NULL)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while(0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_CLOSE_DIR +* Purpose : close directory +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_CLOSE_DIR + #include <sys/types.h> + #include <dirent.h> + #define TARGET_NATIVE_FILE_CLOSE_DIR(handle,result) \ + do { \ + closedir((DIR*)handle); \ + result=TARGET_NATIVE_OK; \ + } while(0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_READ_DIR +* Purpose : read directory entry +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +/* XXX ??? name als buffer? */ +#ifndef TARGET_NATIVE_FILE_READ_DIR + #include <sys/types.h> + #include <dirent.h> + #define TARGET_NATIVE_FILE_READ_DIR(handle,name,result) \ + do { \ + struct dirent *__direntBuffer; \ + \ + name=NULL; \ + \ + __direntBuffer=readdir((DIR*)handle); \ + if (__direntBuffer!=NULL) { \ + name=__direntBuffer->d_name; \ + result=TARGET_NATIVE_OK; \ + } else { \ + result=TARGET_NATIVE_ERROR; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FILE_FSYNC +* Purpose : do filesystem sync +* Input : - +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_FILE_FSYNC + #define TARGET_NATIVE_FILE_FSYNC(filedescriptor,result) \ + do { \ + result=(fsync(filedescriptor)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while(0) +#endif + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* __TARGET_GENERIC_FILE__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/generic/target_generic_io.h b/libjava/classpath/native/target/generic/target_generic_io.h new file mode 100644 index 00000000000..cc24915ab19 --- /dev/null +++ b/libjava/classpath/native/target/generic/target_generic_io.h @@ -0,0 +1,82 @@ +/* generic_math_int64.h - Native methods for 64bit math operations + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: generic target defintions of miscellaneous functions +Systems : all +*/ + +#ifndef __TARGET_GENERIC_IO__ +#define __TARGET_GENERIC_IO__ + +/* check if target_native_io.h included */ +#ifndef __TARGET_NATIVE_IO__ + #error Do NOT INCLUDE generic target files! Include the corresponding native target files instead! +#endif + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include "config.h" + +#include <stdlib.h> +#include <assert.h> + +#include "target_native.h" + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TARGET_GENERIC_IO__ */ + +/* end of file */ diff --git a/libjava/classpath/native/target/generic/target_generic_math_float.h b/libjava/classpath/native/target/generic/target_generic_math_float.h new file mode 100644 index 00000000000..e2085e08028 --- /dev/null +++ b/libjava/classpath/native/target/generic/target_generic_math_float.h @@ -0,0 +1,130 @@ +/* generic_math_int64.h - Native methods for 64bit math operations + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: generic target defintions of float/double constants/ + macros/functions +Systems : all +*/ + +#ifndef __TARGET_GENERIC_MATH_FLOAT__ +#define __TARGET_GENERIC_MATH_FLOAT__ + +/* check if target_native_math_float.h included */ +#ifndef __TARGET_NATIVE_MATH_FLOAT__ + #error Do NOT INCLUDE generic target files! Include the corresponding native target files instead! +#endif + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include "config.h" + +#include <stdlib.h> +#include <assert.h> + +#include <jni.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/* test float/double values for NaN,Inf */ +#ifndef TARGET_NATIVE_MATH_FLOAT_FLOAT_ISNAN + #include <math.h> + #define TARGET_NATIVE_MATH_FLOAT_FLOAT_ISNAN(f) isnan(f) +#endif +#ifndef TARGET_NATIVE_MATH_FLOAT_FLOAT_ISINF + #include <math.h> + #define TARGET_NATIVE_MATH_FLOAT_FLOAT_ISINF(f) isinf(f) +#endif +#ifndef TARGET_NATIVE_MATH_FLOAT_FLOAT_FINITE + #include <math.h> + #define TARGET_NATIVE_MATH_FLOAT_FLOAT_FINITE(f) finite(f) +#endif + +#ifndef TARGET_NATIVE_MATH_FLOAT_DOUBLE_ISNAN + #include <math.h> + #define TARGET_NATIVE_MATH_FLOAT_DOUBLE_ISNAN(d) isnan(d) +#endif +#ifndef TARGET_NATIVE_MATH_FLOAT_DOUBLE_ISINF + #include <math.h> + #define TARGET_NATIVE_MATH_FLOAT_DOUBLE_ISINF(d) isinf(d) +#endif +#ifndef TARGET_NATIVE_MATH_FLOAT_DOUBLE_FINITE + #include <math.h> + #define TARGET_NATIVE_MATH_FLOAT_DOUBLE_FINITE(d) finite(d) +#endif + +/* division, modulo operations (used to avoid unexcepted exceptions on some + targets; generic codes are direct operations without checks) +*/ +#ifndef TARGET_NATIVE_MATH_FLOAT_FLOAT_DIV + #define TARGET_NATIVE_MATH_FLOAT_FLOAT_DIV(f0,f1) ((f0)/(f1)) +#endif +#ifndef TARGET_NATIVE_MATH_FLOAT_FLOAT_MOD + #include <math.h> + #define TARGET_NATIVE_MATH_FLOAT_FLOAT_MOD(f0,f1) ((jfloat)fmod((jdouble)(f0),(jdouble)(f1))) +#endif + +#ifndef TARGET_NATIVE_MATH_FLOAT_DOUBLE_DIV + #define TARGET_NATIVE_MATH_FLOAT_DOUBLE_DIV(d0,d1) ((d0)/(d1)) +#endif +#ifndef TARGET_NATIVE_MATH_FLOAT_DOUBLE_MOD + #include <math.h> + #define TARGET_NATIVE_MATH_FLOAT_DOUBLE_MOD(d0,d1) fmod(d0,d1) +#endif + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TARGET_GENERIC_MATH_FLOAT__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/generic/target_generic_math_int.h b/libjava/classpath/native/target/generic/target_generic_math_int.h new file mode 100644 index 00000000000..c6861487efd --- /dev/null +++ b/libjava/classpath/native/target/generic/target_generic_math_int.h @@ -0,0 +1,260 @@ +/* generic_math_int64.h - Native methods for 64bit math operations + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: generic target defintions of int/int64 constants/ + macros/functions +Systems : all +*/ + +#ifndef __TARGET_GENERIC_MATH_INT__ +#define __TARGET_GENERIC_MATH_INT__ + +/* check if target_native_math_int.h included */ +#ifndef __TARGET_NATIVE_MATH_INT__ + #error Do NOT INCLUDE generic target files! Include the corresponding native target files instead! +#endif + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include "config.h" + +#include <stdlib.h> +#include <assert.h> + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ +#ifndef TARGET_NATIVE_MATH_INT_INT64_CONST_0 + #define TARGET_NATIVE_MATH_INT_INT64_CONST_0 0LL +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_CONST_1 + #define TARGET_NATIVE_MATH_INT_INT64_CONST_1 1LL +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1 + #define TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1 -1LL +#endif + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/* math operations */ +#ifndef TARGET_NATIVE_MATH_INT_INT64_ADD + #define TARGET_NATIVE_MATH_INT_INT64_ADD(v1,v2) ((v1)+(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_SUB + #define TARGET_NATIVE_MATH_INT_INT64_SUB(v1,v2) ((v1)-(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_MUL + #define TARGET_NATIVE_MATH_INT_INT64_MUL(v1,v2) ((v1)*(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_DIV + #define TARGET_NATIVE_MATH_INT_INT64_DIV(v1,v2) ((v1)/(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_MOD + #define TARGET_NATIVE_MATH_INT_INT64_MOD(v1,v2) ((v1)%(v2)) +#endif + +#ifndef TARGET_NATIVE_MATH_INT_UINT64_ADD + #define TARGET_NATIVE_MATH_INT_UINT64_ADD(v1,v2) ((v1)+(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_SUB + #define TARGET_NATIVE_MATH_INT_UINT64_SUB(v1,v2) ((v1)-(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_MUL + #define TARGET_NATIVE_MATH_INT_UINT64_MUL(v1,v2) ((v1)*(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_DIV + #define TARGET_NATIVE_MATH_INT_UINT64_DIV(v1,v2) ((v1)/(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_MOD + #define TARGET_NATIVE_MATH_INT_UINT64_MOD(v1,v2) ((v1)%(v2)) +#endif + +/* bit operations */ +#ifndef TARGET_NATIVE_MATH_INT_INT64_AND + #define TARGET_NATIVE_MATH_INT_INT64_AND(v1,v2) ((v1)&(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_OR + #define TARGET_NATIVE_MATH_INT_INT64_OR(v1,v2) ((v1)|(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_XOR + #define TARGET_NATIVE_MATH_INT_INT64_XOR(v1,v2) ((v1)^(v2)) +#endif + +#ifndef TARGET_NATIVE_MATH_INT_UINT64_AND + #define TARGET_NATIVE_MATH_INT_UINT64_AND(v1,v2) ((v1)&(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_OR + #define TARGET_NATIVE_MATH_INT_UINT64_OR(v1,v2) ((v1)|(v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_XOR + #define TARGET_NATIVE_MATH_INT_UINT64_XOR(v1,v2) ((v1)^(v2)) +#endif + +/* shift operations */ +#ifndef TARGET_NATIVE_MATH_INT_INT64_SHIFTL + #define TARGET_NATIVE_MATH_INT_INT64_SHIFTL(v,l) ((v)<<(l)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_SHIFTR + #define TARGET_NATIVE_MATH_INT_INT64_SHIFTR(v,l) (((v)>>(l)) | (((v)>=0) ? 0 : (0xffffFFFFffffFFFFLL << (64-(l))))) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_SHIFTR + #define TARGET_NATIVE_MATH_INT_UINT64_SHIFTR(v,l) (((v)>>(l)) & ~(((v)>=0) ? 0 : (0xffffFFFFffffFFFFLL << (64-(l))))) +#endif + +/* negation */ +#ifndef TARGET_NATIVE_MATH_INT_INT64_NEG + #define TARGET_NATIVE_MATH_INT_INT64_NEG(v) (-(v)) +#endif + +/* increment/decrement routines */ +#ifndef TARGET_NATIVE_MATH_INT_INT64_INC + #define TARGET_NATIVE_MATH_INT_INT64_INC(v) { v++; } +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_DEC + #define TARGET_NATIVE_MATH_INT_INT64_DEC(v) { v--; } +#endif + +#ifndef TARGET_NATIVE_MATH_INT_UINT64_INC + #define TARGET_NATIVE_MATH_INT_UINT64_INC(v) { v++; } +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_DEC + #define TARGET_NATIVE_MATH_INT_UINT64_DEC(v) { v--; } +#endif + +/* comparison routines */ +#ifndef TARGET_NATIVE_MATH_INT_INT64_EQ + #define TARGET_NATIVE_MATH_INT_INT64_EQ(v1,v2) ((v1) == (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_NE + #define TARGET_NATIVE_MATH_INT_INT64_NE(v1,v2) ((v1) != (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_LT + #define TARGET_NATIVE_MATH_INT_INT64_LT(v1,v2) ((v1) < (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_LE + #define TARGET_NATIVE_MATH_INT_INT64_LE(v1,v2) ((v1) <= (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_GT + #define TARGET_NATIVE_MATH_INT_INT64_GT(v1,v2) ((v1) > (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_GE + #define TARGET_NATIVE_MATH_INT_INT64_GE(v1,v2) ((v1) >= (v2)) +#endif + +#ifndef TARGET_NATIVE_MATH_INT_UINT64_EQ + #define TARGET_NATIVE_MATH_INT_UINT64_EQ(v1,v2) ((v1) == (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_NE + #define TARGET_NATIVE_MATH_INT_UINT64_NE(v1,v2) ((v1) != (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_LT + #define TARGET_NATIVE_MATH_INT_UINT64_LT(v1,v2) ((v1) < (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_LE + #define TARGET_NATIVE_MATH_INT_UINT64_LE(v1,v2) ((v1) <= (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_GT + #define TARGET_NATIVE_MATH_INT_UINT64_GT(v1,v2) ((v1) > (v2)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_GE + #define TARGET_NATIVE_MATH_INT_UINT64_GE(v1,v2) ((v1) >= (v2)) +#endif + +/* type conversion routines */ +#ifndef TARGET_NATIVE_MATH_INT_INT32_TO_INT64 + #define TARGET_NATIVE_MATH_INT_INT32_TO_INT64(v) ((jlong)(v)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT32_TO_UINT64 + #define TARGET_NATIVE_MATH_INT_UINT32_TO_UINT64(v) ((jlong)(v)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_TO_INT32 + #define TARGET_NATIVE_MATH_INT_INT64_TO_INT32(v) ((jint )(v)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_TO_UINT32 + #define TARGET_NATIVE_MATH_INT_UINT64_TO_UINT32(v) ((jint)(v)) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_TO_DOUBLE + #define TARGET_NATIVE_MATH_INT_INT64_TO_DOUBLE(v) ((jdouble)(v)) +#endif + +/* combine/split int32 low/high values <-> int64 values */ +#ifndef TARGET_NATIVE_MATH_INT_INT32_LOW_HIGH_TO_INT64 + #define TARGET_NATIVE_MATH_INT_INT32_LOW_HIGH_TO_INT64(low,high,v) \ + do { \ + (v)=((((jlong)(high)) << 32) | ((((jlong)(low)) << 0) & 0x00000000ffffFFFFLL)); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT32_LOW_HIGH_TO_UINT64 + #define TARGET_NATIVE_MATH_INT_UINT32_LOW_HIGH_TO_UINT64(low,high,v) \ + do { \ + (v)=((((jlong)(high)) << 32) | ((((jlong)(low)) << 0) & 0x00000000ffffFFFFLL)); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MATH_INT_INT64_TO_INT32_LOW_HIGH + #define TARGET_NATIVE_MATH_INT_INT64_TO_INT32_LOW_HIGH(v,low,high) \ + do { \ + (high)=((v) & 0xFFFFffff00000000L) >> 32; \ + (low) =((v) & 0x00000000FFFFffffL) >> 0; \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MATH_INT_UINT64_TO_UINT32_LOW_HIGH + #define TARGET_NATIVE_MATH_INT_UINT64_TO_UINT32_LOW_HIGH(v,low,high) \ + do { \ + (high)=((v) & 0xFFFFffff00000000L) >> 32; \ + (low) =((v) & 0x00000000FFFFffffL) >> 0; \ + } while (0) +#endif + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TARGET_GENERIC_MATH_INT__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/generic/target_generic_misc.h b/libjava/classpath/native/target/generic/target_generic_misc.h new file mode 100644 index 00000000000..1174aa83c7e --- /dev/null +++ b/libjava/classpath/native/target/generic/target_generic_misc.h @@ -0,0 +1,203 @@ +/* generic_math_int64.h - Native methods for 64bit math operations + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: generic target defintions of miscellaneous functions +Systems : all +*/ + +#ifndef __TARGET_GENERIC_MISC__ +#define __TARGET_GENERIC_MISC__ + +/* check if target_native_misc.h included */ +#ifndef __TARGET_NATIVE_MISC__ + #error Do NOT INCLUDE generic target files! Include the corresponding native target files instead! +#endif + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include "config.h" + +#include <stdlib.h> +#include <assert.h> + +#include "target_native.h" + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***********************************************************************\ +* Name : TARGET_NATIVE_MISC_FORMAT_STRING<n> +* Purpose : format a string (with a fixed number of) arguments +* Input : buffer - buffer for string +* bufferSize - size of buffer +* format - format string (like printf) +* args - optional arguments (GNU CPP only!) +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - this is a "safe" macro to format string; buffer- +* overflows will be avoided. Direct usage of e. g. +* snprintf() is not permitted because it is not ANSI C +* (not portable!) +* - do not use this routine in a function without +* variable number of arguments (ellipses), because +* va_list/va_start/va_end is used! +\***********************************************************************/ + +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING0 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING0(buffer,bufferSize,format) \ + do { \ + snprintf(buffer,bufferSize,format); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING1 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING1(buffer,bufferSize,format,arg1) \ + do { \ + snprintf(buffer,bufferSize,format,arg1); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING2 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING2(buffer,bufferSize,format,arg1,arg2) \ + do { \ + snprintf(buffer,bufferSize,format,arg1,arg2); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING3 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING3(buffer,bufferSize,format,arg1,arg2,arg3) \ + do { \ + snprintf(buffer,bufferSize,format,arg1,arg2,arg3); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING4 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING4(buffer,bufferSize,format,arg1,arg2,arg3,arg4) \ + do { \ + snprintf(buffer,bufferSize,format,arg1,arg2,arg3,arg4); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING5 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING5(buffer,bufferSize,format,arg1,arg2,arg3,arg4,arg5) \ + do { \ + snprintf(buffer,bufferSize,format,arg1,arg2,arg3,arg4,arg5); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING6 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING6(buffer,bufferSize,format,arg1,arg2,arg3,arg4,arg5,arg6) \ + do { \ + snprintf(buffer,bufferSize,format,arg1,arg2,arg3,arg4,arg5,arg6); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING7 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING7(buffer,bufferSize,format,arg1,arg2,arg3,arg14,arg5,arg6,arg7) \ + do { \ + snprintf(buffer,bufferSize,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING8 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING8(buffer,bufferSize,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) \ + do { \ + snprintf(buffer,bufferSize,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); \ + } while (0) +#endif +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING9 + #include <stdarg.h> + #define TARGET_NATIVE_MISC_FORMAT_STRING9(buffer,bufferSize,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9) \ + do { \ + snprintf(buffer,bufferSize,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9); \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_FORMAT_STRING_ELLIPSE +* Purpose : format a string with arguments +* Input : buffer - buffer for string +* bufferSize - size of buffer +* format - format string (like printf) +* Output : - +* Return : - +* Side-effect: unknown +* Notes : - this is a "safe" macro to format string; buffer- +* overflows will be avoided. Direct usage of e. g. +* snprintf() is not permitted because it is not ANSI C +* (not portable!) +* - do not use this routine in a function without +* variable number of arguments (ellipses), because +* va_list/va_start/va_end is used! +\***********************************************************************/ + +#ifndef TARGET_NATIVE_MISC_FORMAT_STRING_ELLIPSE + #include <stdarg.h> + #define TARGET_NATIVE_FORMAT_STRING_ELLIPSE(buffer,bufferSize,format) \ + do { \ + va_list __arguments; \ + \ + va_start(__arguments,format); \ + vsnprintf(buffer,bufferSize,format,__arguments); \ + va_end(__arguments); \ + } while (0) +#endif + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TARGET_GENERIC_MISC__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/generic/target_generic_network.h b/libjava/classpath/native/target/generic/target_generic_network.h new file mode 100644 index 00000000000..dbbd92e2c92 --- /dev/null +++ b/libjava/classpath/native/target/generic/target_generic_network.h @@ -0,0 +1,1278 @@ +/* target_generic_network.h - Native methods for network operations. + Copyright (C) 1998, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +/* +Description: generic target defintions of network functions +Systems : all +*/ + +#ifndef __TARGET_GENERIC_NETWORK__ +#define __TARGET_GENERIC_NETWORK__ + +/* check if target_native_network.h included */ +#ifndef __TARGET_NATIVE_NETWORK__ + #error Do NOT INCLUDE generic target files! Include the corresponding native target files instead! +#endif + +/****************************** Includes *******************************/ +/* do not move; needed here because of some macro definitions */ +#include "config.h" + +#include <stdlib.h> + +#include "target_native.h" + +/****************** Conditional compilation switches *******************/ + +/***************************** Constants *******************************/ + +/***************************** Datatypes *******************************/ + +/***************************** Variables *******************************/ + +/****************************** Macros *********************************/ + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT +* Purpose : convert IP adddress (4 parts) into integer (host-format +* 32bit) +* Input : n0,n1,n2,n3 - IP address parts +* Output : i - integer with IP address in host-format +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT + #define TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT(n0,n1,n2,n3,i) \ + do { \ + i=(((unsigned char)n0) << 24) | \ + (((unsigned char)n1) << 16) | \ + (((unsigned char)n2) << 8) | \ + (((unsigned char)n3) << 0); \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES +* Purpose : convert IP adddress (4 parts) into integer (host-format +* 32bit) +* Input : n0,n1,n2,n3 - IP address parts +* Output : i - integer with IP address in host-format +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES + #define TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES(i,n0,n1,n2,n3) \ + do { \ + n0=(i & 0xFF000000) >> 24; \ + n1=(i & 0x00FF0000) >> 16; \ + n2=(i & 0x0000FF00) >> 8; \ + n3=(i & 0x000000FF) >> 0; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_GET_HOSTNAME +* Purpose : get hostname +* Input : maxNameLen - max. length of name +* Output : name - name (NUL terminated) +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_GET_HOSTNAME + #include <unistd.h> + #define TARGET_NATIVE_NETWORK_GET_HOSTNAME(name,maxNameLen,result) \ + do { \ + result=(gethostname(name,maxNameLen-1)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + name[maxNameLen-1]='\0'; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_ADDRESS +* Purpose : get hostname by address +* Input : address - IP address (32bit, NOT network byte order!) +* maxNameLen - max. length of name +* Output : name - name (NUL terminated) +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +/* XXX NYI??? reentrant? */ +#ifndef TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_ADDRESS + #include <netdb.h> + #define TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_ADDRESS(address,name,maxNameLen,result) \ + do { \ + int __networkAddress; \ + struct hostent *__hostEntry; \ + \ + __networkAddress=htonl(address); \ + __hostEntry = gethostbyaddr((char*)&__networkAddress,sizeof(__networkAddress),AF_INET); \ + if (__hostEntry!=NULL) \ + { \ + strncpy(name,__hostEntry->h_name,maxNameLen-1); \ + name[maxNameLen]='\0'; \ + result=TARGET_NATIVE_OK; \ + } \ + else \ + { \ + result=TARGET_NATIVE_ERROR; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_NAME +* Purpose : get hostname by name +* Input : name - hostname +* maxAddressSize - max. size of address array +* Output : addresses - host adddresses (array, NOT in network +* byte order!) +* addressCount - number of entries in address array +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +/* XXX NYI??? reentrant? */ +#ifndef TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_NAME + #include <netdb.h> + #define TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_NAME(name,addresses,maxAddressSize,addressCount,result) \ + do { \ + struct hostent *__hostEntry; \ + \ + addressCount=0; \ + \ + __hostEntry = gethostbyname(name); \ + if (__hostEntry!=NULL) \ + { \ + while ((addressCount<maxAddressSize) && (__hostEntry->h_addr_list[addressCount]!=NULL)) \ + { \ + addresses[addressCount]=ntohl(*(int*)(__hostEntry->h_addr_list[addressCount])); \ + addressCount++; \ + } \ + result=TARGET_NATIVE_OK; \ + } \ + else \ + { \ + result=TARGET_NATIVE_ERROR; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_OPEN_STREAM +* Purpose : open stream socket +* Input : - +* Output : socketDescriptor - socket descriptor +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_OPEN_STREAM + #include <sys/types.h> + #include <sys/socket.h> + #include <fcntl.h> + #define TARGET_NATIVE_NETWORK_SOCKET_OPEN_STREAM(socketDescriptor,result) \ + do { \ + socketDescriptor=socket(AF_INET,SOCK_STREAM,0); \ + fcntl(socketDescriptor,F_SETFD,FD_CLOEXEC); \ + result=(socketDescriptor!=-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_OPEN_DATAGRAM +* Purpose : open datagram socket +* Input : - +* Output : socketDescriptor - socket descriptor +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_OPEN_DATAGRAM + #include <sys/types.h> + #include <sys/socket.h> + #include <fcntl.h> + #define TARGET_NATIVE_NETWORK_SOCKET_OPEN_DATAGRAM(socketDescriptor,result) \ + do { \ + socketDescriptor=socket(AF_INET,SOCK_DGRAM,0); \ + fcntl(socketDescriptor,F_SETFD,FD_CLOEXEC); \ + result=(socketDescriptor!=-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_CLOSE +* Purpose : close socket +* Input : socketDescriptor - socket descriptor +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_CLOSE + #include <unistd.h> + #define TARGET_NATIVE_NETWORK_SOCKET_CLOSE(socketDescriptor,result) \ + do { \ + result=(close(socketDescriptor)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_CONNECT +* Purpose : connect socket +* Input : socketDescriptor - socket descriptor +* address - address (network format???) +* port - port number (NOT in network byte order!) +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_CONNECT + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_CONNECT(socketDescriptor,address,port,result) \ + do { \ + struct sockaddr_in __socketAddress; \ + \ + memset(&__socketAddress,0,sizeof(__socketAddress)); \ + __socketAddress.sin_family = AF_INET; \ + __socketAddress.sin_addr.s_addr = htonl(address); \ + __socketAddress.sin_port = htons(((short)port)); \ + \ + result=(connect(socketDescriptor,(struct sockaddr*)&__socketAddress,sizeof(__socketAddress))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_BIND +* Purpose : bind socket +* Input : socketDescriptor - socket descriptor +* address - address (NOT ??? in network byte order!) +* port - port (NOT in network byte order!) +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +/* XXX ??? address in network byte order? */ +#ifndef TARGET_NATIVE_NETWORK_SOCKET_BIND + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_BIND(socketDescriptor,address,port,result) \ + do { \ + struct sockaddr_in __socketAddress; \ + \ + memset(&__socketAddress,0,sizeof(__socketAddress)); \ + __socketAddress.sin_family = AF_INET; \ + __socketAddress.sin_addr.s_addr = htonl(address); \ + __socketAddress.sin_port = htons(((short)port)); \ + \ + result=(bind(socketDescriptor,(struct sockaddr*)&__socketAddress,sizeof(__socketAddress))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_LISTEN +* Purpose : listen socket +* Input : socketDescriptor - socket descriptor +* maxQueueLength - max. number of pending connections +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +/* XXX ??? address in network byte order? */ +#ifndef TARGET_NATIVE_NETWORK_SOCKET_LISTEN + #include <sys/socket.h> + #define TARGET_NATIVE_NETWORK_SOCKET_LISTEN(socketDescriptor,maxQueueLength,result) \ + do { \ + result=(listen(socketDescriptor,maxQueueLength)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_ACCEPT +* Purpose : accept socket +* Input : socketDescriptor - socket descriptor +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +/* XXX ??? address in network byte order? */ +#ifndef TARGET_NATIVE_NETWORK_SOCKET_ACCEPT + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_ACCEPT(socketDescriptor,newSocketDescriptor,result) \ + do { \ + struct sockaddr_in __socketAddress; \ + socklen_t __socketAddressLength; \ + \ + memset(&__socketAddress,0,sizeof(__socketAddress)); \ + __socketAddressLength=sizeof(__socketAddress); \ + newSocketDescriptor=accept(socketDescriptor,(struct sockaddr*)&__socketAddress,&__socketAddressLength); \ + result=(newSocketDescriptor!=-1)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO +* Purpose : get local socket data info +* Input : socketDescriptor - socket descriptor +* Output : localAddress - local address (NOT in network byte order!) +* localPort - local port number (NOT in network byte order!) +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO(socketDescriptor,localAddress,localPort,result) \ + do { \ + struct sockaddr_in __socketAddress; \ + socklen_t __socketAddressLength; \ + \ + localAddress=0; \ + localPort =0; \ + \ + __socketAddressLength=sizeof(__socketAddress); \ + result=(getsockname(socketDescriptor,(struct sockaddr*)&__socketAddress,&__socketAddressLength)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + localAddress=ntohl(__socketAddress.sin_addr.s_addr); \ + localPort =ntohs(__socketAddress.sin_port); \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO +* Purpose : get remote socket data info +* Input : socketDescriptor - socket descriptor +* Output : remoteAddress - remote address (NOT in network byte order!) +* remotePort - remote port number (NOT in network byte order!) +* : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_REMOTE_INFO(socketDescriptor,remoteAddress,remotePort,result) \ + do { \ + struct sockaddr_in __socketAddress; \ + socklen_t __socketAddressLength; \ + \ + remoteAddress=0; \ + remotePort =0; \ + \ + __socketAddressLength=sizeof(__socketAddress); \ + result=(getpeername(socketDescriptor,(struct sockaddr*)&__socketAddress,&__socketAddressLength)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + remoteAddress=ntohl(__socketAddress.sin_addr.s_addr); \ + remotePort =ntohs(__socketAddress.sin_port); \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_AVAILABLE +* Purpose : get number of available bytes for receive +* Input : socketDescriptor - socket descriptor +* Output : bytesAvailable - available bytes for receive +* : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_AVAILABLE + #include <sys/ioctl.h> + #define TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_AVAILABLE(socketDescriptor,bytesAvailable,result) \ + do { \ + int __value; \ + \ + bytesAvailable=0; \ + \ + result=(ioctl(socketDescriptor,FIONREAD,&__value)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + bytesAvailable=__value; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_RECEIVE +* Purpose : receive data from socket +* Input : socketDescriptor - socket descriptor +* maxLength - max. size of bfufer +* Output : buffer - received data +* bytesReceive - length of received data +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_RECEIVE + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_RECEIVE(socketDescriptor,buffer,maxLength,bytesReceived) \ + do { \ + struct sockaddr_in __socketAddress; \ + socklen_t __socketAddressLength; \ + \ + memset(&__socketAddress,0,sizeof(__socketAddress)); \ + __socketAddressLength=sizeof(__socketAddress); \ + bytesReceived=recv(socketDescriptor,buffer,maxLength,0); \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_WITH_ADDRESS_PORT +* Purpose : receive data from socket +* Input : socketDescriptor - socket descriptor +* maxLength - max. size of bfufer +* Output : buffer - received data +* address - from address (NOT in network byte order!) +* port - from port (NOT in network byte order!) +* bytesReceive - length of received data +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_WITH_ADDRESS_PORT + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_WITH_ADDRESS_PORT(socketDescriptor,buffer,maxLength,address,port,bytesReceived) \ + do { \ + struct sockaddr_in __socketAddress; \ + socklen_t __socketAddressLength; \ + \ + port=0; \ + \ + memset(&__socketAddress,0,sizeof(__socketAddress)); \ + __socketAddressLength=sizeof(__socketAddress); \ + bytesReceived=recvfrom(socketDescriptor,buffer,maxLength,0,(struct sockaddr*)&__socketAddress,&__socketAddressLength); \ + if (__socketAddressLength==sizeof(__socketAddress)) \ + { \ + address=ntohl(__socketAddress.sin_addr.s_addr); \ + port =ntohs(__socketAddress.sin_port); \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SEND +* Purpose : send data to socket +* Input : socketDescriptor - socket descriptor +* : buffer - data to send +* length - length of data to send +* Output : bytesSent - number of bytes sent, -1 otherwise +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SEND + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SEND(socketDescriptor,buffer,length,bytesSent) \ + do { \ + bytesSent=send(socketDescriptor,buffer,length,0); \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT +* Purpose : send data to socket +* Input : socketDescriptor - socket descriptor +* : buffer - data to send +* length - length of data to send +* Address - to address (NOT in network byte order!) +* Port - to port (NOT in network byte order!) +* Output : bytesSent - number of bytes sent, -1 otherwise +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT(socketDescriptor,buffer,length,address,port,bytesSent) \ + do { \ + struct sockaddr_in __socketAddress; \ + \ + memset(&__socketAddress,0,sizeof(__socketAddress)); \ + __socketAddress.sin_family = AF_INET; \ + __socketAddress.sin_addr.s_addr = htonl(address); \ + __socketAddress.sin_port = htons((short)port); \ + bytesSent=sendto(socketDescriptor,buffer,length,0,(struct sockaddr*)&__socketAddress,sizeof(__socketAddress)); \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_TCP_NODELAY +* Purpose : set socket option TCP_NODELAY +* Input : socketDescriptor - socket descriptor +* flag - 1 or 0 +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_TCP_NODELAY + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/tcp.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_TCP_NODELAY(socketDescriptor,flag,result) \ + do { \ + int __value; \ + \ + __value=flag; \ + result=(setsockopt(socketDescriptor,IPPROTO_TCP,TCP_NODELAY,&__value,sizeof(__value))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER +* Purpose : set socket option SO_LINGER +* Input : socketDescriptor - socket descriptor +* flag - 1 or 0 +* value - linger value +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER + #include <sys/types.h> + #include <sys/socket.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_LINGER(socketDescriptor,flag,value,result) \ + do { \ + struct linger __linger; \ + \ + memset(&__linger,0,sizeof(__linger)); \ + if (flag) \ + { \ + __linger.l_onoff=0; \ + } \ + else \ + { \ + __linger.l_linger=value; \ + __linger.l_onoff =1; \ + } \ + result=(setsockopt(socketDescriptor,SOL_SOCKET,SO_LINGER,&__linger,sizeof(__linger))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_TIMEOUT +* Purpose : set socket option SO_TIMEOUT +* Input : socketDescriptor - socket descriptor +* flag - 1 or 0 +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_TIMEOUT + #include <sys/types.h> + #include <sys/socket.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_TIMEOUT(socketDescriptor,flag,result) \ + do { \ + struct timeval __value; \ + \ + __value.tv_sec = flag / 1000; \ + __value.tv_usec = (flag % 1000) * 1000; \ + result=(setsockopt(socketDescriptor,SOL_SOCKET,SO_TIMEOUT,&__value,sizeof(__value))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_SNDBUF +* Purpose : set socket option SO_SNDBUF +* Input : socketDescriptor - socket descriptor +* size - size of send buffer +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_SNDBUF + #include <sys/types.h> + #include <sys/socket.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_SNDBUF(socketDescriptor,size,result) \ + do { \ + int __value; \ + \ + __value=size; \ + result=(setsockopt(socketDescriptor,SOL_SOCKET,SO_SNDBUF,&__value,sizeof(__value))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_RCDBUF +* Purpose : set socket option SO_RCDBUF +* Input : socketDescriptor - socket descriptor +* size - size of receive buffer +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_RCDBUF + #include <sys/types.h> + #include <sys/socket.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_SO_RCDBUF(socketDescriptor,size,result) \ + do { \ + int __value; \ + \ + __value=size; \ + result=(setsockopt(socketDescriptor,SOL_SOCKET,SO_RCVBUF,&__value,sizeof(__value))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_TTL +* Purpose : set socket option IP_TTL +* Input : socketDescriptor - socket descriptor +* value - value +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_TTL + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_TTL(socketDescriptor,value,result) \ + do { \ + int __value; \ + \ + __value=value; \ + result=(setsockopt(socketDescriptor,IPPROTO_IP,IP_TTL,&__value,sizeof(__value))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_MULTICAST_IF +* Purpose : set socket option IP_MULTICAST_IF +* Input : socketDescriptor - socket descriptor +* address - integer with IP address in host-format +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_MULTICAST_IF + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_IP_MULTICAST_IF(socketDescriptor,address,result) \ + do { \ + struct sockaddr_in __socketAddress; \ + \ + memset(&__socketAddress,0,sizeof(__socketAddress)); \ + __socketAddress.sin_family = AF_INET; \ + __socketAddress.sin_addr.s_addr = htonl(address); \ + result=(setsockopt(socketDescriptor,IPPROTO_IP,IP_MULTICAST_IF,&__socketAddress,sizeof(__socketAddress))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_REUSE_ADDRESS +* Purpose : set socket option REUSE_ADDRESS +* Input : socketDescriptor - socket descriptor +* flag - 1 or 0 +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_REUSE_ADDRESS + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_REUSE_ADDRESS(socketDescriptor,flag,result) \ + do { \ + int __value; \ + \ + __value=flag; \ + result=(setsockopt(socketDescriptor,SOL_SOCKET,SO_REUSEADDR,&__value,sizeof(__value))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_ADD_MEMBERSHIP +* Purpose : set socket option IP_ADD_MEMBERSHIP +* Input : socketDescriptor - socket descriptor +* address - network address (host-format) +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_ADD_MEMBERSHIP + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_ADD_MEMBERSHIP(socketDescriptor,address,result) \ + do { \ + struct ip_mreq __request; \ + \ + memset(&__request,0,sizeof(__request)); \ + __request.imr_multiaddr.s_addr=htonl(address); \ + __request.imr_interface.s_addr=INADDR_ANY; \ + result=(setsockopt(socketDescriptor,IPPROTO_IP,IP_ADD_MEMBERSHIP,&__request,sizeof(__request))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_DROP_MEMBERSHIP +* Purpose : set socket option IP_DROP_MEMBERSHIP +* Input : socketDescriptor - socket descriptor +* address - network address (host-format) +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_DROP_MEMBERSHIP + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_DROP_MEMBERSHIP(socketDescriptor,address,result) \ + do { \ + struct ip_mreq __request; \ + \ + memset(&__request,0,sizeof(__request)); \ + __request.imr_multiaddr.s_addr=htonl(address); \ + __request.imr_interface.s_addr=INADDR_ANY; \ + result=(setsockopt(socketDescriptor,IPPROTO_IP,IP_DROP_MEMBERSHIP,&__request,sizeof(__request))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_KEEP_ALIVE +* Purpose : set socket option KEEP_ALIVE +* Input : socketDescriptor - socket descriptor +* flag - 1 or 0 +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_KEEP_ALIVE + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_KEEP_ALIVE(socketDescriptor,flag,result) \ + do { \ + int __value; \ + \ + __value=flag; \ + result=(setsockopt(socketDescriptor,SOL_SOCKET,SO_KEEPALIVE,&__value,sizeof(__value))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_BROADCAST +* Purpose : set socket option SO_BROADCAST +* Input : socketDescriptor - socket descriptor +* flag - 1 or 0 +* Output : result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_BROADCAST + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/tcp.h> + #define TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_BROADCAST(socketDescriptor,flag,result) \ + do { \ + int __value; \ + \ + __value=flag; \ + result=(setsockopt(socketDescriptor,SOL_SOCKET,SO_BROADCAST,&__value,sizeof(__value))==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + } while (0) +#endif + +/*---------------------------------------------------------------------*/ + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_TCP_NODELAY +* Purpose : get socket option TCP_NODELAY +* Input : socketDescriptor - socket descriptor +* Output : flag - 1 or 0 +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_TCP_NODELAY + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/tcp.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_TCP_NODELAY(socketDescriptor,flag,result) \ + do { \ + int __value; \ + socklen_t __len; \ + \ + flag=0; \ + \ + __len=sizeof(__value); \ + result=(getsockopt(socketDescriptor,IPPROTO_TCP,TCP_NODELAY,&__value,&__len)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + flag=__value; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_LINGER +* Purpose : get socket option SO_LINGER +* Input : socketDescriptor - socket descriptor +* Output : flag - 1 or 0 +* value - linger value +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_LINGER + #include <sys/types.h> + #include <sys/socket.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_LINGER(socketDescriptor,flag,value,result) \ + do { \ + struct linger __linger; \ + socklen_t __len; \ + \ + flag =0; \ + value=0; \ + \ + __len=sizeof(__linger); \ + result=(getsockopt(socketDescriptor,SOL_SOCKET,SO_LINGER,&__linger,&__len)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + flag =__linger.l_onoff; \ + value=__linger.l_linger; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_TIMEOUT +* Purpose : get socket option SO_TIMEOUT +* Input : socketDescriptor - socket descriptor +* Output : flag - 1 or 0 +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_TIMEOUT + #include <sys/types.h> + #include <sys/socket.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_TIMEOUT(socketDescriptor,flag,result) \ + do { \ + struct timeval __value; \ + socklen_t __len; \ + \ + flag=0; \ + \ + __len=sizeof(__value); \ + result=(getsockopt(socketDescriptor,SOL_SOCKET,SO_TIMEOUT,&__value,&__len)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + flag = (__value.tv_sec * 1000LL) + (__value.tv_usec / 1000LL); \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_SNDBUF +* Purpose : get socket option SO_SNDBUF +* Input : socketDescriptor - socket descriptor +* Output : size - size of send buffer +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_SNDBUF + #include <sys/types.h> + #include <sys/socket.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_SNDBUF(socketDescriptor,size,result) \ + do { \ + int __value; \ + socklen_t __len; \ + \ + size=0; \ + \ + __len=sizeof(__value); \ + result=(getsockopt(socketDescriptor,SOL_SOCKET,SO_SNDBUF,&__value,&__len)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + size=__value; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_RCDBUF +* Purpose : get socket option SO_RCDBUF +* Input : socketDescriptor - socket descriptor +* Output : size - size of receive buffer +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_RCDBUF + #include <sys/types.h> + #include <sys/socket.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_SO_RCDBUF(socketDescriptor,size,result) \ + do { \ + int __value; \ + socklen_t __len; \ + \ + size=0; \ + \ + __len=sizeof(__value); \ + result=(getsockopt(socketDescriptor,SOL_SOCKET,SO_RCVBUF,&__value,&__len)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + size=__value; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_TTL +* Purpose : get socket option IP_TTL +* Input : socketDescriptor - socket descriptor +* Output : flag - 1 or 0 +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_TTL + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_TTL(socketDescriptor,flag,result) \ + do { \ + int __value; \ + socklen_t __len; \ + \ + flag=0; \ + \ + __len=sizeof(__value); \ + result=(getsockopt(socketDescriptor,IPPROTO_IP,IP_TTL,&__value,&__len)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + flag=__value; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_MULTICAST_IF +* Purpose : get socket option IP_MULTICAST_IF +* Input : socketDescriptor - socket descriptor +* Output : address - integer with IP address in host-format +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_MULTICAST_IF + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_IP_MULTICAST_IF(socketDescriptor,address,result) \ + do { \ + struct sockaddr_in __socketAddress; \ + socklen_t __socketAddressLength; \ + \ + address=0;\ + \ + memset(&__socketAddress,0,sizeof(__socketAddress)); \ + __socketAddress.sin_family = AF_INET; \ + __socketAddress.sin_addr.s_addr = htonl(address); \ + __socketAddressLength=sizeof(__socketAddress); \ + result=(getsockopt(socketDescriptor,IPPROTO_IP,IP_MULTICAST_IF,&__socketAddress,&__socketAddressLength)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + address=ntohl(__socketAddress.sin_addr.s_addr); \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BIND_ADDRESS +* Purpose : get socket option SOCKOPT_SO_BINDADDR +* Input : socketDescriptor - socket descriptor +* Output : address - integer with IP address in host-format +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BIND_ADDRESS + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BIND_ADDRESS(socketDescriptor,address,result) \ + do { \ + struct sockaddr_in __socketAddress; \ + socklen_t __socketAddressLength; \ + \ + address=0;\ + \ + memset(&__socketAddress,0,sizeof(__socketAddress)); \ + __socketAddressLength=sizeof(__socketAddress); \ + result=(getsockname(socketDescriptor,(struct sockaddr*)&__socketAddress,&__socketAddressLength)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + address=ntohl(__socketAddress.sin_addr.s_addr); \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_REUSE_ADDRESS +* Purpose : get socket option REUSE_ADDRESS +* Input : socketDescriptor - socket descriptor +* Output : flag - 1 or 0 +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_REUSE_ADDRESS + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_REUSE_ADDRESS(socketDescriptor,flag,result) \ + do { \ + int __value; \ + socklen_t __len; \ + \ + flag=0; \ + \ + __len=sizeof(__value); \ + result=(getsockopt(socketDescriptor,SOL_SOCKET,SO_REUSEADDR,&__value,&__len)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + flag=__value; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_KEEP_ALIVE +* Purpose : get socket option KEEP_ALIVE +* Input : socketDescriptor - socket descriptor +* Output : flag - 1 or 0 +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_KEEP_ALIVE + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_KEEP_ALIVE(socketDescriptor,flag,result) \ + do { \ + int __value; \ + socklen_t __len; \ + \ + flag=0; \ + \ + __len=sizeof(__value); \ + result=(getsockopt(socketDescriptor,SOL_SOCKET,SO_KEEPALIVE,&__value,&__len)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + flag=__value; \ + } \ + } while (0) +#endif + +/***********************************************************************\ +* Name : TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BROADCAST +* Purpose : get socket option SO_BROADCAST +* Input : socketDescriptor - socket descriptor +* Output : flag - 1 or 0 +* result - TARGET_NATIVE_OK if no error occurred, +* TARGET_NATIVE_ERROR otherwise +* Return : - +* Side-effect: unknown +* Notes : - +\***********************************************************************/ + +#ifndef TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BROADCAST + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/tcp.h> + #define TARGET_NATIVE_NETWORK_SOCKET_GET_OPTION_BROADCAST(socketDescriptor,flag,result) \ + do { \ + int __value; \ + socklen_t __len; \ + \ + flag=0; \ + \ + __len=sizeof(__value); \ + result=(getsockopt(socketDescriptor,SOL_SOCKET,SO_BROADCAST,&__value,&__len)==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \ + if (result==TARGET_NATIVE_OK) \ + { \ + flag=__value; \ + } \ + } while (0) +#endif + +/***************************** Functions *******************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TARGET_GENERIC_NETWORK__ */ + +/* end of file */ + diff --git a/libjava/classpath/native/target/readme.txt b/libjava/classpath/native/target/readme.txt new file mode 100644 index 00000000000..6fee79eba63 --- /dev/null +++ b/libjava/classpath/native/target/readme.txt @@ -0,0 +1,149 @@ +The GNU classpath native layer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To enable GNU classpath to run on a diverse array of different hardware +platforms, a new native software layer has been added. This layer hide all +machine and hardware dependent issues except common available definitions, +which are ANSI C functions. For each targets system where the GNU classpath +library is to be used, a specific set of native layer functions have to be +provided. A generic set of functions is provided for Unix like systems +(currently tested only with Linux). For a new target system, some or +all native layer functions have to be rewritten. The following scheme +illustrate the native layer. + + Java API + ---------------------- + | Java classes | + | -------------------- | + | C native functions | + | -------------------- | + >> | C native layer | << + | -------------------- | + | operating system | + | -------------------- | + | hardware | + ---------------------- + +The C native layer is implemented as a set of C pre-processor native macros. +These macros expand to the appropriated native code. Macros are used +instead function calls to give optimal performance and small code size. +Of course in special cases, a macro can also expand to a function call +if this is needed. This approach provide a flexible and efficient +implementation of the native layer. + +The naming pattern for native macros is like follows: + + TARGET_NATIVE_<module name>_<macro name> + +where <module name> is a name of a module, e. g. FILE; <macro name> is +the name of the specific native macro, e. g. OPEN_READ. + +The parameters for the macro use in general (with a few exceptions) the +scheme + + <parameter>,<parameter>,...,<result> + +where <parameter> is input/output parameter and <result> is the result +code TARGET_NATIVE_OK or TARGET_NATIVE_ERROR. Specific error codes +and error strings can be gotten with + + TARGET_NATIVE_LAST_ERROR and + TARGET_NATIVE_LAST_ERROR_STRING + +(see also file target_generic.h). + +For a single target system there exists two sets of native macros in +the files + + a) <target name>/target_native_<module name>.h + b) generic/target_generic_<module name>.h + +The macros in "a" are target specific implementations of native +functions, the macros in "b" are generic implementations (for Unix) of +the same native functions. If a native macro is not defined in the file +"a", then the definition in file "b" is used (there is a check to see if +a native macros is already defined elsewhere). This technique enables +"a" to 'overwrite' single generic native macros with specific native +macros for a specific target. In the default case, where only the +generic implementation of the native macros is used, the files in the +directory '<target name>' are empty except for the mandatory include of the +generic header file in the directory 'generic' at the end. Please +look at the existing Linux target specific files. + +The directory and file structure is as follows. + + native + ... + | + |--- target + | | + | |--- Linux + | | |--- target_native_<module name>.h + | | |--- ... + | | ... + | |--- ... + | |--- generic + | | |--- target_generic_<module name>.h + | | |--- ... + ... ... ... + + +Include hierarchy is as follows. + + native file <name> + --> include 'target_native_<module name>.h' + ... + <target specific definitions> + ... + --> include 'target_generic_<module name>.h' + ... + <generic definitions> + ... + +When writing native code, please take care with the following. + + - Use _only_ ANSI C specific functions directly which are available + on all target systems with the same parameters, e. g. strdup() is + not an ANSI C function, thus is is not available on all systems; mkdir() + expect on some systems different parameters. + + !!!Do NOT use this functions in your native code!!! + + Instead + + * if a function is not available, create a native macro in the file + + <target name>/target_native_<module name>.h + + * if it is a generic function, include a generic implementation in + + generic/target_generic_<module name>.h + + * Then use this macro in your native code. + + - Avoid _all_ OS specific data types and constants, e. g. structures or error + numbers. Instead, wrap them in a native macro and convert the values to + basic scalar types like char, int, double or long. + + - Take care with 64 bit values; the are machine dependent. Not all + target system support 64 bit operations. The macros in + target_generic_math_int.h give a set of macros implementing 64 bit + operations and constants. + + - Avoid - if possible - non-reentrant functions. Non-reentrant functions + cause strange problems on some multitasking systems. + + - Avoid - if possible - dynamic data types created by malloc() and similar + functions. Instead use (local) static variables to avoid stack usage. + On some target systems, dynamic memory management is either slow or even + dangerous. Moreover malloc()-calls can cause fragmentation of the system + memory, which could result in a system crash or an application failure. + +For some examples, please look in the current implementation for +Linux in the directory 'target/Linux' and the generic implementation in +the directory 'target/generic'. + + + aicas GmbH, February 2003 + + diff --git a/libjava/classpath/native/testsuite/.cvsignore b/libjava/classpath/native/testsuite/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/testsuite/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/testsuite/Makefile.am b/libjava/classpath/native/testsuite/Makefile.am new file mode 100644 index 00000000000..26f2f828b16 --- /dev/null +++ b/libjava/classpath/native/testsuite/Makefile.am @@ -0,0 +1,2 @@ +##bin_PROGRAMS = guile-jvm + diff --git a/libjava/classpath/native/testsuite/guile-jvm.c b/libjava/classpath/native/testsuite/guile-jvm.c new file mode 100644 index 00000000000..c372f75f2d8 --- /dev/null +++ b/libjava/classpath/native/testsuite/guile-jvm.c @@ -0,0 +1,223 @@ +/* + * Guile/JNI/JVM Testing Framework + * + * Copyright (c) 1998 Free Software Foundation, Inc. + * Written by Paul Fisher (rao@gnu.org) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <libguile.h> +#include <guile/gh.h> +#include <jni.h> + +static JNIEnv *env; +static jclass test_class, result_class; +static jmethodID test_mid, test_name_mid, result_name_mid, result_msg_mid; + +SCM +abort_test (SCM name, char *exception) +{ + (*env)->ExceptionClear (env); + return gh_list (name, + gh_symbol2scm ("ERROR"), + gh_str02scm (exception), + SCM_UNDEFINED); +} + +SCM +handle_test_exception (jobject test_name_obj) +{ + jthrowable throwable; + jclass object_class; + jobject err_msg_obj; + char *err_msg, *test_name; + const char *utf; + SCM result; + jboolean is_copy; + static jmethodID obj_toString_mid = NULL; + + throwable = (*env)->ExceptionOccurred (env); + (*env)->ExceptionClear (env); + + if (obj_toString_mid == NULL) + obj_toString_mid = (*env)->GetMethodID (env, + (*env)->FindClass (env, + "java/lang/Object"), + "toString", + "()Ljava/lang/String;"); + + err_msg_obj = (*env)->CallObjectMethod (env, throwable, obj_toString_mid); + + utf = (*env)->GetStringUTFChars (env, err_msg_obj, &is_copy); + err_msg = strdup (utf); + (*env)->ReleaseStringUTFChars (env, err_msg_obj, utf); + + utf = (*env)->GetStringUTFChars (env, test_name_obj, &is_copy); + test_name = strdup (utf); + (*env)->ReleaseStringUTFChars (env, test_name_obj, utf); + + result = abort_test (gh_str02scm (test_name), err_msg); + + free (err_msg); + free (test_name); + + return result; +} + +SCM +perform_test (SCM clazz_scm_name) +{ + char *clazz_name, *test_name, *result_name, *msg; + const char *utf; + jclass clazz; + jmethodID mid; + jobject test_obj, result_obj, test_name_obj, result_name_obj, msg_obj; + jboolean is_copy; + SCM scm_test_name, scm_result_name, scm_result_msg; + + clazz_name = gh_scm2newstr (clazz_scm_name, NULL); + clazz = (*env)->FindClass (env, clazz_name); + if (clazz == NULL) + { + SCM clazz_err = gh_str02scm (clazz_name); + free (clazz_name); + return abort_test (clazz_err, "Unable to find class"); + } + + mid = (*env)->GetMethodID (env, clazz, "<init>", "()V"); + test_obj = (*env)->NewObject (env, clazz, mid); + + if ((*env)->IsInstanceOf (env, test_obj, test_class) == JNI_FALSE) + { + SCM clazz_err = gh_str02scm (clazz_name); + free (clazz_name); + return abort_test (clazz_err, "Not an instanceof gnu.test.Test"); + } + free (clazz_name); + + /* Call all the Java testing methods */ + test_name_obj = (*env)->CallObjectMethod (env, test_obj, test_name_mid); + result_obj = (*env)->CallObjectMethod (env, test_obj, test_mid); + + /* Handle an exception if one occurred */ + if ((*env)->ExceptionOccurred (env)) + return handle_test_exception (test_name_obj); + + result_name_obj = (*env)->CallObjectMethod (env, result_obj, + result_name_mid); + msg_obj = (*env)->CallObjectMethod (env, result_obj, result_msg_mid); + + /* Grab all the C result messages */ + utf = (*env)->GetStringUTFChars (env, test_name_obj, &is_copy); + test_name = strdup (utf); + (*env)->ReleaseStringUTFChars (env, test_name_obj, utf); + + utf = (*env)->GetStringUTFChars (env, result_name_obj, &is_copy); + result_name = strdup (utf); + (*env)->ReleaseStringUTFChars (env, result_name_obj, utf); + + utf = (*env)->GetStringUTFChars (env, msg_obj, &is_copy); + msg = strdup (utf); + (*env)->ReleaseStringUTFChars (env, msg_obj, utf); + + /* Convert the C result messages to Scheme */ + scm_test_name = gh_str02scm (test_name); + scm_result_name = gh_symbol2scm (result_name); + scm_result_msg = gh_str02scm (msg); + + /* Free up the C result messages */ + free (test_name); + free (result_name); + free (msg); + + return gh_list (scm_test_name, + scm_result_name, + scm_result_msg, + SCM_UNDEFINED); +} + +int +init_testing_framework () +{ + JavaVM *jvm; + JDK1_1InitArgs vm_args; + + vm_args.version = 0x00010001; + JNI_GetDefaultJavaVMInitArgs (&vm_args); + vm_args.classpath = getenv ("CLASSPATH"); + if (JNI_CreateJavaVM (&jvm, &env, &vm_args) < 0) + return -1; + + test_class = (*env)->FindClass (env, "gnu/test/Test"); + if (test_class == NULL) + { + fprintf (stderr, "Unable to locate gnu.test.Test\n"); + return -1; + } + test_class = (*env)->NewGlobalRef (env, test_class); + + result_class = (*env)->FindClass (env, "gnu/test/Result"); + if (result_class == NULL) + { + fprintf (stderr, "Unable to locate gnu.test.Result\n"); + return -1; + } + result_class = (*env)->NewGlobalRef (env, result_class); + + test_mid = (*env)->GetMethodID (env, test_class, "test", + "()Lgnu/test/Result;"); + test_name_mid = (*env)->GetMethodID (env, test_class, "getName", + "()Ljava/lang/String;"); + if (test_mid == NULL || test_name_mid == NULL) + { + fprintf (stderr, "Malformed gnu.test.Test class\n"); + return -1; + } + + result_name_mid = (*env)->GetMethodID (env, result_class, "getName", + "()Ljava/lang/String;"); + result_msg_mid = (*env)->GetMethodID (env, result_class, "getMsg", + "()Ljava/lang/String;"); + if (result_name_mid == NULL || result_msg_mid == NULL) + { + fprintf (stderr, "Malformed gnu.test.Result class\n"); + return -1; + } + + gh_new_procedure1_0 ("test", perform_test); + return 0; +} + +static void +inner_main (void *closure, int argc, char **argv) +{ + if (init_testing_framework () < 0) + { + fprintf (stderr, "Unable to instantiate JVM.\n"); + exit (1); + } + scm_shell (argc, argv); +} + +int +main (int argc, char **argv) +{ + scm_boot_guile (argc, argv, inner_main, 0); + return 0; +} diff --git a/libjava/classpath/native/vmi/.cvsignore b/libjava/classpath/native/vmi/.cvsignore new file mode 100644 index 00000000000..e9f2658a694 --- /dev/null +++ b/libjava/classpath/native/vmi/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/vmi/Makefile.am b/libjava/classpath/native/vmi/Makefile.am new file mode 100644 index 00000000000..11b462a3d19 --- /dev/null +++ b/libjava/classpath/native/vmi/Makefile.am @@ -0,0 +1,6 @@ +## Input file for automake to generate the Makefile.in used by configure + +EXTRA_DIST = \ +TODO \ +vmi.c \ +vmi.h diff --git a/libjava/classpath/native/vmi/TODO b/libjava/classpath/native/vmi/TODO new file mode 100644 index 00000000000..8107ad4440b --- /dev/null +++ b/libjava/classpath/native/vmi/TODO @@ -0,0 +1,28 @@ +TODO for JCL VMI library: + +API: +- More functions will almost certainly be required. I am + adding them in only as needs arise to keep the job as + easy as possible in the short term. The full JVMDI + will presumably need to be mimicked. + +Japhar 1.1: +- Using the JVMDI for many functions, since Japhar + implements JVMDI. Several JVMDI functions are not + implemented yet, though, so it becomes a question of + waiting til they are or implementing them ourselves. +- Specifically, the JVMDI functions not yet implemented in + Japhar that the VMI calls are: + - JVMDI_GetClassModifiers() + - JVMDI_GetClassName() + - JVMDI_GetClassMethods() + - JVMDI_GetClassFields() + - JVMDI_GetImplementedInterfaces() + - JVMDI_IsInterface() + - JVMDI_IsArray() + - JVMDI_ClassLoader() + - JVMDI_GetMethodModifiers() + - JVMDI_GetThrownExceptions() + - JVMDI_GetFieldName() + - JVMDI_GetFieldDeclaringClass() + - JVMDI_GetFieldModifiers() diff --git a/libjava/classpath/native/vmi/vmi.c b/libjava/classpath/native/vmi/vmi.c new file mode 100755 index 00000000000..6022bedfde3 --- /dev/null +++ b/libjava/classpath/native/vmi/vmi.c @@ -0,0 +1,143 @@ +/* Japhar implementation of VMI. + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + + +#include <jcl.h> +#include <vmi.h> +#include <jvmdi.h> +#include <interp.h> +#include <native-threads.h> + +JNIEXPORT vmiError JNICALL +VMI_GetFrameClass(JNIEnv *env, + jframeID frame, + jclass *clazz) { + + return VMI_ERROR_NONE; +} + +JNIEXPORT vmiError JNICALL +VMI_GetFrameObject(JNIEnv *env, + jframeID frame, + jobject *obj) { + StackFrame *sframe = (StackFrame*)frame; + if(env == NULL || obj == NULL) + return VMI_ERROR_NULL_POINTER; + if(frame == NULL) + return VMI_ERROR_INVALID_FRAMEID; + + *obj = THISPTR(sframe); + return VMI_ERROR_NONE; +} + +JNIEXPORT vmiError JNICALL +VMI_GetThisFrame(JNIEnv *env, jframeID *frame) { + JThreadInfo *thread_info; + + if(env == NULL || frame == NULL) + return VMI_ERROR_NULL_POINTER; + + thread_info = THREAD_getJavaInfo(); + *frame = (jframeID)TOPFRAME(thread_info); + return VMI_ERROR_NONE; +} + +JNIEXPORT vmiError JNICALL +VMI_GetThisThreadObject(JNIEnv* env, jthread *thread) { + JThreadInfo *thread_info; + if(env == NULL || thread == NULL) + return VMI_ERROR_NULL_POINTER; + thread_info = THREAD_getJavaInfo(); + *thread = (jthread)thread_info->java_thread; + return VMI_ERROR_NONE; +} + +JNIEXPORT void JNICALL +VMI_ThrowAppropriateException(JNIEnv *env, vmiError err) { + switch(err) { + case VMI_ERROR_NONE: + JCL_ThrowException(env, "java/lang/InternalError", "ERROR_NONE passed to VMI exception thrower."); + break; + case VMI_ERROR_NULL_POINTER: + JCL_ThrowException(env, "java/lang/NullPointerException", "null pointer in VMI detected."); + break; + case VMI_ERROR_OUT_OF_MEMORY: + JCL_ThrowException(env, "java/lang/OutOfMemoryError", "Out of memory! (in VMI)."); + break; + case VMI_ERROR_INVALID_METHODID: + JCL_ThrowException(env, "java/lang/InternalError", "VMI error: INVALID_METHODID"); + break; + case VMI_ERROR_INVALID_CLASS: + JCL_ThrowException(env, "java/lang/InternalError", "VMI error: INVALID_CLASS"); + break; + case VMI_ERROR_INVALID_BCI: + JCL_ThrowException(env, "java/lang/InternalError", "VMI error: INVALID_BCI"); + break; + case VMI_ERROR_NO_SUCH_BREAKPOINT: + JCL_ThrowException(env, "java/lang/InternalError", "VMI error: NO_SUCH_BREAKPOINT"); + break; + case VMI_ERROR_VM_DEAD: + JCL_ThrowException(env, "java/lang/InternalError", "VMI error: VM Dead! Kinda makes ya wonder how this exception got thrown, huh?"); + break; + case VMI_ERROR_INVALID_FRAMEID: + JCL_ThrowException(env, "java/lang/IllegalThreadStateException", "NULL Frame ID detected in VMI."); + break; + case VMI_ERROR_INVALID_SLOT: + JCL_ThrowException(env, "java/lang/InternalError", "VMI error: INVALID_SLOT"); + break; + case VMI_ERROR_TYPE_MISMATCH: + JCL_ThrowException(env, "java/lang/InternalError", "VMI error: INVALID_SLOT"); + break; + case VMI_ERROR_NATIVE_FRAME: + JCL_ThrowException(env, "java/lang/InternalError", "VMI error: NATIVE_FRAME"); + break; + case VMI_ERROR_NO_MORE_FRAMES: + JCL_ThrowException(env, "java/lang/InternalError", "VMI error: NO_MORE_FRAMES"); + break; + case VMI_ERROR_INVALID_THREAD: + JCL_ThrowException(env, "java/lang/IllegalThreadStateException", "Invalid thread in VMI."); + break; + case VMI_ERROR_THREAD_NOT_SUSPENDED: + JCL_ThrowException(env, "java/lang/IllegalThreadStateException", "Attempt to introspect unsuspended thread in VMI."); + break; + default: + JCL_ThrowException(env, "java/lang/UnknownError", "VMI returned erroneous error value ..."); + break; + } +} + + diff --git a/libjava/classpath/native/vmi/vmi.h b/libjava/classpath/native/vmi/vmi.h new file mode 100755 index 00000000000..1a8e26a8174 --- /dev/null +++ b/libjava/classpath/native/vmi/vmi.h @@ -0,0 +1,92 @@ +/* Japhar implementation of VMI. + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +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. */ + +#ifndef __VMI_H__ +#define __VMI_H__ + +#include <jni.h> + +typedef void * jframeID; +typedef void * jthread; + +typedef enum { + VMI_ERROR_NONE, + VMI_ERROR_NULL_POINTER, + VMI_ERROR_OUT_OF_MEMORY, + VMI_ERROR_INVALID_METHODID, + VMI_ERROR_INVALID_CLASS, + VMI_ERROR_INVALID_BCI, + VMI_ERROR_NO_SUCH_BREAKPOINT, + VMI_ERROR_VM_DEAD, + VMI_ERROR_INVALID_FRAMEID, + VMI_ERROR_INVALID_SLOT, + VMI_ERROR_TYPE_MISMATCH, + VMI_ERROR_NATIVE_FRAME, + VMI_ERROR_NO_MORE_FRAMES, + VMI_ERROR_INVALID_THREAD, + VMI_ERROR_THREAD_NOT_SUSPENDED +} vmiError; + + +#define VMI_MOD_PUBLIC 0x0001 +#define VMI_MOD_PRIVATE 0x0002 +#define VMI_MOD_PROTECTED 0x0004 +#define VMI_MOD_STATIC 0x0008 +#define VMI_MOD_FINAL 0x0010 +#define VMI_MOD_SYNCHRONIZED 0x0020 +#define VMI_MOD_VOLATILE 0x0040 +#define VMI_MOD_TRANSIENT 0x0080 +#define VMI_MOD_NATIVE 0x0100 +#define VMI_MOD_INTERFACE 0x0200 +#define VMI_MOD_ABSTRACT 0x0400 + +JNIEXPORT vmiError JNICALL +VMI_GetFrameClass(JNIEnv *env, jframeID frame, jobject *obj); + +JNIEXPORT vmiError JNICALL +VMI_GetFrameObject(JNIEnv *env, jframeID frame, jobject *obj); + +JNIEXPORT vmiError JNICALL +VMI_GetThisFrame(JNIEnv *env, jframeID *frame); + +JNIEXPORT vmiError JNICALL +VMI_GetThisThreadObject(JNIEnv *env, jthread *thread); + +JNIEXPORT void JNICALL +VMI_ThrowAppropriateException(JNIEnv *env, vmiError err); + +#endif |