package bigloo;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.lang.Runtime;
import java.net.*;

public final class foreign
{
   private static final bint[] bint_allocated = new bint[2148];

   static
      {
	 for (int i = -100; i < 2048; ++i)
	    bint_allocated[i + 100] = new bint(i);
      }

   // CARE no foreign functions may throws something.. CATCH it

   public static void trace_exit()
      {
	 // System.out.println( "Good bye." );
      }

   public static void dump_stack()
      {
	 final Exception o = new Exception("jop");

	 o.printStackTrace();
      }

   /////
   // PRAGMAS
   /////
   public static int ptr_alg()
      {
	 return 2;
      }

   /////
   // INTERNAL
   /////
   public static void print(String msg)
      {
	 System.out.println(msg);
      }

   public static void oprint(Object msg)
      {
	 System.out.println("OPRINT = " + msg);
      }

   public static void Error(String msg)
      {
	 System.err.println(msg);
	 System.exit(-1);
      }

   public static byte[] FOREIGN_TYPE_NAME(Object o)
      {
	 return o.getClass().toString().getBytes();
      }

   public static Object listargv(String[]argv)
      {
	 final int len = argv.length;
	 Object result = BNIL;

	 for (int i = 0; i < len; ++i)
	    result = new pair(argv[len - i - 1].getBytes(), result);
	 result = new pair(executable_name, result);
	 command_line = result;
	 return result;
      }

   public static int parseint(byte[]buf, int pos, int bout, int radix)
      {
	 int result = 0;
	 boolean neg = false;
	 byte cn;

	 if (buf[pos] == (byte) '-')
	 {
	    ++pos;
	    neg = true;
	 }
	 if (buf[pos] == (byte) '+')
	 {
	    ++pos;
	    neg = false;
	 }

	 while (pos < bout)
	 {
	    cn = buf[pos++];
	    if (((byte) '0' <= cn) && (cn <= (byte) '9'))
	       result = result * radix + (cn - (byte) '0');
	    else if (cn <= (byte) 'Z')
	       result = result * radix + 10 + (cn - (byte) 'A');
	    else
	       result = result * radix + 10 + (cn - (byte) 'a');
	 }

	 return (neg ? -result : result);
      }

   public static Object parseinteger(byte[]buf, int pos, int bout, int radix)
      {
	 int result = 0;
	 boolean neg = false;
	 byte cn;

	 if (buf[pos] == (byte) '-')
	 {
	    ++pos;
	    neg = true;
	 }
	 if (buf[pos] == (byte) '+')
	 {
	    ++pos;
	    neg = false;
	 }

	 while (pos < bout)
	 {
	    int result2;
	    cn = buf[pos++];
	    if (((byte) '0' <= cn) && (cn <= (byte) '9'))
	       result2 = result * radix + (cn - (byte) '0');
	    else if (cn <= (byte) 'Z')
	       result2 = result * radix + 10 + (cn - (byte) 'A');
	    else
	       result2 = result * radix + 10 + (cn - (byte) 'a');

	    if( result2 < result ) {
	       long result3 = result; 
	       pos--;
	       while (pos < bout)
	       {
		  cn = buf[pos++];
		  if (((byte) '0' <= cn) && (cn <= (byte) '9'))
		     result3 = result3 * radix + (cn - (byte) '0');
		  else if (cn <= (byte) 'Z')
		     result3 = result3 * radix + 10 + (cn - (byte) 'A');
		  else
		     result3 = result3 * radix + 10 + (cn - (byte) 'a');
	       }
	       return LLONG_TO_BLLONG(neg ? -result3 : result3);
	    } else {
	       result = result2;
	    }
	 }

	 return BINT(neg ? -result : result);
      }

   /////
   // BOOLEAN
   /////
   // Constants
   public static final bbool BTRUE = bbool.vrai;
   public static final bbool BFALSE = bbool.faux;

   // Predicates
   public static boolean BOOLEANP(Object o)
      {
	 return ((o == bbool.faux) || (o == bbool.vrai));
      }

   // Conversions
   public static boolean CBOOL(bbool b)
      {
	 return (b != bbool.faux);
      }

   public static boolean CBOOL(Object b)
      {
	 return (b != bbool.faux);
      }

   public static bbool BBOOL(boolean b)
      {
	 return (b ? bbool.vrai : bbool.faux);
      }

   // Lib functions
   public static boolean EQ(Object o1, Object o2)
      {
	 return ((o1 == o2) ||
		 ((o1 instanceof bint)
		  && (o2 instanceof bint)
		  && (((bint) o1).value == ((bint) o2).value)));
      }

   public static boolean BOXED_EQ(Object o1, Object o2)
      {
	 return (o1 == o2);
      }

   //////
   // CHARACTER
   //////
   // Predicates
   public static boolean CHARP(Object o)
      {
	 return (o instanceof bchar);
      }

   // Conversions
   public static bchar BCHAR(int cn)
      {
	 return bchar.allocated[cn & 0xFF];
      }

   public static bchar BCHAR(byte c)
      {
	 return bchar.allocated[c & 0xFF];
      }

   public static byte CCHAR(bchar c)
      {
	 return c.value;
      }

   public static int BCHAR_TO_UCHAR(bchar c)
      {
	 return c.value;
      }

   public static int CHAR_TO_UCHAR(byte c)
      {
	 return (c & 0xFF);
      }

   public static byte UCHAR_TO_CHAR(int c)
      {
	 return (byte) c;
      }

   // Open functions
   public static boolean CHAR_EQ(int cn1, int cn2)
      {
	 return (cn1 == cn2);
      }

   public static boolean CHAR_LT(int cn1, int cn2)
      {
	 return ((cn1 & 0xFF) < (cn2 & 0xFF));
      }

   public static boolean CHAR_GT(int cn1, int cn2)
      {
	 return ((cn1 & 0xFF) > (cn2 & 0xFF));
      }

   public static boolean CHAR_LE(int cn1, int cn2)
      {
	 return ((cn1 & 0xFF) <= (cn2 & 0xFF));
      }

   public static boolean CHAR_GE(int cn1, int cn2)
      {
	 return ((cn1 & 0xFF) >= (cn2 & 0xFF));
      }

   public static int CHAR_OR(int cn1, int cn2)
      {
	 return (cn1 | cn2);
      }

   public static int CHAR_AND(int cn1, int cn2)
      {
	 return (cn1 & cn2);
      }

   public static int CHAR_NOT(int cn)
   {
      return ~ cn;
   }

  // Lib functions
   public static int toupper(int cn)
   {
      if ((97 <= cn) && (cn <= 122))
	 return (cn - 32);
      return cn;
   }

   public static int tolower(int cn)
   {
      if ((65 <= cn) && (cn <= 90))
	 return (cn + 32);
      return cn;
   }

  //////
  // INTEGER
  //////
  // Constants
   public static final int SIZEOFLONG = 4;

  // Predicates
   public static boolean INTEGERP(Object o)
   {
      return (o instanceof bint);
   }

   public static boolean ELONGP(Object o)
   {
      return (o instanceof belong);
   }

   public static boolean LLONGP(Object o)
   {
      return (o instanceof bllong);
   }

  // Conversions
   public static int CHAR_TO_INT(int cn)
   {
      return (cn & 0xFF);
   }

   public static int INT_TO_CHAR(int n)
   {
      return n;
   }

   public static short INT_TO_SHORT(int n)
   {
      return (short)n;
   }

   public static int SHORT_TO_INT(short n)
   {
      return n;
   }

   public static int SHORT_TO_LONG(short n)
   {
      return n;
   }

   public static int BINT_TO_LONG(bint n)
   {
      return n.value;
   }

   public static int BINT_TO_ULONG(bint n)
   {
      return n.value;
   }

   public static int INT_TO_LONG(int n)
   {
      return n;
   }

   public static short LONG_TO_SHORT(int n)
   {
      return (short)n;
   }

   public static int LONG_TO_INT(int n)
   {
      return n;
   }

   public static int ULONG_TO_INT(int n)
   {
      return n;
   }

   public static bllong LLONG_TO_BLLONG(long n)
   {
      return new bllong(n);
   }

   public static long LONG_TO_LLONG(int n)
   {
      return n;
   }

   public static long BLLONG_TO_LLONG(bllong n)
   {
      return n.value;
   }

   public static belong LONG_TO_BELONG(int n)
   {
      return new belong(n);
   }

   public static long LONG_TO_ELONG(int n)
   {
      return n;
   }

   public static long BELONG_TO_LONG(belong n)
   {
      return n.value;
   }

   public static long BELONG_TO_ELONG(belong n)
   {
      return n.value;
   }

   public static belong ELONG_TO_BELONG(long n)
   {
      return new belong(n);
   }

   public static bllong LONG_TO_BLLONG(int n)
   {
      return new bllong(n);
   }

   public static bint BINT(long v)
   {
      if ((-100 <= v) && (v < 2018))
	 return bint_allocated[(int) v + 100];
      return new bint((int) v);
   }

   public static bint BINT(int v)
   {
      if ((-100 <= v) && (v < 2018))
	 return bint_allocated[v + 100];
      return new bint(v);
   }

   public static int CINT(bint v)
   {
      return v.value;
   }

  // Open functions
   public static boolean EQ_FX(int n1, int n2)
   {
      return (n1 == n2);
   }

   public static boolean EQ_ELONG(long n1, long n2)
   {
      return (n1 == n2);
   }

   public static boolean EQ_LLONG(long n1, long n2)
   {
      return (n1 == n2);
   }

   public static boolean LT_FX(int n1, int n2)
   {
      return (n1 < n2);
   }

   public static boolean LE_FX(int n1, int n2)
   {
      return (n1 <= n2);
   }

   public static boolean GT_FX(int n1, int n2)
   {
      return (n1 > n2);
   }

   public static boolean GE_FX(int n1, int n2)
   {
      return (n1 >= n2);
   }

   public static boolean EVENP_FX(int n)
   {
      return ((n & 1) == 0);
   }

   public static boolean ODDP_FX(int n)
   {
      return ((n & 1) != 0);
   }

   public static int PLUS_FX(int n1, int n2)
   {
      return (n1 + n2);
   }

   public static int MINUS_FX(int n1, int n2)
   {
      return (n1 - n2);
   }

   public static int MUL_FX(int n1, int n2)
   {
      return (n1 * n2);
   }

   public static int DIV_FX(int n1, int n2)
   {
      return (n1 / n2);
   }

   public static int NEG_FX(int n)
   {
      return -n;
   }

   public static int QUOTIENT_FX(int n1, int n2)
   {
      return (n1 / n2);
   }

   public static int REMAINDER_FX(int n1, int n2)
   {
      return (n1 % n2);
   }

   public static int BITOR(int a1, int a2)
   {
      return (a1 | a2);
   }

   public static int BITAND(int a1, int a2)
   {
      return (a1 & a2);
   }

   public static int BITXOR(int a1, int a2)
   {
      return (a1 ^ a2);
   }

   public static int BITNOT(int a)
   {
      return ~a;
   }

   public static int BITRSH(int a1, int a2)
   {
      return (a1 >> a2);
   }

   public static int BITURSH(int a1, int a2)
   {
      return (a1 >>> a2);
   }

   public static int BITLSH(int a1, int a2)
   {
      return (a1 << a2);
   }

  //////
  // FLOAT
  //////
  // Predicates
   public static boolean REALP(Object o)
   {
      return (o instanceof real);
   }

  // Conversions
   public static double REAL_TO_DOUBLE(real n)
   {
      return n.value;
   }

   public static float REAL_TO_FLOAT(real n)
   {
      return (float) n.value;
   }

   public static real DOUBLE_TO_REAL(double n)
   {
      return new real(n);
   }

   public static real FLOAT_TO_REAL(float n)
   {
      return new real((double) n);
   }

   public static float DOUBLE_TO_FLOAT(double n)
   {
      return (float) n;
   }

   public static double FLOAT_TO_DOUBLE(float n)
   {
      return (double) n;
   }

   public static double FIXNUM_TO_FLONUM(int n)
   {
      return (double) n;
   }

   public static int FLONUM_TO_FIXNUM(double n)
   {
      return (int) n;
   }

   public static double ELONG_TO_FLONUM(long n)
   {
      return (double) n;
   }

   public static long FLONUM_TO_ELONG(double n)
   {
      return (long) n;
   }

   public static double LLONG_TO_FLONUM(long n)
   {
      return (double) n;
   }

   public static long FLONUM_TO_LLONG(double n)
   {
      return (long) n;
   }

  // Open functions
   public static boolean EQ_FL(double n1, double n2)
   {
      return (n1 == n2);
   }

   public static boolean LT_FL(double n1, double n2)
   {
      return (n1 < n2);
   }

   public static boolean LE_FL(double n1, double n2)
   {
      return (n1 <= n2);
   }

   public static boolean GT_FL(double n1, double n2)
   {
      return (n1 > n2);
   }

   public static boolean GE_FL(double n1, double n2)
   {
      return (n1 >= n2);
   }

   public static double PLUS_FL(double n1, double n2)
   {
      return (n1 + n2);
   }

   public static double MINUS_FL(double n1, double n2)
   {
      return (n1 - n2);
   }

   public static double MUL_FL(double n1, double n2)
   {
      return (n1 * n2);
   }

   public static double DIV_FL(double n1, double n2)
   {
      return (n1 / n2);
   }

   public static double NEG_FL(double n)
   {
      return -n;
   }

   public static double fmod(double n1, double n2)
   {
      return (n1 % n2);
   }

   public static double floor(double n)
   {
      return Math.floor(n);
   }

   public static double ceil(double n)
   {
      return Math.ceil(n);
   }

   public static double exp(double n)
   {
      return Math.exp(n);
   }

   public static double log(double n)
   {
      return Math.log(n);
   }

   public static double sin(double n)
   {
      return Math.sin(n);
   }

   public static double cos(double n)
   {
      return Math.cos(n);
   }

   public static double tan(double n)
   {
      return Math.tan(n);
   }

   public static double asin(double n)
   {
      return Math.asin(n);
   }

   public static double acos(double n)
   {
      return Math.acos(n);
   }

   public static double atan(double n)
   {
      return Math.atan(n);
   }

   public static double atan2(double n1, double n2)
   {
      return Math.atan2(n1, n2);
   }

   public static double sqrt(double n)
   {
      return Math.sqrt(n);
   }

   public static double pow(double n1, double n2)
   {
      return Math.pow(n1, n2);
   }

  //////
  // OBJECT CONSTANTS
  //////
   public static final Object BUNSPEC = unspecified.unspecified;
   public static final Object BNIL = nil.nil;
   public static final Object BEOA = BNIL;
   public static final Object BEOF = eof.eof;
   public static final Object BOPTIONAL = optional.optional;
   public static final Object BREST = rest.rest;
   public static final Object BKEY = key.key;
   public static final int BDB_LIBRARY_MAGIC_NUMBER = 0x1024;

   public static boolean EOF_OBJECTP(Object o)
   {
      return (o == BEOF);
   }

   public static boolean NULLP(Object o)
   {
      return (o == BNIL);
   }

   public static int CCNST(cnst o)
   {
      return o.value;
   }

   public static int CCNST(Object o)
   {
     // CARE !! J'arrive pas a changer ce !@?# type dans intext et symbol
      return ((cnst) o).value;
   }

   public static Object BCNST(int v)
   {
      return new cnst(v);
   }

   public static boolean CNSTP(Object o)
   {
      return ((o instanceof bchar) || (o instanceof cnst));
   }

  //////
  // STANGE TYPES (no constructors invoked)

   public static boolean POINTERP(Object o)
   {
      return true;
   }

   public static boolean OPAQUEP(Object o)
   {
      return false;
   }

   public static boolean BGL_OBJECTP(Object o)
   {
      return (o instanceof object);
   }

  //////
  // Unicode characters
  //////
   public static boolean UCS2P(Object o)
   {
      return (o instanceof bucs2);
   }

   public static bucs2 BUCS2(char c)
   {
      return new bucs2(c);
   }

   public static char CUCS2(bucs2 c)
   {
      return c.value;
   }

   public static int CUCS2(char c)
   {
      return (c & 0xFFFF);
   }

   public static char INT_TO_UCS2(int n)
   {
      return (char) n;
   }

   public static boolean UCS2_EQ(char c1, char c2)
   {
      return (c1 == c2);
   }

   public static boolean UCS2_GT(char c1, char c2)
   {
      return (c1 > c2);
   }

   public static boolean UCS2_LT(char c1, char c2)
   {
      return (c1 < c2);
   }

   public static boolean UCS2_GE(char c1, char c2)
   {
      return (c1 >= c2);
   }

   public static boolean UCS2_LE(char c1, char c2)
   {
      return (c1 <= c2);
   }

   public static boolean ucs2_letterp(char c)
   {
      return Character.isLetter(c);
   }

   public static boolean ucs2_digitp(char c)
   {
      return Character.isDigit(c);
   }

   public static boolean ucs2_whitespacep(char c)
   {
      return Character.isSpaceChar(c);
   }

   public static boolean ucs2_lowerp(char c)
   {
      return Character.isLowerCase(c);
   }

   public static boolean ucs2_upperp(char c)
   {
      return Character.isUpperCase(c);
   }

   public static boolean ucs2_definedp(int c)
   {
      return Character.isDefined((char) c);
   }

   public static char ucs2_toupper(char c)
   {
      return Character.toUpperCase(c);
   }

   public static char ucs2_tolower(char c)
   {
      return Character.toLowerCase(c);
   }

  //////
  // Unicode strings
  //////
   public static boolean UCS2_STRINGP(Object o)
   {
      return (o instanceof char[]);
   }

   public static int UCS2_STRING_LENGTH(char[]o)
   {
      return o.length;
   }

   public static char[] make_ucs2_string(int len, char c)
   {
      final char[] result = new char[len];

      for (int i = 0; i < len; ++i)
	 result[i] = c;

      return result;
   }

   public static char UCS2_STRING_REF(char[]o, int i)
   {
      return o[i];
   }

   public static Object UCS2_STRING_SET(char[]o, int i, char c)
   {
      o[i] = c;
      return unspecified.unspecified;
   }

   public static boolean ucs2_strcmp(char[]o1, char[]o2)
   {
      return (new String(o1)).equals(new String(o2));
   }

   public static boolean ucs2_strcicmp(char[]o1, char[]o2)
   {
      return (new String(o1)).equalsIgnoreCase(new String(o2));
   }

   public static boolean ucs2_string_lt(char[]o1, char[]o2)
   {
      return ((new String(o1)).compareTo(new String(o2)) < 0);
   }

   public static boolean ucs2_string_gt(char[]o1, char[]o2)
   {
      return ((new String(o1)).compareTo(new String(o2)) > 0);
   }

   public static boolean ucs2_string_le(char[]o1, char[]o2)
   {
      return ((new String(o1)).compareTo(new String(o2)) <= 0);
   }

   public static boolean ucs2_string_ge(char[]o1, char[]o2)
   {
      return ((new String(o1)).compareTo(new String(o2)) >= 0);
   }

   public static boolean ucs2_string_cilt(char[]o1, char[]o2)
   {
     // !!!!! JDK 1.2:  return ((new String( o1 )).compareToIgnoreCase( new String( o2 ) ) < 0);
      return ((new String(o1)).toLowerCase().compareTo((new String(o2)).
	    toLowerCase()) < 0);
   }

   public static boolean ucs2_string_cigt(char[]o1, char[]o2)
   {
     // !!!!! JDK 1.2:  return ((new String( o1 )).compareToIgnoreCase( new String( o2 ) ) > 0);
      return ((new String(o1)).toLowerCase().compareTo((new String(o2)).
	    toLowerCase()) > 0);
   }

   public static boolean ucs2_string_cile(char[]o1, char[]o2)
   {
     // !!!!! JDK 1.2:  return ((new String( o1 )).compareTo( new String( o2 ) ) <= 0);
      return ((new String(o1)).toLowerCase().compareTo((new String(o2)).
	    toLowerCase()) <= 0);
   }

   public static boolean ucs2_string_cige(char[]o1, char[]o2)
   {
     // !!!!! JDK 1.2:  return ((new String( o1 )).compareToIgnoreCase( new String( o2 ) ) >= 0);
      return ((new String(o1)).toLowerCase().compareTo((new String(o2)).
	    toLowerCase()) >= 0);
   }

   public static char[] c_subucs2_string(char[]o, int min, int max)
   {
      return (new String(o)).substring(min, max).toCharArray();
   }

   public static char[] c_ucs2_string_copy(char[]o)
   {
      return (new String(o)).toCharArray();
   }

   public static char[] c_ucs2_string_append(char[]o1, char[]o2)
   {
      final char[] result = new char[o1.length + o2.length];

      System.arraycopy(o1, 0, result, 0, o1.length);
      System.arraycopy(o2, 0, result, o1.length, o2.length);

      return result;
   }

   public static byte[] ucs2_string_to_utf8_string(char[]o)
   {
      return ucs2_string_to_utf8_string(new String(o));
   }

   public static byte[] ucs2_string_to_utf8_string(String s)
   {
      try
      {
	 final ByteArrayOutputStream bout = new ByteArrayOutputStream();
	 final DataOutputStream out = new DataOutputStream(bout);

	 out.writeUTF(s);

	 final byte[] tmp = bout.toByteArray();
	 final byte[] result = new byte[tmp.length - 2];

	 System.arraycopy(tmp, 2, result, 0, result.length);
	 bout.close();

	 return result;
      }
      catch(Exception e)
      {
	 fail("ucs2_string_to_utf8_string", e.getMessage(), s);
	 return null;
      }
   }

   public static int utf8length(byte[]bytes, int nb)
   {
      int result = 0;
      int i = 0;

      for (; i < nb; ++result)
	{
	   final byte b = bytes[i];

	   if ((b & 0x80) == 0)
	      ++i;
	   else if ((b & 0x20) == 0)
	      i += 2;
	   else
	      i += 3;
	}

      if (i != nb)
	 throw new RuntimeException("Bad utf8 string : " + new String(bytes));

      return result;
   }

   public static char[] utf8_string_to_ucs2_string(byte[]bytes)
   {
      final int nb = bytes.length;
      final int nc = utf8length(bytes, nb);
      final char[] chars = new char[nc];
      int i = 0;

      for (int j = 0; j < nc; ++j)
	{
	   final byte b = bytes[i];

	   if ((b & 0x80) == 0)
	     {
		chars[j] = (char) b;
		++i;
	     }
	   else if ((b & 0x20) == 0)
	     {
		chars[j] = (char) (((b & 0x1F) << 6) | (bytes[i + 1] & 0x3F));
		i += 2;
	     }
	   else
	     {
		chars[j] = (char) (((b & 0x0F) << 12)
		   | ((bytes[i + 1] & 0x3F) << 6) | (bytes[i + 2] & 0x3F));
		i += 3;
	     }
	}

      return chars;
   }

  //////
  // PROCESS
  //////
   public static boolean PROCESSP(Object o)
   {
      return (o instanceof process);
   }

   public static process c_run_process(Object bhost,
      Object bfork,
      Object bwaiting,
      Object binput,
      Object boutput,
      Object berror,
      byte[]bcommand, Object bargs, Object benv) throws IOException
   {
      return new process(((bhost instanceof byte[])? (byte[])bhost : null),
			 // !!!! can't directly cast to byte[] ?????
	 bfork != bbool.faux,
	 bwaiting != bbool.faux,
	 binput, boutput, berror, bcommand, bargs, benv);
   }

   public static Object c_unregister_process(process o)
   {
      return bigloo.foreign.BUNSPEC;
   }

   public static int PROCESS_PID(process o)
   {
      return o.pid();
   }

   public static Object PROCESS_INPUT_PORT(process o)
   {
      return o.input_port;
   }

   public static Object PROCESS_OUTPUT_PORT(process o)
   {
      return o.output_port;
   }

   public static Object PROCESS_ERROR_PORT(process o)
   {
      return o.error_port;
   }

   public static boolean c_process_alivep(process o)
   {
      return o.alivep();
   }

   public static Object c_process_wait(process o)
   {
      o.waitfor();
      return bigloo.foreign.BUNSPEC;
   }

   public static Object c_process_xstatus(process o)
   {
      return o.xstatus();
   }

   public static Object c_process_send_signal(process o, int s)
   {
      return o.send_signal(s);
   }

   public static Object c_process_kill(process o)
   {
      return o.kill();
   }

   public static Object c_process_stop(process o)
   {
      return o.stop();
   }

   public static Object c_process_continue(process o)
   {
      return o.cont();
   }

   public static Object c_process_list()
   {
      return bigloo.process.process_list();
   }

  //////
  // STRING
  //////
  // Predicates
   public static boolean STRINGP(Object o)
   {
      return (o instanceof byte[]);
   }

  // Conversions
   public static byte[] string_to_bstring(byte[]o)
   {
      return o;
   }

   public static byte[] BSTRING_TO_STRING(byte[]o)
   {
      return o;
   }

   public static int strtol(byte[]s, int i, int radix)
   {
      final int len = s.length;

      return ((len == 0) ? 0 : parseint(s, i, len, radix));
   }

   public static long strtoll(byte[]s, int i, int radix)
   {
      final int len = s.length;

      return ((len == 0) ? 0 : parseint(s, i, len, radix));
   }

   public static byte[] integer_to_string(int n, int radix)
   {
     // CARE open this code to avoid triple allocation...
      return Integer.toString(n, radix).getBytes();
   }

   public static byte[] elong_to_string(long n, int radix)
   {
     // CARE open this code to avoid triple allocation...
      return Long.toString(n, radix).getBytes();
   }

   public static byte[] llong_to_string(long n, int radix)
   {
     // CARE open this code to avoid triple allocation...
      return Long.toString(n, radix).getBytes();
   }

   public static byte[] real_to_string(double n)
   {
      return Double.toString(n).getBytes();
   }

   public static double strtod(byte[]s, int i)
   {
     // !!!!! JDK 1.2:  return Double.parseDouble( new String( s, i, (s.length - i) ) );

      final int len = s.length;

      return ((len == 0)
	 ? 0 : Double.valueOf(new String(s, i, (len - i))).doubleValue());
   }

  // Open functions
   public static int STRING_REF(byte[]s, int i)
   {
      return (s[i] & 0xFF);
   }

   public static Object STRING_SET(byte[]s, int i, int cn)
   {
      s[i] = (byte) cn;
      return unspecified.unspecified;
   }

  // Lib functions
  // Des fois j'me demande un peu!!!!!...faut pas, faut pas...
   public static final Hashtable marked_string = new Hashtable();

   public static int STRING_LENGTH(byte[]s)
   {
      return s.length;
   }

   public static Object MARK_INTEXT_STRING(byte[]s)
   {
      marked_string.put(s, unspecified.unspecified);
      return unspecified.unspecified;
   }

   public static Object UNMARK_INTEXT_STRING(byte[]s)
   {
      marked_string.remove(s);
      return unspecified.unspecified;
   }

   public static Object MARK_INTEXT_UCS2_STRING(Object s)
   {
      marked_string.put(s, unspecified.unspecified);
      return unspecified.unspecified;
   }

   public static Object UNMARK_INTEXT_UCS2_STRING(Object s)
   {
      marked_string.remove(s);
      return unspecified.unspecified;
   }

   public static boolean INTEXT_STRING_MARKED_P(byte[]s)
   {
      return (marked_string.get(s) != null);
   }

   public static boolean INTEXT_UCS2_STRING_MARKED_P(Object s)
   {
      return (marked_string.get(s) != null);
   }

  // Creations
   public static byte[] make_string(int n, int init)
   {
      final byte[] r = new byte[n];
      final byte in = (byte) init;

      for (int i = 0; i < n; ++i)
	 r[i] = in;

      return r;
   }

   public static byte[] make_string_sans_fill(int n)
   {
      return new byte[n];
   }

   public static byte[] bgl_string_shrink(byte[]src, int len)
   {
      return c_substring(src, 0, len);
   }

   public static byte[] c_substring(byte[]src, int min, int max)
   {
      final int len = max - min;
      final byte[] result = new byte[len];

     // CARE Do a bench to find a better constant
      if (len < 4)
	 for (int i = 0; i < len; ++i)
	    result[i] = src[min + i];
      else
	 System.arraycopy(src, min, result, 0, len);

      return result;
   }

   public static Object ill_char_rep(int cn)
   {
      final byte[] r = new byte[5];

      r[0] = (byte) '#';
      r[1] = (byte) 'a';
      r[2] = (byte) (((byte) '0') + (cn / 100));
      r[3] = (byte) (((byte) '0') + ((cn / 10) % 10));
      r[4] = (byte) (((byte) '0') + (cn % 10));

      return r;
   }

   public static byte[] string_append(byte[]o1, byte[]o2)
   {
      final int n1 = o1.length;
      final int n2 = o2.length;
      final byte[] r = new byte[n1 + n2];

      System.arraycopy(o1, 0, r, 0, n1);
      System.arraycopy(o2, 0, r, n1, n2);

      return r;
   }

   public static byte[] string_append_3(byte[]o1, byte[]o2, byte[]o3)
   {
      final int n1 = o1.length;
      final int n2 = o2.length;
      final int n3 = o3.length;
      final byte[] r = new byte[n1 + n2 + n3];

      System.arraycopy(o1, 0, r, 0, n1);
      System.arraycopy(o2, 0, r, n1, n2);
      System.arraycopy(o3, 0, r, n1 + n2, n3);

      return r;
   }

   public static byte[] escape_C_string(byte[]src)
   {
     // on supprime un caractere de cette chaine car elle est rendue par le
     // lecteur comme etant `"tototo'. Ceci est du au fait qu'on utilise
     // la fonction `the-small-string' qui supprime le premier et le
     // dernier caractere de la chaine lue. Comme les chaines etrangeres
     // commencent par 2 caracteres, on en supprime 1 autre maintenant.

      final int len = src.length;
      int size = 0;

      for (int i = 1; i < len; ++i, ++size)
	 if (src[i] == '\\')
	   {
	      if ((i + 3 < len)
		 && isdigit(src[i + 1])
		 && isdigit(src[i + 2]) && isdigit(src[i + 3]))
		 i += 3;
	      else
		 i += 1;
	   }

      final byte[] result = new byte[size];
      int j = 0;

      for (int i = 1; i < len; ++i, ++j)
	{
	   if (src[i] != '\\')
	      result[j] = src[i];
	   else
	     {
		final byte cn = src[++i];

		switch (cn)
		  {
		  case (byte) '\0':
		     result[j] = (byte) '\\';
		     break;
		  case (byte) 'n':
		     result[j] = (byte) '\n';
		     break;
		  case (byte) 't':
		     result[j] = (byte) '\t';
		     break;
		  case (byte) 'b':
		     result[j] = (byte) '\b';
		     break;
		  case (byte) 'r':
		     result[j] = (byte) '\r';
		     break;
		  case (byte) 'f':
		     result[j] = (byte) '\f';
		     break;
		  case (byte) 'v':
		     result[j] = (byte) 11;
		     break;
		  default:
		     {
			if (i + 2 < len)
			  {
			     final byte s0 = src[i];
			     final byte s1 = src[i + 1];
			     final byte s2 = src[i + 2];

			     if (isdigit(s0) && isdigit(s1) && isdigit(s2))
			       {
				  result[j] = (byte) (64 * ((int) (s0 - '0'))
				     + 8 * ((int) (s1 - '0'))
				     + ((int) (s2 - '0')));
				  i += 2;
			       }
			     else
			       {
				  if (((s0 == (byte) 'x') || (s0 == (byte) 'X'))
				     && (isdigit(s1)
					|| (((byte) 'a' <= s1)
					   && (s1 <= (byte) 'f'))
					|| (((byte) 'A' <= s1)
					   && (s1 <= (byte) 'F')))
				     && (isdigit(s2) || (((byte) 'a' <= s2)
					   && (s2 <= (byte) 'f'))
					|| (((byte) 'A' <= s2)
					   && (s2 <= (byte) 'F'))))
				    {
				       final byte n1 = (byte) (isdigit(s1)
					  ? (s1 - (byte) '0')
					  : 10 + (((byte) 'a' <= s1)
					     ? (s1 - (byte) 'a')
					     : (s1 - (byte) 'A')));
				       final byte n2 = (byte) (isdigit(s2)
					  ? (s2 - (byte) '0')
					  : 10 + (((byte) 'a' <= s2)
					     ? (s2 - (byte) 'a')
					     : (s2 - (byte) 'A')));

				       result[j] = (byte) (n1 * 16 + n2);
				       i += 2;
				    }
				  else
				     result[j] = cn;
			       }
			  }
			else
			   result[j] = cn;
		     }
		     break;
		  }
	     }
	}

      return result;
   }

   static boolean isdigit(byte cn)
   {
      return (((byte) '0' <= cn) && (cn <= (byte) '9'));
   }

   public static byte[] escape_scheme_string(byte[]src)
   {
      final int len = src.length;
      int w = 0;

      for (int i = 0; i < len; ++i)
	{
	   ++w;
	   if (src[i] == (byte) '\\')
	      ++i;
	}

      final byte[] dst = new byte[w];

      w = 0;
      for (int i = 0; i < len; ++i)
	{
	   final byte cn = src[i];

	   if (cn != (byte) '\\')
	      dst[w++] = (byte) cn;
	   else
	     {
		++i;
		dst[w++] = ((src[i] == 'n') ? (byte) '\n' : src[i]);
	     }
	}

      return dst;
   }

   public static byte[] string_for_read(byte[]src)
   {
      return create_string_for_read(src, false);
   }

   public static byte[] create_string_for_read(byte[]src, boolean symbolp)
   {
      final int len = src.length;
      int w = 0;

      for (int i = 0; i < len; ++i)
	{
	   final byte cn = src[i];

	   switch (cn)
	     {
	     case (byte) '\n':
	     case (byte) '\t':
	     case (byte) '\b':
	     case (byte) '\r':
	     case (byte) '\f':
	     case (byte) 11:
	     case (byte) '"':
	     case (byte) '\\':
		w += 2;
		break;
	     case (byte) '|':
		w += (symbolp ? 2 : 1);
		break;
	     default:
		w += (((32 <= cn) && (cn <= 126)) ? 1 : 4);
		break;
	     }
	}

      final byte[] res = new byte[w];

      w = 0;
      for (int i = 0; i < len; ++i)
	{
	   final byte cn = src[i];

	   switch (cn)
	     {
	     case (byte) '\n':
		res[w++] = (byte) '\\';
		res[w++] = (byte) 'n';
		break;
	     case (byte) '\t':
		res[w++] = (byte) '\\';
		res[w++] = (byte) 't';
		break;
	     case (byte) '\b':
		res[w++] = (byte) '\\';
		res[w++] = (byte) 'b';
		break;
	     case (byte) '\r':
		res[w++] = (byte) '\\';
		res[w++] = (byte) 'r';
		break;
	     case (byte) '\f':
		res[w++] = (byte) '\\';
		res[w++] = (byte) 'f';
		break;
	     case (byte) 11:
		res[w++] = (byte) '\\';
		res[w++] = (byte) 'v';
		break;
	     case (byte) '"':
	     case (byte) '\\':
		res[w++] = (byte) '\\';
		res[w++] = cn;
		break;
	     case (byte) '|':
		if (symbolp)
		   res[w++] = (byte) '\\';
		res[w++] = (byte) '|';
		break;
	     default:
		if ((32 <= cn) && (cn <= 126))
		   res[w++] = cn;
		else
		  {
		     final int icn = cn & 0xFF;

		     res[w++] = (byte) '\\';
		     res[w++] = (byte) ('0' + ((icn >> 6) & 0x7));
		     res[w++] = (byte) ('0' + ((icn >> 3) & 0x7));
		     res[w++] = (byte) ('0' + (icn & 0x7));
		  }
		break;
	     }
	}

      return res;
   }

  // Side effects
   public static Object blit_string(byte[]src, int i1, byte[]dst, int i2, int n)
   {
      System.arraycopy(src, i1, dst, i2, n);
      return unspecified.unspecified;
   }

  // Comparisons
   public static boolean bigloo_strcmp(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;

      if (n1 != n2)
	 return false;

      for (int i = 0; i < n1; ++i)
	 if (s1[i] != s2[i])
	    return false;

      return true;
   }

   public static boolean bigloo_strncmp(byte[]s1, byte[]s2, int l)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;

      if ((n1 >= l) && (n2 >= l))
	{
	   for (int i = 0; i < l; ++i)
	      if (s1[i] != s2[i])
		 return false;
	   return true;
	}
      else
	 return false;
   }

   public static boolean bigloo_strncmp_ci(byte[]s1, byte[]s2, int l)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;

      if ((n1 >= l) && (n2 >= l))
	{
	   for (int i = 0; i < l; ++i)
	      if (toupper(s1[i]) != toupper(s2[i]))
		 return false;
	   return true;
	}
      else
	 return false;
   }

   public static boolean strcicmp(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;

      if (n1 != n2)
	 return false;
      for (int i = 0; i < n1; ++i)
	 if (toupper(s1[i]) != toupper(s2[i]))
	    return false;
      return true;
   }

   public static boolean string_le(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;
      final int min = (n1 < n2) ? n1 : n2;

      for (int i = 0; i < min; ++i)
	{
	   final int c1 = s1[i] & 0xFF;
	   final int c2 = s2[i] & 0xFF;

	   if (c1 != c2)
	      return (c1 <= c2);
	}

      return (n1 <= n2);
   }

   public static boolean string_lt(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;
      final int min = (n1 < n2) ? n1 : n2;

      for (int i = 0; i < min; ++i)
	{
	   final int c1 = s1[i] & 0xFF;
	   final int c2 = s2[i] & 0xFF;

	   if (c1 != c2)
	      return (c1 < c2);
	}

      return (n1 < n2);
   }

   public static boolean string_gt(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;
      final int min = (n1 < n2) ? n1 : n2;

      for (int i = 0; i < min; ++i)
	{
	   final int c1 = s1[i] & 0xFF;
	   final int c2 = s2[i] & 0xFF;

	   if (c1 != c2)
	      return (c1 > c2);
	}

      return (n1 > n2);
   }

   public static boolean string_ge(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;
      final int min = (n1 < n2) ? n1 : n2;

      for (int i = 0; i < min; ++i)
	{
	   final int c1 = s1[i] & 0xFF;
	   final int c2 = s2[i] & 0xFF;

	   if (c1 != c2)
	      return (c1 >= c2);
	}

      return (n1 >= n2);
   }

   public static boolean string_cilt(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;
      final int min = (n1 < n2) ? n1 : n2;

      for (int i = 0; i < min; ++i)
	{
	   final int c1 = toupper(s1[i] & 0xFF);
	   final int c2 = toupper(s2[i] & 0xFF);

	   if (c1 != c2)
	      return (c1 < c2);
	}

      return (n1 < n2);
   }

   public static boolean string_cile(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;
      final int min = (n1 < n2) ? n1 : n2;

      for (int i = 0; i < min; ++i)
	{
	   final int c1 = toupper(s1[i] & 0xFF);
	   final int c2 = toupper(s2[i] & 0xFF);

	   if (c1 != c2)
	      return (c1 <= c2);
	}

      return (n1 <= n2);
   }

   public static boolean string_cigt(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;
      final int min = (n1 < n2) ? n1 : n2;

      for (int i = 0; i < min; ++i)
	{
	   final int c1 = toupper(s1[i] & 0xFF);
	   final int c2 = toupper(s2[i] & 0xFF);

	   if (c1 != c2)
	      return (c1 > c2);
	}

      return (n1 > n2);
   }

   public static boolean string_cige(byte[]s1, byte[]s2)
   {
      final int n1 = s1.length;
      final int n2 = s2.length;
      final int min = (n1 < n2) ? n1 : n2;

      for (int i = 0; i < min; ++i)
	{
	   final int c1 = toupper(s1[i] & 0xFF);
	   final int c2 = toupper(s2[i] & 0xFF);

	   if (c1 != c2)
	      return (c1 >= c2);
	}

      return (n1 >= n2);
   }

  //////
  // KEYWORD
  //////
  // Predicates
   public static boolean KEYWORDP(Object o)
   {
      return (o instanceof keyword);
   }

  // Open functions
   public static byte[] KEYWORD_TO_STRING(keyword key)
   {
      return key.string;
   }

  // Lib functions
   public static keyword string_to_keyword(byte[]s)
   {
      return keyword.make_keyword(s);
   }

  //////
  // SYMBOL
  //////
  // Predicates
   public static boolean SYMBOLP(Object o)
   {
      return (o instanceof symbol);
   }

  // Lib functions
   public static boolean symbol_exists_p(byte[]name)
   {
      return symbol.exists(name);
   }

   public static symbol string_to_symbol(byte[]name)
   {
      return symbol.make_symbol(name);
   }

   public static byte[] SYMBOL_TO_STRING(symbol o)
   {
     // CARE why not a correct signature in Scheme
      return o.string;
   }

   public static Object GET_SYMBOL_PLIST(symbol o)
   {
      return o.cval;
   }

   public static Object SET_SYMBOL_PLIST(symbol o, Object v)
   {
      o.cval = v;
      return unspecified.unspecified;
   }

   public static Object GET_KEYWORD_PLIST(keyword o)
   {
      return o.cval;
   }

   public static Object SET_KEYWORD_PLIST(keyword o, Object v)
   {
      o.cval = v;
      return unspecified.unspecified;
   }

  //////
  // CELL
  //////
  // Predicates
   public static boolean CELLP(Object o)
   {
      return (o instanceof cell);
   }

  // Open functions
   public static cell MAKE_CELL(Object o)
   {
      return new cell(o);
   }

   public static Object CELL_SET(cell o, Object v)
   {
      o.car = v;
      return unspecified.unspecified;
   }

   public static Object CELL_REF(cell o)
   {
      return o.car;
   }

   public static Object _EVMEANING_ADDRESS(Object o)
   {
     // CARE Where is declared this function !!
      return new cell(o);
   }

   public static Object _EVMEANING_ADDRESS_REF(Object o)
   {
      return ((cell) o).car;
   }

   public static Object _EVMEANING_ADDRESS_SET(Object o, Object v)
   {
      ((cell) o).car = v;
      return unspecified.unspecified;
   }

  //////
  // FOREIGN
  //////
   public static boolean FOREIGNP(Object o)
   {
      return (!(o instanceof obj) && !(o instanceof object));
   }

   public static boolean FOREIGN_NULLP(Object f)
   {
      return (f == null);
   }

   public static boolean OBJECT_PTR_NULL(Object o)
   {
      return (o == null);
   }

   public static boolean STRING_PTR_NULL(byte[] o)
   {
      return (o == null);
   }

   public static boolean FOREIGN_EQP(Object f1, Object f2)
   {
      return (f1 == f2);
   }

   public static symbol FOREIGN_ID(Object f)
   {
     // CARE where defined?
      if( f == null ) {
	 return string_to_symbol("null".getBytes());
      } else {
	 return string_to_symbol(f.getClass().getName().getBytes());
      }
   }

   public static cobj FOREIGN_TO_COBJ(Object f)
   {
      return (cobj) f;
   }

   public static cobj obj_to_cobj(Object o)
   {
      return (cobj) o;
   }

   public static Object COBJ_TO_OBJ(cobj o)
   {
      return o;
   }

  //////
  // CUSTOM
  //////
   public static boolean CUSTOMP(Object o)
   {
      return (o instanceof custom);
   }

   public static boolean CUSTOM_CMP(custom c1, custom c2)
   {
      return c1.equal(c2);
   }

   public static int CUSTOM_HASH_NUMBER(custom c)
   {
      return c.hash();
   }

   public static byte[] CUSTOM_IDENTIFIER(custom c)
   {
      return c.identifier;
   }

   public static Object CUSTOM_IDENTIFIER_SET(custom c, byte[] s)
   {
      c.identifier = s;
      return unspecified.unspecified;
   }

  //////
  // DATE
  //////
   public static boolean DATEP(Object o)
   {
      return (o instanceof bigloo.date);
   }

   public static date bgl_make_date(int s,
      int min, int h, int d, int mon, int y, int tz, int dst )
   {
      return new bigloo.date(s, min, h, d, mon - 1, y, tz, dst);
   }

   public static date bgl_seconds_to_date(long sec)
   {
      return new bigloo.date(sec);
   }

   public static date bgl_seconds_to_utc_date(long sec)
   {
      date d = new bigloo.date(sec);
      d.calendar.setTimeZone(new SimpleTimeZone(0, "UTC"));
      return d;
   }

   public static long bgl_current_seconds()
   {
      return (new Date().getTime() / 1000);
   }

   public static long bgl_date_to_seconds(date d)
   {
      return (d.calendar.getTime().getTime() / 1000);
   }

   public static byte[] bgl_seconds_to_string(long sec)
   {
      return bgl_seconds_to_date(sec).calendar.getTime().toString().getBytes();
   }

   public static long bgl_integer_to_seconds(int i)
   {
      return i;
   }

   public static byte[] bgl_seconds_to_utc_string(long sec)
   {
      return bgl_seconds_to_utc_date(sec).calendar.getTime().toString().getBytes();
   }

   public static boolean secondEQ(long s1, long s2)
   {
      return (s1 == s2);
   }

   public static boolean secondLT(long s1, long s2)
   {
      return (s1 < s2);
   }

   public static boolean secondLE(long s1, long s2)
   {
      return s1 <= s2;
   }

   public static boolean secondGT(long s1, long s2)
   {
      return (s1 > s2);
   }

   public static boolean secondGE(long s1, long s2)
   {
      return (s1 >= s2);
   }

   public static long secondADD(long s1, long s2)
   {
      return (s1 + s2);
   }

   public static long secondMUL(long s1, long s2)
   {
      return (s1 * s2);
   }

   public static long secondSUB(long s1, long s2)
   {
      return (s1 - s2);
   }

   public static int BGL_DATE_SECOND(date d)
   {
      return d.calendar.get(Calendar.SECOND);
   }

   public static int BGL_DATE_MINUTE(date d)
   {
      return d.calendar.get(Calendar.MINUTE);
   }

   public static int BGL_DATE_HOUR(date d)
   {
      return d.calendar.get(Calendar.HOUR_OF_DAY);
   }

   public static int BGL_DATE_DAY(date d)
   {
      return d.calendar.get(Calendar.DAY_OF_MONTH);
   }

   public static int BGL_DATE_WDAY(date d)
   {
      return d.calendar.get(Calendar.DAY_OF_WEEK);
   }

   public static int BGL_DATE_YDAY(date d)
   {
      return d.calendar.get(Calendar.DAY_OF_YEAR);
   }

   public static int BGL_DATE_MONTH(date d)
   {
      return (d.calendar.get(Calendar.MONTH) + 1);
   }

   public static int BGL_DATE_YEAR(date d)
   {
      return d.calendar.get(Calendar.YEAR);
   }

   public static int BGL_DATE_TIMEZONE(date d)
   {
      return d.timezone;
   }

   public static int BGL_DATE_ISDST(date d)
   {
      return ( d.calendar.get(Calendar.DST_OFFSET) > 0 ) ? 1 : -1;
   }

   private static final byte[][] day_names = { "Sunday".getBytes(),
      "Monday".getBytes(),
      "Tuesday".getBytes(),
      "Wednesday".getBytes(),
      "Thursday".getBytes(),
      "Friday".getBytes(),
      "Saturday".getBytes()
   };

   private static final byte[][] day_anames = { "Sun".getBytes(),
      "Mon".getBytes(),
      "Tue".getBytes(),
      "Wed".getBytes(),
      "Thu".getBytes(),
      "Fri".getBytes(),
      "Sat".getBytes()
   };

   private static final byte[][] month_names = { "January".getBytes(),
      "February".getBytes(),
      "March".getBytes(),
      "April".getBytes(),
      "May".getBytes(),
      "June".getBytes(),
      "July".getBytes(),
      "August".getBytes(),
      "September".getBytes(),
      "October".getBytes(),
      "November".getBytes(),
      "December".getBytes()
   };

   private static final byte[][] month_anames = { "Jan".getBytes(),
      "Feb".getBytes(),
      "Mar".getBytes(),
      "Apr".getBytes(),
      "May".getBytes(),
      "Jun".getBytes(),
      "Jul".getBytes(),
      "Aug".getBytes(),
      "Sep".getBytes(),
      "Oct".getBytes(),
      "Nov".getBytes(),
      "Dec".getBytes()
   };

   public static byte[] bgl_day_name(int n)
   {
      return day_names[n - 1];
   }

   public static byte[] bgl_day_aname(int n)
   {
      return day_anames[n - 1];
   }

   public static byte[] bgl_month_name(int n)
   {
      return month_names[n - 1];
   }

   public static byte[] bgl_month_aname(int n)
   {
      return month_anames[n - 1];
   }

  //////
  // PAIR
  //////
  // Predicates
   public static boolean PAIRP(Object o)
   {
      return (o instanceof pair);
   }

  // Open functions
   public static pair MAKE_PAIR(Object car, Object cdr)
   {
     // CARE where defined?
      return new pair(car, cdr);
   }

   public static Object CAR(pair c)
   {
      return c.car;
   }

   public static Object CDR(pair c)
   {
      return c.cdr;
   }

   public static Object SET_CAR(pair c, Object o)
   {
      c.car = o;
      return unspecified.unspecified;
   }

   public static Object SET_CDR(pair c, Object o)
   {
      c.cdr = o;
      return unspecified.unspecified;
   }

  //////
  // EXTENDED_PAIR
  //////
   public static boolean EXTENDED_PAIRP(Object o)
   {
      return (o instanceof extended_pair);
   }

   public static extended_pair MAKE_EXTENDED_PAIR(Object car,
      Object cdr, Object cer)
   {
      return new extended_pair(car, cdr, cer);
   }

   public static Object CER(extended_pair c)
   {
      return c.cer;
   }

   public static Object SET_CER(extended_pair c, Object o)
   {
      c.cer = o;
      return unspecified.unspecified;
   }

  //////
  // VECTOR
  //////
  // Predicates
   public static boolean VECTORP(Object o)
   {
      return (o instanceof Object[]);
   }

  // Open functions
   public static int VECTOR_LENGTH(Object[]v)
   {
      return v.length;
   }

   public static Object VECTOR_REF(Object[]v, int i)
   {
      return v[i];
   }

   public static Object VECTOR_SET(Object[]v, int i, Object o)
   {
      v[i] = o;
      return unspecified.unspecified;
   }

   public static boolean BOUND_CHECK(int n1, int n2)
   {
      return (n1 < n2);
   }

   public static Object VECTOR_TAG_SET(Object[]v, int n)
   {
      return unspecified.unspecified;
   }

   public static int VECTOR_TAG(Object[]v)
   {
      return 0;
   }

  // Lib functions
   public static Object[] make_vector(int n, Object init)
   {
      final Object[] r = new Object[n];

      for (int i = 0; i < n; ++i)
	 r[i] = init;

      return r;
   }

   public static Object[] create_vector(int n)
   {
      return new Object[n];
   }

   public static Object fill_vector(Object[]v, int len, Object o)
   {
      for (int i = 0; i < len; ++i)
	 v[i] = o;
      return unspecified.unspecified;
   }

   public static Object[] sort_vector(Object[]v, procedure p)
   {
      final int n = v.length;

      for (int incr = n / 2; incr != 0; incr /= 2)
	 for (int i = incr; i < n; ++i)
	    for (int j = i - incr; j >= 0; j -= incr)
	       if (p.funcall2(v[j], v[j + incr]) != bbool.faux)
		  break;
	       else
		 {
		    final Object tmp = v[j + incr];

		    v[j + incr] = v[j];
		    v[j] = tmp;
		 }

      return v;
   }

  //////
  // TVECTOR
  //////
   public static boolean TVECTORP(Object o)
   {
      return ((o instanceof double[])
	 ||(o instanceof int[])
	 ||(o instanceof long[]) ||(o instanceof Object[]));
   }

   private static final Object[] desc_table = new Object[4];

   public static Object TVECTOR_DESCR(Object o)
   {
      if (o instanceof double[])
	 return desc_table[0];
      if (o instanceof int[])
	 return desc_table[1];
      if (o instanceof long[])
	 return desc_table[2];
      if (o instanceof Object[])
	 return desc_table[3];
      return fail("tvector_desc", "Unknown tvec object", o);
   }

   public static Object TVECTOR_DESCR_SET(Object o, Object desc)
   {
      if (o instanceof double[])
	 desc_table[0] = desc;
      else if (o instanceof int[])
	 desc_table[1] = desc;
      else if (o instanceof long[])
	 desc_table[2] = desc;
      else if (o instanceof Object[])
	 desc_table[3] = desc;

      return unspecified.unspecified;
   }

   public static int TVECTOR_LENGTH(Object o)
   {
      if (o instanceof double[])
	 return ((double[]) o).length;
      if (o instanceof int[])
	 return ((int[]) o).length;
      if (o instanceof long[])
	 return ((long[]) o).length;
      if (o instanceof Object[])
	 return ((Object[])o).length;

      fail("tvector_length", "Unknown tvec object", o);
      return 0;
   }

  //////
  // STRUCT
  //////
   public static boolean STRUCTP(Object o)
   {
      return (o instanceof struct);
   }

   public static Object STRUCT_KEY(struct o)
   {
      return o.key;
   }

   public static Object STRUCT_KEY_SET(struct o, Object v)
   {
      o.key = v;
      return unspecified.unspecified;
   }

   public static int STRUCT_LENGTH(struct o)
   {
      return o.values.length;
   }

   public static Object STRUCT_REF(struct o, int i)
   {
      return o.values[i];
   }

   public static Object STRUCT_SET(struct o, int i, Object v)
   {
      o.values[i] = v;
      return unspecified.unspecified;
   }

   public static Object UNSAFE_STRUCT_REF(struct o, int i)
   {
      return o.values[i];
   }

   public static Object UNSAFE_STRUCT_SET(struct o, int i, Object v)
   {
      o.values[i] = v;
      return unspecified.unspecified;
   }

   public static struct create_struct (symbol key, int size)
   {
      return new struct (key, size);
   }

   public static struct make_struct (symbol key, int size, Object o)
   {
      return new struct (key, size, o);
   }

  /////
  // OBJECT
  /////

   public static int OBJECT_TYPE = 0;

   public static Object BGL_OBJECT_WIDENING_SET(object o, Object v)
   {
      o.widening = v;
      return unspecified.unspecified;
   }

   public static Object BGL_OBJECT_WIDENING(object o)
   {
      return o.widening;
   }

   public static int BGL_OBJECT_CLASS_NUM(object o)
   {
      return o.header;
   }

   public static Object BGL_OBJECT_CLASS_NUM_SET(object o, int n)
   {
      o.header = n;
      return unspecified.unspecified;
   }

   public static Object BGL_HEAP_DEBUG_MARK_OBJ(Object o)
   {
      return o;
   }

  //////
  // PROCEDURE
  //////
   public static boolean PROCEDUREP(Object o)
   {
      return (o instanceof procedure);
   }

   public static procedure buildproc(procedure p, int i, int a, int n)
   {
      p.index = i;
      p.arity = a;
      p.env = new Object[n];
      return p;
   }

   public static int PROCEDURE_ARITY(procedure p)
   {
      return p.arity;
   }

   public static boolean PROCEDURE_CORRECT_ARITYP(procedure p, int i)
   {
      final int arity = p.arity;

      return ((arity == i) || ((arity < 0) && (-i - 1 <= arity)));
   }

   public static Object PROCEDURE_SET(procedure p, int i, Object o)
   {
      p.env[i] = o;
      return unspecified.unspecified;
   }

   public static Object PROCEDURE_REF(procedure p, int i)
   {
      return p.env[i];
   }

   public static procedure MAKE_EL_PROCEDURE(int n)
   {
      return new procedure(0, 0, new Object[n]);
   }

   public static Object PROCEDURE_EL_SET(procedure p, int i, Object o)
   {
      p.env[i] = o;
      return unspecified.unspecified;
   }

   public static Object PROCEDURE_EL_REF(procedure p, int i)
   {
      return p.env[i];
   }

   public static procedure MAKE_EL_PROCEDURE_1(int n)
   {
      return new procedure(0, 0, new Object[n]);
   }

   public static Object PROCEDURE_1_EL_SET(procedure p, int i, Object o)
   {
      p.env[i] = o;
      return unspecified.unspecified;
   }

   public static Object PROCEDURE_1_EL_REF(procedure p, int i)
   {
      return p.env[i];
   }

   public static Object PROCEDURE_L_REF(procedure p, int i)
   {
      return p.env[i];
   }

   public static Object PROCEDURE_L_SET(procedure p, int i, Object o)
   {
      p.env[i] = o;
      return unspecified.unspecified;
   }

  // CARE ?!?!
   public static Object PUSH_BEFORE(procedure p)
   {
      return null;
   }

   public static Object POP_BEFORE()
   {
      return null;
   }

  //////
  // EXCEPTIONS and ERRORS
  //////
   public static Object GET_ERROR_HANDLER()
   {
      return bgldynamic.current_dynamic_env.error_handler;
   }

   public static void SET_ERROR_HANDLER(Object hdl)
   {
      bgldynamic.current_dynamic_env.error_handler = hdl;
   }

   // Name after the equivalent C function. Its only purpose is to
   // give the JVM based debuggers a chance to stop the execution
   // after an error.
   private static void bigloo_abort() {
      ;
   }
   
   public static RuntimeException fail(Object proc, Object msg, Object env)
   {
      bigloo.runtime.Llib.error.the_failure(proc, msg, env);

      final RuntimeException e = new RuntimeException("bigloo error...");
      final stackwriter sw = new stackwriter(System.err, true);

      e.printStackTrace(sw);
      sw.flush();

      bigloo_abort();
      
      final Object v = bigloo.runtime.Llib.bigloo.bigloo_exit_apply(BINT(1));

      if (v instanceof bint)
	 System.exit(CINT((bint) v));
      else
	 System.exit(1);

      return e;
   }

   public static void internalerror(Throwable e)
      throws Throwable
   {
      final stackwriter sw = new stackwriter(System.err, true);

      System.err.println("Internal error...");
      e.printStackTrace(sw);
      sw.flush();

      bigloo_abort();

      System.exit(1);
   }

   public static final byte[] nomsg = "null".getBytes();

   public static RuntimeException fail(String proc, String msg, Object env)
   {
      return fail(proc.getBytes(), (msg == null) ? nomsg : msg.getBytes(), env);
   }

   public static void exit(int n)
   {
      System.exit(n);
   }

   public static Object BGL_EXITD_TOP()
   {
      return bgldynamic.current_dynamic_env.exitd_top;
   }

   public static Object BGL_EXITD_TOP_SET(Object o)
   {
     //print("** setexit " + o);
      bgldynamic.current_dynamic_env.exitd_top = o;
      return unspecified.unspecified;
   }

   public static Object setexit()
   {
      return new exit();
   }

   public static exit EXITD_TO_EXIT(Object o)
   {
     //print("** self " + o);
      return (exit) o;
   }

   public static boolean EXITD_USERP(Object o)
   {
     //print("** userp " + o);
      return ((exit) o).userp;
   }

   public static bint EXITD_STAMP(Object o)
   {
     //print("** stamp " + o);
      return bint.BZERO;
   }

   public static Object jumpexit(Object excep, Object value)
   {
     //print("** jump " + excep + " " + value);
      throw new bexception(excep, value);
   }

   public static int BGL_MVALUES_NUMBER()
   {
      return bgldynamic.current_dynamic_env.mvalues_number;
   }

   public static int BGL_MVALUES_NUMBER_SET(int n)
   {
      bgldynamic.current_dynamic_env.mvalues_number = n;
      return n;
   }

   public static Object BGL_MVALUES_VAL(int n)
   {
      return bgldynamic.current_dynamic_env.mvalues_values[n];
   }

   public static Object BGL_MVALUES_VAL_SET(int n, Object o)
   {
      bgldynamic.current_dynamic_env.mvalues_values[n] = o;
      return unspecified.unspecified;
   }

   public static Object debug_handler(bexception v, exit tag)
   {
      if (!tag.userp)
	{
	  //print("** PROTECT " + v + " " + tag);
	   return v.value;
	}
      if (v.tag == tag)
	{
	  //print("** TAG reached " + v + " " + tag);
	   return v.value;
	}
     //print("** TAG forward " + v + " " + tag);
      throw v;
   }

   public static Object PUSH_EXIT(exit v, boolean protect)
   {
     //print("** PUSH " + v + " " + protect);
      v.userp = protect;
      v.prev = (exit) bgldynamic.current_dynamic_env.exitd_top;
      bgldynamic.current_dynamic_env.exitd_top = v;
      return unspecified.unspecified;
   }

   public static Object POP_EXIT()
   {
     //print("** POP " + EXIT_TOP + " -> " + ((EXIT)EXIT_TOP).prev);
      bgldynamic.current_dynamic_env.exitd_top =
	 ((exit) bgldynamic.current_dynamic_env.exitd_top).prev;
      return unspecified.unspecified;
   }

   public static Object call_cc(procedure p)
   {
      final exit saved = (exit) bgldynamic.current_dynamic_env.exitd_top;
      final exit me = (exit) setexit();
      Object r;

      PUSH_EXIT(me, true);

      try
      {
	 if (PROCEDURE_CORRECT_ARITYP(p, 1))
	   {
	      r = p.funcall1(new callcc());
	      bgldynamic.current_dynamic_env.exitd_top = saved;
	   }
	 else
	   {
	      r = null;
	      fail("call/cc", "Wrong arity", p);
	   }
      }
      catch(bexception x)
      {
	 r = debug_handler(x, me);
	 bgldynamic.current_dynamic_env.exitd_top = saved;
      }

      return r;
   }

  //////
  // EVAL
  //////
  // CARE
   public static final procedure BIGLOO_EXIT_ENV = new procedure();

   public static Object PUSH_TRACE(Object o)
   {
      new stack_trace(o);
      return unspecified.unspecified;
   }

   public static Object POP_TRACE()
   {
      return stack_trace.pop_trace();
   }

   public static Object dump_trace_stack(output_port p,
      int depth) throws IOException
   {
      return stack_trace.dump(p, depth);
   }

   public static Object __EVMEANING_ADDRESS_REF(procedure f)
   {
      return f.funcall0();
   }

   public static Object __EVMEANING_ADDRESS_SET(procedure f, Object v)
   {
      f.funcall1(v);
      return unspecified.unspecified;
   }

   public static Object eval_funcall_0(procedure fun)
   {
      return fun.funcall0();
   }

   public static Object eval_funcall_1(procedure fun, Object a0)
   {
      return fun.funcall1(a0);
   }

   public static Object eval_funcall_2(procedure fun, Object a0, Object a1)
   {
      return fun.funcall2(a0, a1);
   }

   public static Object eval_funcall_3(procedure fun,
      Object a0, Object a1, Object a2)
   {
      return fun.funcall3(a0, a1, a2);
   }

   public static Object eval_funcall_4(procedure fun,
      Object a0, Object a1, Object a2, Object a3)
   {
      return fun.funcall4(a0, a1, a2, a3);
   }

   public static Object eval_apply(procedure fun, Object list)
   {
      return fun.apply(list);
   }

  //////
  // FILES
  ////

   public static boolean unlink(byte[]file)
   {
      return !(new File(new String(file)).delete());
   }

   public static boolean rmdir(byte[]file)
   {
      return !(new File(new String(file)).delete());
   }

   public static boolean fexists(byte[]file)
   {
      return (new File(new String(file)).exists());
   }

   public static int rename(byte[]old, byte[]to)
   {
      return ((new File(new String(old))).
	 renameTo(new File(new String(to))) ? 0 : 69);
   }

   public static boolean mkdir(byte[]path, int mode)
   {
      return (new File(new String(path))).mkdir();
   }

   public static boolean directoryp(byte[]file)
   {
      return (new File(new String(file))).isDirectory();
   }

   public static int bgl_file_size(byte[]file)
   {
      return (int) (new File(new String(file))).length();
   }

   public static long bgl_last_modification_time(byte[]file)
   {
      return (long) (new File(new String(file))).lastModified();
   }

   public static Object directory_to_list(byte[]name)
   {
      final String[] files = (new File(new String(name))).list();
      Object result = BNIL;

      if (files != null)
	{
	   final int file_count = files.length;

	   for (int i = 0; i < file_count; ++i)
	      result = new pair(files[file_count - i - 1].getBytes(), result);
	}

      return result;
   }

  //////
  // SYSTEM and OS
  //////
   public static final int PTR_ALIGNMENT = 2;
   public static final int SIGINT = 3;
   public static final int SIGILL = 4;
   public static final int SIGFPE = 8;
   public static final int SIGBUS = 7;
   public static final int SIGSEGV = 11;

   public static int sigsetmask(int n)
   {
      return n;
   }

   public static Object c_signal(int n, procedure p)
   {
      return unspecified.unspecified;
   }

   public static Object get_signal_handler(int n)
   {
      return BFALSE;
   }

   public static Object reset_console(Object o)
   {
      return unspecified.unspecified;
   }

   static byte[] get_property(String name, String def)
   {
     // !!!!! JDK 1.1: System.getProperty( name, def ) ?????
      final Properties p = System.getProperties();
      final String s = p.getProperty(name);

      if (s == null)
	 if (def == null)
	    return null;
	 else
	    return def.getBytes();
      else
	 return s.getBytes();
   }

   public static byte[] getenv(byte[]name)
   {
      final String sname = new String(name);

      if (sname.equals("HOME") || sname.equals("USERPROFILE") )
	 return get_property("user.home", null);
      if (sname.equals("USER"))
	 return get_property("user.name", null);
      if (sname.equals("CLASSPATH"))
	 return get_property("java.library.path", null);
      if (sname.equals("TMPDIR"))
	 return get_property("java.io.tmpdir", null);
      if (sname.equals("BIGLOOSTACKDEPTH") || sname.equals("BIGLOOLIVEPROCESS"))
	 return get_property("bigloo." + new String(name), "0");
      return get_property("bigloo." + new String(name), null);
   }

   public static boolean getenv_exists(byte[]name)
   {
      final String sname = new String(name);

      return (sname.equals("HOME")
	      || sname.equals("USERPROFILE")
	      || sname.equals("USER")
	      || sname.equals("CLASSPATH")
	      || sname.equals("TMPDIR")
	      || sname.equals("BIGLOOSTACKDEPTH")
	      || sname.equals("BIGLOOLIVEPROCESS")
	      || (get_property("bigloo." + sname, null) != null));
   }

   public static int bgl_setenv(byte[]name, byte[]val)
   {
     // !!!!! Disparu après JDK 1.1 selon Manuel ?????
      return 0;
   }

   public static byte[] getcwd(byte[]path, int i)
   {
      return get_property("user.dir", ".");
   }

   public static boolean bgl_chmod(byte[]f, boolean r, boolean w, boolean x)
      throws IOException
   {
      if (java.util.Arrays.equals(bigloo.os.OS_CLASS, "unix".getBytes()))
	{
	   final StringBuffer cmd = new StringBuffer("chmod a");

	                cmd.append(r ? "+r " : "-r ");
	                cmd.append(w ? "+w " : "-w ");
	                cmd.append(x ? "+x " : "-x ");

	                cmd.append(f);

	   final Process process = Runtime.getRuntime().exec(cmd.toString());

	           try
	   {
	      process.waitFor();
	   }
	   catch  (InterruptedException _)
	   {
	   }

	   return (process.exitValue() == 0);
	}
      else
	 return false;
   }

   public static boolean bgl_chmod(byte[]f, int v)
      throws IOException
   {
      if (java.util.Arrays.equals(bigloo.os.OS_CLASS, "unix".getBytes()))
	{
	   final String cmd = "chmod " + Integer.toString(v, 8) + " ";
	   final Process process =
	      Runtime.getRuntime().exec(cmd + new String(f));

	           try
	   {
	      process.waitFor();
	   }
	   catch  (InterruptedException _)
	   {
	   }

	   return (process.exitValue() == 0);
	}
      else
	 return false;
   }

   public static boolean chdir(byte[]path)
   {
      final Properties p = System.getProperties();

      System.out.println("***WARNING: JVM chdir is not implemented yet");	// !!!!! ?????

     // !!!!! JDK 1.2:  System.setProperty( "user.dir", new String( path ) );
      p.put("user.dir", new String(path));
      return false;
   }

   public static Object command_line = BNIL;

   public static final byte[] executable_name= bigloo.os.BGL_DEFAULT_A_OUT;

   public static int system(byte[]cmd)
      throws IOException, InterruptedException
   {
      final process p = new process(null, false, true, null,
				    bigloo.foreign.BUNSPEC,
				    bigloo.foreign.BUNSPEC,
				    cmd, null, null);
	  
      return ((p.xstatus()instanceof bint) ? ((bint) p.xstatus()).value : -1);
   }

   public static byte[] c_date()
   {
      return (new Date()).toString().getBytes();
   }

   public static Object BIGLOO_EXIT(Object n)
   {
      final Object exitv = bigloo.runtime.Llib.bigloo.bigloo_exit_apply(n);

      trace_exit();
      System.exit((exitv instanceof bint) ? ((bint) exitv).value : 0);

      return null;
   }

   public static final byte[] BGL_DYNAMIC_LOAD_INIT =
      "BGL_DYNAMIC_LOAD_INIT".getBytes();

   public static int bgl_dload(byte[]filename, byte[]init_sym)
   {
      return bigloo.dlopen.dload(filename, init_sym);
   }

   public static byte[] bgl_dload_error()
   {
      return bigloo.dlopen.dload_error();
   }

  //////
  // SOCKET
  //////
   public static boolean SOCKETP(Object o)
   {
      return (o instanceof socket);
   }

   public static boolean SOCKET_SERVERP(Object o)
   {
      return (o instanceof server_socket);
   }

   public static boolean SOCKET_CLIENTP(Object o)
   {
      return (o instanceof client_socket);
   }

   public static socket socket_dup(socket s)
   {
      return s.socket_dup();
   }

   public static socket make_client_socket(byte[]hostname, int port, boolean b)
   {
      return new client_socket(hostname, port, b);
   }

   public static socket make_server_socket(int port)
   {
      return new server_socket(port);
   }

   public static Object SOCKET_HOSTNAME(socket s)
   {
      return s.HOSTNAME();
   }

   public static Object SOCKET_HOSTIP(socket s)
   {
      return s.HOSTIP();
   }

   public static boolean SOCKET_DOWNP(socket s)
   {
      return s.DOWNP();
   }

   public static int SOCKET_PORT(socket s)
   {
      return s.PORT();
   }

   public static Object SOCKET_INPUT(socket s)
   {
      return s.input;
   }

   public static Object SOCKET_OUTPUT(socket s)
   {
      return s.output;
   }

   public static Object socket_accept_connection(socket s, boolean b)
      throws IOException, SecurityException
   {
      return ((server_socket) s).accept_connection(b);
   }

   public static socket socket_accept(socket s, boolean b, boolean errp)
      throws IOException, SecurityException
   {
      return ((server_socket) s).accept(b, errp);
   }

   public static byte[] socket_local_addr(socket s)
   {
      return s.local_addr();
   }

   public static Object socket_shutdown(socket s, boolean b)
      throws IOException
   {
      return s.shutdown(b);
   }

   public static Object socket_close(socket s) throws IOException
   {
      return s.close();
   }

  //////
  // INPUT
  //////
   public static final int default_io_bufsiz = 1024;

   public static boolean INPUT_PORTP(Object o)
   {
      return (o instanceof input_port);
   }

   public static boolean INPUT_STRING_PORTP(Object o)
   {
      return (o instanceof input_string_port);
   }

   public static boolean INPUT_PROCEDURE_PORTP(Object o)
   {
      return (o instanceof input_procedure_port);
   }

   public static input_port getCurrentInputPort()
   {
      return bgldynamic.current_dynamic_env.current_input_port;
   }

   public static void setCurrentInputPort(input_port o)
   {
      bgldynamic.current_dynamic_env.current_input_port = o;
   }

   public static Object open_input_file(byte[]s, bint len)
   {
      try
      {
	 return (input_pipe_port.pipe_name_p(s)
		 ? (Object) new input_pipe_port(s, len.value)
		 : (Object) new input_file_port(s, len.value));
      }
      catch(IOException _)
      {
	 return BFALSE;
      }
   }

   public static Object open_input_pipe(byte[]s, bint len)
   {
      return new input_pipe_port(new String(s), len.value);
   }

   public static int bgl_input_port_bufsiz(input_port p)
   {
      return p.bufsiz;
   }

   public static Object bgl_sendchars(input_port in, output_port out, int o)
   {
      return BFALSE;
   }

   public static Object open_input_string(byte[]s)
   {
      return new input_string_port(s);
   }

   public static Object open_input_procedure(procedure p)
   {
      return new input_procedure_port(p);
   }

   public static Object open_input_c_string(byte[]s)
   {
      return new input_string_port(s);
   }

   public static Object reopen_input_c_string(input_port p, byte[]s)
   {
      ((input_string_port) p).reopen_input_c_string(s);
      return p;
   }

   public static Object bgl_input_port_seek(input_port p, int pos)
   {
      try
      {
	 return p.bgl_input_port_seek(pos);
      }
      catch(Exception e)
      {
	 return bigloo.foreign.BFALSE;
      }
   }

   public static Object bgl_input_port_reopen(input_port p) throws IOException
   {
      return p.bgl_input_port_reopen();
   }

   public static Object bgl_output_port_seek(output_port p,
      int pos) throws IOException
   {
      return p.bgl_output_port_seek(pos);
   }

   public static boolean CLOSED_RGC_BUFFER(input_port o)
   {
      return o.other_eof;
   }

   public static int INPUT_PORT_FILEPOS(input_port p)
   {
      return p.filepos;
   }

   public static int OUTPUT_PORT_FILEPOS(output_port p)
   {
      return 0;
   }

   public static byte[] INPUT_PORT_NAME(input_port p)
   {
      return p.name.getBytes();
   }

   public static int RGC_BUFFER_POSITION(input_port p)
   {
      return (p.forward - p.matchstart);
   }

   public static int RGC_BUFFER_GET_CHAR(input_port p)
   {
      return (p.buffer[p.forward++] & 0xFF);
   }

   public static int rgc_buffer_unget_char(input_port p, int c)
   {
      if (0 < p.matchstop)
	 --p.matchstop;
      else
	{
	   p.buffer[0] = (byte) c;
	   if (p.abufsiz == 0)
	     {
		p.abufsiz = 1;
		p.buffer[1] = (byte) '\0';
	     }
	}
      return c;
   }

   public static int RGC_START_MATCH(input_port p)
   {
      return (p.forward = p.matchstart = p.matchstop);
   }

   public static int RGC_STOP_MATCH(input_port p)
   {
      return (p.matchstop = p.forward);
   }

   public static int RGC_SET_FILEPOS(input_port p)
   {
      return (p.filepos += (p.matchstop - p.matchstart));
   }

   public static int RGC_BUFFER_LENGTH(input_port p)
   {
      return (p.matchstop - p.matchstart);
   }

   public static boolean RGC_BUFFER_EMPTY(input_port p)
   {
      return (p.forward == p.abufsiz);
   }

   public static boolean bgl_rgc_charready(input_port p)
   {
      return p.rgc_charready();
   }

   public static boolean rgc_buffer_eof_p(input_port p)
   {
      return ((p.buffer[p.forward] == 0) && (p.forward + 1 == p.abufsiz));
   }

   private static int rgc_do_blit(input_port p, byte[]s, int o, int l)
      throws IOException
   {
      RGC_START_MATCH(p);

      while (((p.abufsiz - p.matchstart) <= l) && !p.eof) {
	 p.forward = p.abufsiz;
	 rgc_fill_buffer(p);
      }

      if ((p.abufsiz - p.matchstart) <= l)
	 l = (p.abufsiz - p.matchstart - 1);

      p.forward = p.matchstart + l;
      RGC_STOP_MATCH(p);
      RGC_SET_FILEPOS(p);
      System.arraycopy(p.buffer, p.matchstart, s, o, l);

      return l;
   }

   public static int rgc_blit_string(input_port p, byte[]s, int o, int l)
      throws IOException
   {
      final int bs = p.bufsiz;

      if (l <= bs)
	 return rgc_do_blit(p, s, o, l);
      else {
	 int result = 0;
	 while (bs < l) {
	    result += rgc_do_blit(p, s, o, bs);
	    o += bs;
	    l -= bs;
	 }
	 result += rgc_do_blit(p, s, o, l);
	 return result;
      }
   }

   public static boolean rgc_buffer_bof_p(input_port p)
   {
      return (p.filepos == 0);
   }

   public static boolean rgc_buffer_bol_p(input_port p)
   {
      if (p.matchstart > 0)
	 return (p.buffer[p.matchstart - 1] == '\n');
      else
	 return (p.lastchar == (byte) '\n');
   }

   public static boolean rgc_buffer_eol_p(input_port p)
      throws IOException
   {
      final int c = RGC_BUFFER_GET_CHAR(p);

      if  (c == 0)
	{
	   if (!RGC_BUFFER_EMPTY(p))
	     {
		--p.forward;
		return false;
	     }
	  // CARE
	  // if(p.kindof == KINDOF_CONSOLE ) return(true);
	   if     (rgc_fill_buffer(p))
	             return rgc_buffer_eol_p(p);
	   return false;
	}
      --p.forward;
      return (c == (byte) '\n');
   }

   public static boolean rgc_fill_buffer(input_port p) throws IOException
   {
      --p.forward;
      if (p.eof)
	 return false;

      return p.rgc_fill_buffer();
   }

   public static byte[] rgc_buffer_substring(input_port p, int o, int e)
   {
      return c_substring(p.buffer, p.matchstart + o, p.matchstart + e);
   }

   public static byte RGC_BUFFER_CHARACTER(input_port p)
   {
      return p.buffer[p.matchstart];
   }

   public static symbol rgc_buffer_symbol(input_port p)
   {
      int start = p.matchstart;
      final int stop = p.matchstop;
      final int n = stop - start;
      final byte[] name = new byte[n];

      for (int i = 0; i < n; ++i, ++start)
	 name[i] = (byte) (p.buffer[start] & 0xFF);

      return symbol.make_symbol(name);
   }

   public static symbol rgc_buffer_upcase_symbol(input_port p)
   {
      int start = p.matchstart;
      final int stop = p.matchstop;
      final int n = stop - start;
      final byte[] name = new byte[n];

      for (int i = 0; i < n; ++i, ++start)
	 name[i] = (byte) toupper(p.buffer[start] & 0xFF);

      return symbol.make_symbol(name);
   }

   public static symbol rgc_buffer_downcase_symbol(input_port p)
   {
      int start = p.matchstart;
      final int stop = p.matchstop;
      final int n = stop - start;
      final byte[] name = new byte[n];

      for (int i = 0; i < n; ++i, ++start)
	 name[i] = (byte) tolower(p.buffer[start] & 0xFF);

      return symbol.make_symbol(name);
   }

   public static keyword rgc_buffer_upcase_keyword(input_port p)
   {
      int start = p.matchstart;
      final int stop = p.matchstop;
      final int n = stop - start;
      final byte[] name = new byte[n];

      for (int i = 0; i < n; ++i, ++start)
	 name[i] = (byte) toupper(p.buffer[start] & 0xFF);

      return keyword.make_keyword(name);
   }

   public static keyword rgc_buffer_downcase_keyword(input_port p)
   {
      int start = p.matchstart;
      final int stop = p.matchstop;
      final int n = stop - start;
      final byte[] name = new byte[n];

      for (int i = 0; i < n; ++i, ++start)
	 name[i] = (byte) tolower(p.buffer[start] & 0xFF);

      return keyword.make_keyword(name);
   }

   public static keyword rgc_buffer_keyword(input_port p)
   {
      int start = p.matchstart;
      final int stop = p.matchstop;
      final int n = stop - start;
      final byte[] name = new byte[n];

      for (int i = 0; i < n; ++i, ++start)
	 name[i] = (byte) (p.buffer[start] & 0xFF);

      return keyword.make_keyword(name);
   }

   public static int rgc_buffer_fixnum(input_port p)
   {
      return parseint(p.buffer, p.matchstart, p.matchstop, 10);
   }

   public static Object rgc_buffer_integer(input_port p)
   {
      return parseinteger(p.buffer, p.matchstart, p.matchstop, 10);
   }

   public static double rgc_buffer_flonum(input_port p)
   {
     // !!!!! JDK 1.2:  return Double.parseDouble( new String( c_substring( p.buffer, p.matchstart, p.matchstop ) ) );
      return Double.valueOf(new String(c_substring(p.buffer, p.matchstart,
	       p.matchstop))).doubleValue();
   }

   public static Object close_input_port(input_port p) throws IOException
   {
      p.close();
      return p;
   }

   public static boolean reset_eof(Object p)
   {
     //print("RES_EOF " + p);
      return ((input_port) p).reset_eof();
   }

  //////
  // BINARY
  //////

   public static boolean BINARY_PORTP(Object o)
   {
      return (o instanceof binary_port);
   }

   public static boolean BINARY_PORT_INP(binary_port p)
   {
      return (p.stream instanceof InputStream);
   }

   public static boolean BINARY_PORT_OUTP(binary_port p)
   {
      return (p.stream instanceof OutputStream);
   }

   public static Object BINARY_PORT_TO_FILE(binary_port p)
   {
      return p.stream;
   }

   public static Object open_output_binary_file(byte[]file) throws IOException
   {
      return new binary_port(new FileOutputStream(new String(file)));
   }

   public static Object append_output_binary_file(byte[]file) throws IOException
   {
      return new binary_port(new FileOutputStream(new String(file), true));
   }

   public static Object open_input_binary_file(byte[]file)
      throws FileNotFoundException
   {
      return new binary_port(new FileInputStream(new String(file)));
   }

   public static Object close_binary_port(binary_port p) throws IOException
   {
      return p.close();
   }

   public static Object output_obj(binary_port p, Object obj) throws IOException
   {
      return p.output_obj(obj);
   }

   public static Object input_obj(binary_port p) throws IOException
   {
      return p.input_obj();
   }

   public static int BGL_INPUT_CHAR(binary_port p) throws IOException
   {
      return ((FileInputStream) p.stream).read();
   }

   public static boolean BGL_INT_EOFP(int i)
   {
      return (i == -1);
   }

   public static Object BGL_OUTPUT_CHAR(binary_port p,
      byte c) throws IOException
   {
      ((FileOutputStream) p.stream).write(c);
      return p;
   }

  //////
  // OUTPUT
  //////
   public static output_port getCurrentOutputPort()
   {
      return bgldynamic.current_dynamic_env.current_output_port;
   }

   public static void setCurrentOutputPort(output_port o)
   {
      bgldynamic.current_dynamic_env.current_output_port = o;
   }

   public static output_port getCurrentErrorPort()
   {
      return bgldynamic.current_dynamic_env.current_error_port;
   }

   public static void setCurrentErrorPort(output_port o)
   {
      bgldynamic.current_dynamic_env.current_error_port = o;
   }

   public static boolean OUTPUT_PORTP(Object o)
   {
      return (o instanceof output_port);
   }

   public static boolean OUTPUT_STRING_PORTP(Object o)
   {
      return (o instanceof output_string_port);
   }

   public static Object FLUSH_OUTPUT_PORT(output_port p) throws IOException
   {
      return p.flush();
   }

   public static Object open_output_file(byte[]file) throws IOException
   {
      if (bigloo_strcmp( file, "null:".getBytes() ))
	 return new output_port( (foreign.bigloo_strcmp( os.OS_CLASS, "unix".getBytes() )
				  ? "/dev/null"
				  : "NUL:").getBytes() );
      else
	 return new output_port(file);
   }

   public static Object append_output_file(byte[]file) throws IOException
   {
      return new output_port(file, true);
   }

   public static Object open_output_string()
   {
      return new output_string_port();
   }

   public static byte[] get_output_string(output_port p)
   {
     // CARE why not a correct signature in Scheme
      return ((output_string_port) p).get_string();
   }

   public static Object close_output_port(output_port p) throws IOException
   {
      return p.close();
   }

   public static int WRITE_CHAR(int cn, output_port p)
   {
      p.write(cn);
      return cn;
   }

   private static final String[] char_name = { "", "", "", "", "", "", "", "",
      "", "tab", "newline", "", "", "return", "", "",
      "", "", "", "", "", "", "", "",
      "", "", "", "", "", "", "", "",
      "space", "!", "\"", "#", "$", "%", "&", "'",
      "(", ")", "*", "+", ",", "-", ".", "/",
      "0", "1", "2", "3", "4", "5", "6", "7",
      "8", "9", ":", ";", "<", " =", ">", "?",
      "@", "A", "B", "C", "D", "E", "F", "G",
      "H", "I", "J", "K", "L", "M", "N", "O",
      "P", "Q", "R", "S", "T", "U", "V", "W",
      "X", "Y", "Z", "[", "\\", "]", "^", "_",
      "`", "a", "b", "c", "d", "e", "f", "g",
      "h", "i", "j", "k", "l", "m", "n", "o",
      "p", "q", "r", "s", "t", "u", "v", "w",
      "x", "y", "z", "{", "|", "}", "~", ""
   };

   public static Object write_char(bchar c, output_port p)
   {
      final int cn = c.value & 0xFF;

      if ((0 < cn) && (cn < 128))
	{
	   final String rep = char_name[cn];

	   if (rep.length() != 0)
	     {
		p.write("#\\");
		p.write(rep);
		return c;
	     }
	}

      p.write("#a");
      p.write(((byte) '0') + (cn / 100));
      p.write(((byte) '0') + ((cn / 10) % 10));
      p.write(((byte) '0') + (cn % 10));

      return c;
   }

   public static Object display_char(bchar c, output_port p)
   {
      p.write(c.value);
      return c;
   }

   private static final byte[] hexa =
      { (byte) '0', (byte) '1', (byte) '2', (byte) '3',
      (byte) '4', (byte) '5', (byte) '6', (byte) '7',
      (byte) '8', (byte) '9', (byte) 'a', (byte) 'b',
      (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f'
   };

   public static Object write_ucs2(bucs2 s, output_port p)
   {
      final int value = s.value;

      p.write("#u");
      p.write(hexa[(value & 0xf000) >> 12]);
      p.write(hexa[(value & 0x0f00) >> 8]);
      p.write(hexa[(value & 0x00f0) >> 4]);
      p.write(hexa[(value & 0x000f)]);

      return s;
   }

   public static Object display_ucs2(bucs2 s, output_port p)
   {
      p.write(s.value);
      return s;
   }

   public static Object write_object(Object o, output_port p)
   {
      if (o == null)
	 p.write("#<jvm:null>");
      else if (o instanceof obj)
	 ((obj) o).write(p);
      else
	 p.write(o.toString());
      return o;
   }

   public static Object write_string(byte[]s, boolean b, output_port p)
   {
      if (b)
	 p.write((byte) '#');
      p.write((byte) '\"');
      p.write(s);
      p.write((byte) '\"');
      return s;
   }

   public static Object display_string(byte[]s, output_port p)
   {
      p.write(s);
      return s;
   }

   public static Object write_symbol(symbol s, output_port p)
   {
      p.write(s.string);
      return s;
   }

   public static Object display_symbol(symbol s, output_port p)
   {
      p.write(s.string);
      return s;
   }

   public static Object display_fixnum(bint n, output_port p)
   {
      p.write(Integer.toString(n.value));
      return n;
   }

   public static Object display_flonum(real n, output_port p)
   {
      p.write(Double.toString(n.value));
      return n;
   }

   public static Object write_utf8string(byte[]s, output_port p)
   {
      p.write(ucs2_string_to_utf8_string("#u\"" + new String(s) + "\""));
      return s;
   }

   public static Object display_ucs2string(char[]s, output_port p)
   {
      p.write(new String(s));
      return s;
   }

  //////
  // HASH
  //////
   private static final byte[] hash_random_table =
      { (byte) 1, (byte) 14, (byte) 110, (byte) 25, (byte) 97, (byte) 174,
	 (byte) 132,
      (byte) 119, (byte) 138, (byte) 170, (byte) 125, (byte) 118, (byte) 27,
      (byte) 233, (byte) 140, (byte) 51,
      (byte) 87, (byte) 197, (byte) 177, (byte) 107, (byte) 234, (byte) 169,
      (byte) 56, (byte) 68, (byte) 30, (byte) 7, (byte) 173, (byte) 73,
	 (byte) 188,
      (byte) 40, (byte) 36, (byte) 65,
      (byte) 49, (byte) 213, (byte) 104, (byte) 190, (byte) 57, (byte) 211,
      (byte) 148, (byte) 223, (byte) 48, (byte) 115, (byte) 15, (byte) 2,
	 (byte) 67,
      (byte) 186, (byte) 210, (byte) 28,
      (byte) 12, (byte) 181, (byte) 103, (byte) 70, (byte) 22, (byte) 58,
	 (byte) 75,
      (byte) 78, (byte) 183, (byte) 167, (byte) 238, (byte) 157, (byte) 124,
      (byte) 147, (byte) 172, (byte) 144,
      (byte) 176, (byte) 161, (byte) 141, (byte) 86, (byte) 60, (byte) 66,
	 (byte) 128,
      (byte) 83, (byte) 156, (byte) 241, (byte) 79, (byte) 46, (byte) 168,
	 (byte) 198,
      (byte) 41, (byte) 254,
      (byte) 178, (byte) 85, (byte) 253, (byte) 237, (byte) 250, (byte) 154,
      (byte) 133, (byte) 88, (byte) 35, (byte) 206, (byte) 95, (byte) 116,
      (byte) 252, (byte) 192, (byte) 54, (byte) 221,
      (byte) 102, (byte) 218, (byte) 255, (byte) 240, (byte) 82, (byte) 106,
      (byte) 158, (byte) 201, (byte) 61, (byte) 3, (byte) 89, (byte) 9,
	 (byte) 42,
      (byte) 155, (byte) 159, (byte) 93,
      (byte) 166, (byte) 80, (byte) 50, (byte) 34, (byte) 175, (byte) 195,
	 (byte) 100,
      (byte) 99, (byte) 26, (byte) 150, (byte) 16, (byte) 145, (byte) 4,
	 (byte) 33,
      (byte) 8, (byte) 189,
      (byte) 121, (byte) 64, (byte) 77, (byte) 72, (byte) 208, (byte) 245,
	 (byte) 130,
      (byte) 122, (byte) 143, (byte) 55, (byte) 105, (byte) 134, (byte) 29,
      (byte) 164, (byte) 185, (byte) 194,
      (byte) 193, (byte) 239, (byte) 101, (byte) 242, (byte) 5, (byte) 171,
      (byte) 126, (byte) 11, (byte) 74, (byte) 59, (byte) 137, (byte) 228,
      (byte) 108, (byte) 191, (byte) 232, (byte) 139,
      (byte) 6, (byte) 24, (byte) 81, (byte) 20, (byte) 127, (byte) 17,
	 (byte) 91,
      (byte) 92, (byte) 251, (byte) 151, (byte) 225, (byte) 207, (byte) 21,
      (byte) 98, (byte) 113, (byte) 112,
      (byte) 84, (byte) 226, (byte) 18, (byte) 214, (byte) 199, (byte) 187,
      (byte) 13, (byte) 32, (byte) 94, (byte) 220, (byte) 224, (byte) 212,
      (byte) 247, (byte) 204, (byte) 196, (byte) 43,
      (byte) 249, (byte) 236, (byte) 45, (byte) 244, (byte) 111, (byte) 182,
      (byte) 153, (byte) 136, (byte) 129, (byte) 90, (byte) 217, (byte) 202,
      (byte) 19, (byte) 165, (byte) 231, (byte) 71,
      (byte) 230, (byte) 142, (byte) 96, (byte) 227, (byte) 62, (byte) 179,
      (byte) 246, (byte) 114, (byte) 162, (byte) 53, (byte) 160, (byte) 215,
      (byte) 205, (byte) 180, (byte) 47, (byte) 109,
      (byte) 44, (byte) 38, (byte) 31, (byte) 149, (byte) 135, (byte) 0,
      (byte) 216, (byte) 52, (byte) 63, (byte) 23, (byte) 37, (byte) 69,
	 (byte) 39,
      (byte) 117, (byte) 146, (byte) 184,
      (byte) 163, (byte) 200, (byte) 222, (byte) 235, (byte) 248, (byte) 243,
      (byte) 219, (byte) 10, (byte) 152, (byte) 131, (byte) 123, (byte) 229,
      (byte) 203, (byte) 76, (byte) 120, (byte) 209
   };

   public static int get_hash_number(byte[]s)
   {
      byte hash = 0;

      for (int i = 0; i < s.length; ++i)
	 hash = hash_random_table[(hash ^ s[i]) & 0xFF];
      return (hash & 0xFF);
   }

   public static int get_hash_power_number(byte[]str, int power)
   {
      int result = 0;

      for (int i = 0; i < str.length; ++i)
	 result += (result << 3) + str[i];
      return (result & ((1 << power) - 1));
   }

   public static int get_hash_number_from_int(int i)
   {
      byte hash = 0;

      while (i != 0)
	{
	   hash = hash_random_table[(int) ((hash ^ i) & 0xFF)];
	   i >>>= 8;
	}
      return (hash & 0xFF);
   }

   public static int get_hash_number_from_int(Object o)
   {
      return get_hash_number_from_int(o.hashCode());
   }

   public static int get_hash_power_number_from_int(int i, int power)
   {
      int result = 0;

      while (i != 0)
	{
	   result += (result << 3) + (i & 0xFF);
	   i >>>= 8;
	}
      return (result & ((1 << power) - 1));
   }

   public static int get_hash_power_number_from_int(Object i, int power)
   {
      final int hash_code = i.hashCode();

      return (hash_code & ((1 << power) - 1));
   }

   public static int bgl_string_hash_number(byte[]s)
   {
      int result = 0;

      for (int i = 0; i < s.length; ++i)
	 result += (result << 3) + s[i];
      return result;
   }

   public static int bgl_symbol_hash_number(symbol obj)
   {
      return (1 + bgl_string_hash_number(SYMBOL_TO_STRING(obj)));
   }

   public static int bgl_keyword_hash_number(keyword obj)
   {
      return (2 + bgl_string_hash_number(KEYWORD_TO_STRING(obj)));
   }

   public static int bgl_obj_hash_number(Object obj)
   {
      return obj.hashCode();
   }

   public static int bgl_foreign_hash_number(Object obj)
   {
      return obj.hashCode();
   }

   public static byte[] bgl_double_to_ieee_string(double v) throws IOException
   {
      final ByteArrayOutputStream bout = new ByteArrayOutputStream();
      final DataOutputStream out = new DataOutputStream(bout);

      out.writeDouble(v);

      final byte[] res = bout.toByteArray();

      bout.close();
      return res;
   }

   public static double bgl_ieee_string_to_double(byte[]s) throws IOException
   {
      final ByteArrayInputStream bint = new ByteArrayInputStream(s);
      final DataInputStream in = new DataInputStream(bint);
      final double res = in.readDouble();

      bint.close();

      return res;
   }

   public static int rand()
   {
      return (int) ((double) Math.random() * java.lang.Integer.MAX_VALUE);
   }

   public static void bgl_sleep( int microsecs ) {
      try {
	 Thread.sleep( (long)(microsecs / 1000),
		       (int)(1000*(microsecs % 1000)) );
      } catch( Exception e ) {
      }
   }

   public static byte[] bgl_gethostname() {
      try {
	 InetAddress addr = java.net.InetAddress.getLocalHost();
	 return addr.getHostName().getBytes();
      } catch( Exception _ ) {
	 return "localhost".getBytes();
      }
   }
}
