Example #1
0
value fortran_printtab(value ba)
{
  int dimx = Bigarray_val(ba)->dim[0];
  int dimy = Bigarray_val(ba)->dim[1];
  printtab_(Data_bigarray_val(ba), &dimx, &dimy);
  return Val_unit;
}
Example #2
0
/* T.F. additions - same style. We use these to distribute mesh info */
value caml_mpi_broadcast_bigarray_float(value data, value root, value comm)
{
  mlsize_t len = Bigarray_val(data)->dim[0];
  double *d = Data_bigarray_val(data);
  MPI_Bcast(d, len, MPI_DOUBLE, Int_val(root), Comm_val(comm));
  return Val_unit;
}
CAMLprim value netsys_init_string(value memv, value offv, value lenv) 
{
    struct caml_bigarray *b = Bigarray_val(memv);
    intnat off = Long_val(offv);
    intnat len = Long_val(lenv);
    value *m;
    char *m_b;
    mlsize_t wosize;
    mlsize_t offset_index;

#ifdef ARCH_SIXTYFOUR
    if (off % 8 != 0)
	invalid_argument("Netsys_mem.init_string");
#else
    if (off % 4 != 0)
	invalid_argument("Netsys_mem.init_string");
#endif

    m = (value *) (((char *) b->data) + off);
    m_b = (char *) m;
    wosize = (len + sizeof (value)) / sizeof (value);  /* >= 1 */
    
    m[0] = /* Make_header (wosize, String_tag, Caml_white) */
	(value) (((header_t) wosize << 10) + String_tag);
    m[wosize] = 0;

    offset_index = Bsize_wsize (wosize) - 1;
    m_b[offset_index + sizeof(value)] = offset_index - len;

    return Val_unit;
}
Example #4
0
value unix_util_write(value fd,value buf)
{
  value vres=alloc(1,1); /* Ok result */
  int res;
  enter_blocking_section();
  res = write(Int_val(fd), /* TODO: unsafe coercion */
	      Bigarray_val(buf)->data,Bigarray_val(buf)->dim[0]);
  leave_blocking_section();
  if (res >=0) Field(vres,0)=Val_int(res);
  else 
    {
      Tag_val(vres)=0; /* Bad result */
      Field(vres,0)=Val_int(c2ml_unix_error(res)); /* TODO: EUNKNOWN x is a block */
    }
  return vres;
}
CAMLprim value netsys_zero_pages(value memv, value offsv, value lenv)
{
#if defined(HAVE_MMAP) && defined(HAVE_SYSCONF) && defined(MAP_ANON) && defined (MAP_FIXED)
    struct caml_bigarray *mem = Bigarray_val(memv);
    long offs = Long_val(offsv);
    long len = Long_val(lenv);
    long pgsize = sysconf(_SC_PAGESIZE);
    char *data = ((char*) mem->data) + offs;
    void *data2;
    
    if (((uintnat) data) % pgsize == 0 && len % pgsize == 0) {
	if (len > 0) {
	    data2 = mmap(data, len, PROT_READ|PROT_WRITE, 
			 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
			 (-1), 0);
	    if (data2 == (void *) -1) uerror("mmap", Nothing);
	    if (((void *) data) != data2)
		failwith("Netsys_mem.zero_pages assertion failed");
	}
    }
    else
	invalid_argument("Netsys_mem.zero_pages only for whole pages");

    return Val_unit;
#else
    invalid_argument("Netsys_mem.zero_pages not available");
#endif
}
Example #6
0
value caml_mpi_broadcast_bigarray_nativeint(value data, value root, value comm)
{
  mlsize_t len = Bigarray_val(data)->dim[0];
  double *d = Data_bigarray_val(data);
  MPI_Bcast(d, len, MPI_LONG, Int_val(root), Comm_val(comm));
  /* According to the docs, MPI_LONG is right, even on LC64 machines. */
  return Val_unit;
}
Example #7
0
CAMLprim value string_to_binary_array (value dst_arr, value dst_idx, value src_str)
{
	CAMLparam3 (dst_arr, dst_idx, src_str);
	int len = string_length (src_str), idx = Long_val(dst_idx);
	if (idx + len > Bigarray_val(dst_arr)->dim[0]) invalid_argument ("Binarray.write");
	memcpy ((char *) Data_bigarray_val(dst_arr) + idx, String_val(src_str), len);
	CAMLreturn (Val_unit);
}
Example #8
0
CAMLprim value ml_blit_buffer_to_string
(value a, value i, value s, value j, value l)
{
  char *src = Array_data(Bigarray_val(a), i);
  char *dest = String_val(s) + Long_val(j);
  memcpy(dest, src, Long_val(l));
  return Val_unit;
}
Example #9
0
CAMLprim value cstring_to_binary_array (value dst_arr, value dst_idx, value dst_len, value src_str)
{
	CAMLparam4 (dst_arr, dst_idx, dst_len, src_str);
	int len = string_length (src_str), idx = Long_val(dst_idx), dlen = Long_val(dst_len);
	if (idx + dlen > Bigarray_val(dst_arr)->dim[0] || len > dlen) invalid_argument ("Binarray.write_sz");
	memcpy ((char *) Data_bigarray_val(dst_arr) + idx, String_val(src_str), len);
	memset ((char *) Data_bigarray_val(dst_arr) + idx + len, 0, dlen - len);
	CAMLreturn (Val_unit);
}
Example #10
0
CAMLprim value
ml_gsl_wavelet_transform_bigarray (value w, value dir, value b, value ws)
{
  struct caml_bigarray *bigarr = Bigarray_val(b);
  double *data  = bigarr->data;
  size_t n      = bigarr->dim[0];
  gsl_wavelet_transform (Wavelet_val (w), data, 1, n,
			 gsl_direction_val (dir), WS_val (ws));
  return Val_unit;
}
Example #11
0
CAMLprim value win_write
(value fd, value buf, value ofs, value len, value id) {
  CAMLparam4(fd, buf, ofs, len);
  struct caml_bigarray *buf_arr = Bigarray_val(buf);

  if (Field(fd, 1) == Val_long(0))
    overlapped_action (WRITE_OVERLAPPED, Long_val(id), Handle(fd),
                       Array_data (buf_arr, ofs), Long_val(len));
  else
    thread_io (WRITE, Long_val(id), Field(fd, 1), Handle(fd),
               Array_data (buf_arr, ofs), Long_val(len));
  CAMLreturn (Val_unit);
}
Example #12
0
value ml_cv_convert_bigarray( value converter, value src, value dest ) {
    CAMLparam3( converter, src, dest );

    int n;
    n = Bigarray_val( dest )->dim[0];

    if ( n > Bigarray_val( src )->dim[0] ) {
        caml_raise_with_arg( *caml_named_value( "ut status exception" ), Val_int( UT_BAD_ARG ) );
    }

    if ( (Bigarray_val( src )->flags & BIGARRAY_KIND_MASK) == BIGARRAY_FLOAT32 ) {
        cv_convert_floats( UD_cv_converter_val( converter ), Data_bigarray_val( src ), n, Data_bigarray_val( dest ) );
    }
    else if ( (Bigarray_val( src )->flags & BIGARRAY_KIND_MASK) == BIGARRAY_FLOAT64 ) {
        cv_convert_doubles( UD_cv_converter_val( converter ), Data_bigarray_val( src ), n, Data_bigarray_val( dest ) );
    }
    else {
        caml_raise_with_arg( *caml_named_value( "ut status exception" ), Val_int( UT_BAD_ARG ) );
    }

    CAMLreturn( Val_unit );
}
CAMLprim value netsys_value_area_remove(value memv) 
{
#ifdef FANCY_PAGE_TABLES
    struct caml_bigarray *b = Bigarray_val(memv);
    int code;
    code = caml_page_table_remove(In_static_data,
				  b->data,
				  b->data + b->dim[0]);
    /* Silently ignore errors... */
    return Val_unit;
#else
    invalid_argument("Netsys_mem.value_area");
#endif
}
CAMLprim value netsys_value_area_add(value memv) 
{
#ifdef FANCY_PAGE_TABLES
    struct caml_bigarray *b = Bigarray_val(memv);
    int code;
    code = caml_page_table_add(In_static_data,
			       b->data,
			       b->data + b->dim[0]);
    if (code != 0) 
	failwith("Netsys_mem.value_area: error");
    return Val_unit;
#else
    invalid_argument("Netsys_mem.value_area");
#endif
}
CAMLprim value netsys_blit_string_to_memory(value sv,
					    value soffv,
					    value memv,
					    value memoffv,
					    value lenv)
{
    struct caml_bigarray *mem = Bigarray_val(memv);
    char * s = String_val(sv);
    long memoff = Long_val(memoffv);
    long soff = Long_val(soffv);
    long len = Long_val(lenv);

    memmove(((char*) mem->data) + memoff, s + soff, len);

    return Val_unit;
}
Example #16
0
static void thread_io
(long action, long id, value threads, HANDLE h, char * buf, long len) {
  struct caml_bigarray *buf_arr = Bigarray_val(buf);
  ioInfo * info = GlobalAlloc(GPTR, sizeof(ioInfo));
  if (info == NULL) {
    errno = ENOMEM;
    uerror(action_name[action], Nothing);
  }

  info->action = action;
  info->id = id;
  info->fd = h;
  info->buffer = buf;
  info->len = len;

  h = get_helper_thread(threads, action);
  QueueUserAPC(perform_io_on_thread, h, (ULONG_PTR) info);
}
Example #17
0
CAMLprim value
ml_sqlite3_bind_blob_big (value s, value idx, value v)
{
  sqlite3_stmt *stmt = Sqlite3_stmt_val (s);
  int i = Int_val (idx);
  int status;
  struct caml_bigarray *ba;

  ba = Bigarray_val (v);
  status = sqlite3_bind_blob (stmt, i, 
			      ba->data, ba->dim[0],
			      ml_sqlite3_release_big);

  if (status != SQLITE_OK)
    ml_sqlite3_raise_exn (status, "sqlite3_bind failed", TRUE);

  ml_sqlite3_register_big (v);
  return Val_unit;
}
CAMLprim value netsys_memory_unmap_file(value memv) 
{
    struct caml_bigarray *b = Bigarray_val(memv);
    if ((b->flags & BIGARRAY_MANAGED_MASK) == BIGARRAY_MAPPED_FILE) {
	if (b->proxy == NULL) {
	    ba_unmap_file(b->data, b->dim[0]);
	    b->data = NULL;
	    b->flags = 
		(b->flags & ~BIGARRAY_MANAGED_MASK) | BIGARRAY_EXTERNAL;
	}
	else if (b->proxy->refcount == 1) {
	    ba_unmap_file(b->proxy->data, b->dim[0]);
	    b->proxy->data = NULL;
	    b->data = NULL;
	    b->flags = 
		(b->flags & ~BIGARRAY_MANAGED_MASK) | BIGARRAY_EXTERNAL;
	}
    }
    return Val_unit;
}
Example #19
0
CAMLprim value digest_array (value v_iarr)
{
	CAMLparam1(v_iarr);
	CAMLlocal1(result);
	MD5Context context;
	int len = Bigarray_val(v_iarr)->dim[0];
	unsigned char *buf = Data_bigarray_val(v_iarr);

	MD5Init (&context);
	while (len > 0) {
		int block = (len > 8192) ? 8192 : len;
		MD5Update (&context, buf, block);
		buf += block;
		len -= block;
	}

	result = alloc_string (16);
	MD5Final (&Byte_u(result, 0), &context);
	CAMLreturn(result);
}
CAMLprim value netsys_mem_write(value fdv, value memv, value offv, value lenv)
{
    intnat numbytes;
    intnat ret;
    char *data;
#ifdef _WIN32
    DWORD n;
    DWORD err = 0;
#endif

    numbytes = Long_val(lenv);
    data = ((char *) (Bigarray_val(memv)->data)) + Long_val(offv);
#ifdef _WIN32
    if (Descr_kind_val(fdv) == KIND_SOCKET) {
	SOCKET h = Socket_val(fdv);
	enter_blocking_section();
	ret = send(h, data, numbytes, 0);
	if (ret == SOCKET_ERROR) err = WSAGetLastError();
	leave_blocking_section();
	ret = n;
    } else {
	HANDLE h = Handle_val(fdv);
	enter_blocking_section();
	if (! WriteFile(h, data, numbytes, &n, NULL)) err = GetLastError();
	leave_blocking_section();
	ret = n;
    }
    if (err) {
	win32_maperr(err);
	ret = -1;
    }
#else
    enter_blocking_section();
    ret = write(Int_val(fdv), data, (int) numbytes);
    leave_blocking_section();
#endif
    if (ret == -1) uerror("mem_write", Nothing);
    return Val_long(ret);
}
Example #21
0
CAMLprim value stub_gntshr_munmap_batched(value xgh, value share) {
	CAMLparam2(xgh, share);
	CAMLlocal1(ml_map);
#ifdef HAVE_GNTSHR
	ml_map = Field(share, 1);

	int size = Bigarray_val(ml_map)->dim[0];
	int pages = size >> XC_PAGE_SHIFT;
#ifdef linux
	/* Bug in xen-4.4 libxc xc_linux_osdep implementation, work-around
	   by using the kernel interface directly. */
	int result = munmap(Data_bigarray_val(ml_map), size);
#else
	int result = xc_gntshr_munmap(_G(xgh), Data_bigarray_val(ml_map), pages);
#endif
	if(result != 0)
		failwith_xc(_G(xgh));
#else
	gntshr_missing();
#endif
	CAMLreturn(Val_unit);
}
CAMLprim value netsys_mem_send(value fdv, value memv, value offv, value lenv,
			       value flagsv)
{
    intnat numbytes;
    intnat ret;
    char *data;
    int flags;
#ifdef _WIN32
    DWORD err = 0;
    SOCKET s;
#else
    int s;
#endif

    numbytes = Long_val(lenv);
    data = ((char *) (Bigarray_val(memv)->data)) + Long_val(offv);
    flags = convert_flag_list(flagsv, msg_flag_table);

#ifdef _WIN32
    s = Socket_val(fdv);
#else
    s = Int_val(fdv);
#endif

    enter_blocking_section();
    ret = send(s, data, (int) numbytes, flags);

#ifdef _WIN32
    if (ret == -1) err = WSAGetLastError();
    leave_blocking_section();
    if (ret == -1) win32_maperr(err);
#else
    leave_blocking_section();
#endif

    if (ret == -1) uerror("mem_send", Nothing);
    return Val_long(ret);
}
Example #23
0
CAMLprim value win_readdirtorychanges
(value fd_val, value buf_val, value recursive, value flags, value id_val) {
  CAMLparam5(fd_val, buf_val, recursive, flags, id_val);
  struct caml_bigarray *buf_arr = Bigarray_val(buf_val);
  long id = Long_val(id_val);
  HANDLE fd = Handle_val(fd_val);
  char * buf = Array_data (buf_arr, 0);
  long len = buf_arr->dim[0];
  long action = READDIRECTORYCHANGES;
  BOOL res;
  long err;
  int notify_filter = convert_flag_list(flags, notify_filter_flags);
  completionData * d = GlobalAlloc(GPTR, sizeof(completionData));
  if (d == NULL) {
    errno = ENOMEM;
    uerror(action_name[action], Nothing);
  }
  d->id = id;
  d->action = action;

  D(printf("Starting %s: id %ld, len %ld\n", action_name[action], id, len));

  res = ReadDirectoryChangesW (fd, buf, len, Bool_val(recursive),
                               notify_filter, NULL, &(d->overlapped),
                               overlapped_completion);

  if (!res) {
    err = GetLastError ();
    if (err != ERROR_IO_PENDING) {
      win32_maperr (err);
  D(printf("Action %s failed: id %ld -> err %d (errCode %ld)\n",
           action_name[action], id, errno, err));
      uerror("ReadDirectoryChangesW", Nothing);
    }
  }
  CAMLreturn (Val_unit);
}
Example #24
0
CAMLprim value win_parse_directory_changes (value buf_val) {
  CAMLparam1(buf_val);
  CAMLlocal4(lst, tmp, elt, filename);
  struct caml_bigarray *buf_arr = Bigarray_val(buf_val);
  char * pos = Array_data (buf_arr, 0);
  FILE_NOTIFY_INFORMATION * entry;

  lst = Val_long(0);
  while (1) {
    entry = (FILE_NOTIFY_INFORMATION *)pos;
    elt = caml_alloc_tuple(2);
    filename = caml_alloc_string(entry->FileNameLength);
    memmove(String_val(filename), entry->FileName, entry->FileNameLength);
    Store_field (elt, 0, filename);
    Store_field (elt, 1, Val_long(entry->Action - 1));
    tmp = caml_alloc_tuple(2);
    Store_field (tmp, 0, elt);
    Store_field (tmp, 1, lst);
    lst = tmp;
    if (entry->NextEntryOffset == 0) break;
    pos += entry->NextEntryOffset;
  }
  CAMLreturn(lst);
}
CAMLprim value netsys_init_header(value memv, value offv, value tagv,
				  value sizev)
{
    struct caml_bigarray *b = Bigarray_val(memv);
    intnat off = Long_val(offv);
    intnat size = Long_val(sizev);
    int tag = Int_val(tagv);
    value *m;

#ifdef ARCH_SIXTYFOUR
    if (off % 8 != 0)
	invalid_argument("Netsys_mem.init_header");
#else
    if (off % 4 != 0)
	invalid_argument("Netsys_mem.init_header");
#endif

    m = (value *) (((char *) b->data) + off);
    m[0] = /* Make_header (wosize, tag, Caml_white) */
	(value) (((header_t) size << 10) + tag);

    return Val_unit;
    
}
Example #26
0
File: sankoff.c Project: amnh/poy5
value
sankoff_CAML_create_eltarr (value is_identity, value taxon_code, value code, value number_of_states, value ecode_bigarr, value states_bigarr, value tcm_bigarr) {
    CAMLparam5(is_identity,taxon_code,code,number_of_states,ecode_bigarr);
    CAMLxparam2(states_bigarr,tcm_bigarr);
    CAMLlocal1(res);
    int num_states;
    num_states = Int_val(number_of_states);
    int tcode = Int_val(taxon_code);
    int iside = Int_val(is_identity);
    int mycode = Int_val(code); 
    int * cost_mat; int dimcm1, dimcm2;
    int * states_arrarr; int dims1, dims2;
    int * ecode_arr; int dim;
    ecode_arr = (int*) Data_bigarray_val(ecode_bigarr);
    dim = Bigarray_val(ecode_bigarr)->dim[0];//number of elts
    states_arrarr = (int*) Data_bigarray_val(states_bigarr);
    dims1 = Bigarray_val(states_bigarr)->dim[0]; //number of elts
    dims2 = Bigarray_val(states_bigarr)->dim[1]; //number of states in each elt
    if (dim!=dims1) failwith ("sankoff.c, size of ecode array != number of charactors");
    if (dims2!= num_states) failwith ("sankoff.c, size of states array != number of states");
    cost_mat = (int*) Data_bigarray_val(tcm_bigarr);
    dimcm1 = Bigarray_val(tcm_bigarr)->dim[0];//number of states
    dimcm2 = Bigarray_val(tcm_bigarr)->dim[1];//number of states
    if ((dimcm1!=dimcm2)||(dimcm1!=dims2)) 
        failwith ("sankoff.c, wrong size of costmat between states");
    eltarr_p neweltarr;
    //alloc struct elt_arr 
    neweltarr = (eltarr_p)calloc(1,sizeof(struct elt_arr));
    neweltarr->code = mycode;
    neweltarr->taxon_code = tcode;
    neweltarr->left_taxon_code = tcode;
    neweltarr->right_taxon_code = tcode;
    neweltarr->sum_cost = 0;
    neweltarr->num_states = dimcm1;
    neweltarr->num_elts = dim;
    neweltarr->is_identity = iside;
    //alloc its pointers
    neweltarr->tcm = (int*)calloc(dimcm1*dimcm2,sizeof(int));
    memcpy(neweltarr->tcm,cost_mat,sizeof(int) * dimcm1 * dimcm2);
    neweltarr->elts = (elt_p)calloc(dim,sizeof(struct elt));
    int i; int j;
    int * states_arr;
    elt_p newelt;
    for (i=0;i<dim;i++)
    {
        newelt = &((neweltarr->elts)[i]);
        assert(newelt!=NULL);
        newelt->ecode = ecode_arr[i];
        newelt->num_states = num_states;
        newelt->states = (int*)calloc( num_states, sizeof(int) );
        newelt->leftstates = (int*)calloc( num_states, sizeof(int) );
        newelt->rightstates = (int*)calloc( num_states, sizeof(int) );
        //for new median_3
        if (median_3_su) { 
            newelt->left_costdiff_mat = (int*)calloc(num_states*num_states,sizeof(int));
            newelt->right_costdiff_mat = (int*)calloc(num_states*num_states,sizeof(int));
        }
        states_arr = sankoff_move_to_line_i(states_arrarr,dims1,dims2,i);
        //the infinity on ocaml side is diff from here, so we pass -1 instead
        //memcpy(newelt->states,states_arr,sizeof(int)*num_states);
        for (j=0;j<num_states;j++) {
            (newelt->states)[j] = ( states_arr[j]==(-1) ) ? infinity : states_arr[j];
        }   
        newelt->beta = (int*)calloc(num_states,sizeof(int));
        newelt->e = (int*)calloc(num_states,sizeof(int));
        newelt->m = (int*)calloc(num_states,sizeof(int));
        sankoff_canonize(newelt,cost_mat);
    }
    res = caml_alloc_custom (&sankoff_custom_operations_eltarr,sizeof (eltarr_p), 1,alloc_custom_max);
    Sankoff_return_eltarr(res) = neweltarr;
    CAMLreturn(res);
}
int netsys_init_value_1(struct htab *t,
			struct nqueue *q,
			char *dest,
			char *dest_end,
			value orig,  
			int enable_bigarrays, 
			int enable_customs,
			int enable_atoms,
			int simulation,
			void *target_addr,
			struct named_custom_ops *target_custom_ops,
			int color,
			intnat *start_offset,
			intnat *bytelen
			)
{
    void *orig_addr;
    void *work_addr;
    value work;
    int   work_tag;
    char *work_header;
    size_t work_bytes;
    size_t work_words;
    void *copy_addr;
    value copy;
    char *copy_header;
    header_t copy_header1;
    int   copy_tag;
    size_t copy_words;
    void *fixup_addr;
    char *dest_cur;
    char *dest_ptr;
    int code, i;
    intnat addr_delta;
    struct named_custom_ops *ops_ptr;
    void *int32_target_ops;
    void *int64_target_ops;
    void *nativeint_target_ops;
    void *bigarray_target_ops;

    copy = 0;

    dest_cur = dest;
    addr_delta = ((char *) target_addr) - dest;

    if (dest_cur >= dest_end && !simulation) return (-4);   /* out of space */

    if (!Is_block(orig)) return (-2);

    orig_addr = (void *) orig;
    code = netsys_queue_add(q, orig_addr);
    if (code != 0) return code;

    /* initialize *_target_ops */
    bigarray_target_ops = NULL;
    int32_target_ops = NULL;
    int64_target_ops = NULL;
    nativeint_target_ops = NULL;
    ops_ptr = target_custom_ops;
    while (ops_ptr != NULL) {
	if (strcmp(ops_ptr->name, "_bigarray") == 0)
	    bigarray_target_ops = ops_ptr->ops;
	else if (strcmp(ops_ptr->name, "_i") == 0)
	    int32_target_ops = ops_ptr->ops;
	else if (strcmp(ops_ptr->name, "_j") == 0)
	    int64_target_ops = ops_ptr->ops;
	else if (strcmp(ops_ptr->name, "_n") == 0)
	    nativeint_target_ops = ops_ptr->ops;
	ops_ptr = ops_ptr->next;
    };

    /* First pass: Iterate over the addresses found in q. Ignore
       addresses already seen in the past (which are in t). For
       new addresses, make a copy, and add these copies to t.
    */

    /* fprintf(stderr, "first pass, orig_addr=%lx simulation=%d addr_delta=%lx\n",
       (unsigned long) orig_addr, simulation, addr_delta);
    */

    code = netsys_queue_take(q, &work_addr);
    while (code != (-3)) {
	if (code != 0) return code;

	/* fprintf(stderr, "work_addr=%lx\n", (unsigned long) work_addr); */

	code = netsys_htab_lookup(t, work_addr, &copy_addr);
	if (code != 0) return code;

	if (copy_addr == NULL) {
	    /* The address is unknown, so copy the value */

	    /* Body of first pass */
	    work = (value) work_addr;
	    work_tag = Tag_val(work);
	    work_header = Hp_val(work);
	    
	    if (work_tag < No_scan_tag) {
		/* It is a scanned value (with subvalues) */
		
		switch(work_tag) {
		case Object_tag:
		case Closure_tag:
		case Lazy_tag:
		case Forward_tag:
		    return (-2);   /* unsupported */
		}

		work_words = Wosize_hp(work_header);
		if (work_words == 0) {
		    if (!enable_atoms) return (-2);
		    if (enable_atoms == 1) goto next;
		};
		
		/* Do the copy. */

		work_bytes = Bhsize_hp(work_header);
		copy_header = dest_cur;
		dest_cur += work_bytes;
		if (dest_cur > dest_end && !simulation) return (-4);
		
		if (simulation) 
		    copy_addr = work_addr;
		else {
		    memcpy(copy_header, work_header, work_bytes);
		    copy = Val_hp(copy_header);
		    copy_addr = (void *) copy;
		    Hd_val(copy) = Whitehd_hd(Hd_val(copy)) | color;
		}

		/* Add the association (work_addr -> copy_addr) to t: */

		code = netsys_htab_add(t, work_addr, copy_addr);
		if (code < 0) return code;

		/* Add the sub values of work_addr to q: */

		for (i=0; i < work_words; ++i) {
		    value field = Field(work, i);
		    if (Is_block (field)) {
			code = netsys_queue_add(q, (void *) field);
			if (code != 0) return code;
		    }
		}
	    }
	    else {
		/* It an opaque value */
		int do_copy = 0;
		int do_bigarray = 0;
		void *target_ops = NULL;
		char caml_id = ' ';  /* only b, i, j, n */
		/* Check for bigarrays and other custom blocks */
		switch (work_tag) {
		case Abstract_tag:
		    return(-2);
		case String_tag:
		    do_copy = 1; break;
		case Double_tag:
		    do_copy = 1; break;
		case Double_array_tag:
		    do_copy = 1; break;
		case Custom_tag: 
		    {
			struct custom_operations *custom_ops;
			char *id;

			custom_ops = Custom_ops_val(work);
			id = custom_ops->identifier;
			if (id[0] == '_') {
			    switch (id[1]) {
			    case 'b':
				if (!enable_bigarrays) return (-2);
				if (strcmp(id, "_bigarray") == 0) {
				    caml_id = 'b';
				    break;
				}
			    case 'i': /* int32 */
			    case 'j': /* int64 */
			    case 'n': /* nativeint */
				if (!enable_customs) return (-2);
				if (id[2] == 0) {
				    caml_id = id[1];
				    break;
				}
			    default:
				return (-2);
			    }
			}
			else
			    return (-2);
		    }
		}; /* switch */

		switch (caml_id) {  /* look closer at some cases */
		case 'b': {
		    target_ops = bigarray_target_ops;
		    do_copy = 1;
		    do_bigarray = 1;
		    break;
		}
		case 'i':
		    target_ops = int32_target_ops; do_copy = 1; break;
		case 'j':
		    target_ops = int64_target_ops; do_copy = 1; break;
		case 'n':
		    target_ops = nativeint_target_ops; do_copy = 1; break;
		};

		if (do_copy) {  
		    /* Copy the value */
		    work_bytes = Bhsize_hp(work_header);
		    copy_header = dest_cur;
		    dest_cur += work_bytes;

		    if (simulation)
			copy_addr = work_addr;
		    else {
			if (dest_cur > dest_end) return (-4);
			memcpy(copy_header, work_header, work_bytes);
			copy = Val_hp(copy_header);
			copy_addr = (void *) copy;
			Hd_val(copy) = Whitehd_hd(Hd_val(copy)) | color;
			if (target_ops != NULL)
			    Custom_ops_val(copy) = target_ops;
		    }
		    
		    code = netsys_htab_add(t, work_addr, copy_addr);
		    if (code < 0) return code;
		}

		if (do_bigarray) {
		    /* postprocessing for copying bigarrays */
		    struct caml_ba_array *b_work, *b_copy;
		    void * data_copy;
		    char * data_header;
		    header_t data_header1;
		    size_t size = 1;
		    size_t size_aligned;
		    size_t size_words;
		    b_work = Bigarray_val(work);
		    b_copy = Bigarray_val(copy);
		    for (i = 0; i < b_work->num_dims; i++) {
			size = size * b_work->dim[i];
		    };
		    size = 
			size * 
			caml_ba_element_size[b_work->flags & BIGARRAY_KIND_MASK];

		    size_aligned = size;
		    if (size%sizeof(void *) != 0)
			size_aligned += sizeof(void *) - (size%sizeof(void *));
		    size_words = Wsize_bsize(size_aligned);

		    /* If we put the copy of the bigarray into our own
		       dest buffer, also generate an abstract header,
		       so it can be skipped when iterating over it.

		       We use here a special representation, so we can
		       encode any length in this header (with a normal
		       Ocaml header we are limited by Max_wosize, e.g.
		       16M on 32 bit systems). The special representation
		       is an Abstract_tag with zero length, followed
		       by the real length (in words)
		    */
		    
		    if (enable_bigarrays == 2) {
			data_header = dest_cur;
			dest_cur += 2*sizeof(void *);
			data_copy = dest_cur;
			dest_cur += size_aligned;
		    } else if (!simulation) {
			data_header = NULL;
			data_copy = stat_alloc(size_aligned);
		    };

		    if (!simulation) {
			if (dest_cur > dest_end) return (-4);

			/* Initialize header: */
			
			if (data_header != NULL) {
			    data_header1 = Abstract_tag;
			    memcpy(data_header, 
				   (char *) &data_header1,
				   sizeof(header_t));
			    memcpy(data_header + sizeof(header_t),
				   (size_t *) &size_words,
				   sizeof(size_t));
			};

			/* Copy bigarray: */
			
			memcpy(data_copy, b_work->data, size);
			b_copy->data = data_copy;
			b_copy->proxy = NULL;

			/* If the copy is in our own buffer, it is
			   now externally managed.
			*/
			b_copy->flags = 
			    (b_copy->flags & ~CAML_BA_MANAGED_MASK) |
			    (enable_bigarrays == 2 ? 
			     CAML_BA_EXTERNAL :
			     CAML_BA_MANAGED);
		    }
		}

	    } /* if (work_tag < No_scan_tag) */
	} /* if (copy_addr == NULL) */

	/* Switch to next address in q: */
    next:
	code = netsys_queue_take(q, &work_addr);
    } /* while */
    
    /* Second pass. The copied blocks still have fields pointing to the
       original blocks. We fix that now by iterating once over the copied
       memory block.
    */

    if (!simulation) {
	/* fprintf(stderr, "second pass\n"); */
	dest_ptr = dest;
	while (dest_ptr < dest_cur) {
	    copy_header1 = *((header_t *) dest_ptr);
	    copy_tag = Tag_hd(copy_header1);
	    copy_words = Wosize_hd(copy_header1);
	    copy = (value) (dest_ptr + sizeof(void *));
	    
	    if (copy_tag < No_scan_tag) {
		for (i=0; i < copy_words; ++i) {
		    value field = Field(copy, i);
		    if (Is_block (field)) {
			/* It is a pointer. Try to fix it up. */
			code = netsys_htab_lookup(t, (void *) field,
						  &fixup_addr);
			if (code != 0) return code;

			if (fixup_addr != NULL)
			    Field(copy,i) = 
				(value) (((char *) fixup_addr) + addr_delta);
		    }
		}
	    }
	    else if (copy_tag == Abstract_tag && copy_words == 0) {
		/* our special representation for skipping data regions */
		copy_words = ((size_t *) dest_ptr)[1] + 1;
	    };
	    
	    dest_ptr += (copy_words + 1) * sizeof(void *);
	}
    }	

    /* hey, fine. Return result */
    *start_offset = sizeof(void *);
    *bytelen = dest_cur - dest;

    /* fprintf(stderr, "return regularly\n");*/

    return 0;
}
value netsys_init_value(value memv, 
			value offv, 
			value orig,  
			value flags,
			value targetaddrv,
			value target_custom_ops
			)
{
    int code;
    value r;
    intnat start_offset, bytelen;
    int  cflags;
    void *targetaddr;
    char *mem_data;
    char *mem_end;
    intnat off;
    struct named_custom_ops *ops, *old_ops, *next_ops;
    
    code = prep_stat_tab();
    if (code != 0) goto exit;

    code = prep_stat_queue();
    if (code != 0) goto exit;

    off = Long_val(offv);
    if (off % sizeof(void *) != 0) { code=(-2); goto exit; }

    cflags = caml_convert_flag_list(flags, init_value_flags);
    targetaddr = (void *) (Nativeint_val(targetaddrv) + off);

    ops = NULL;
    while (Is_block(target_custom_ops)) {
	value pair;
	old_ops = ops;
	pair = Field(target_custom_ops,0);
	ops = (struct named_custom_ops*) 
	          stat_alloc(sizeof(struct named_custom_ops));
	ops->name = stat_alloc(caml_string_length(Field(pair,0))+1);
	strcmp(ops->name, String_val(Field(pair,0)));
	ops->ops = (void *) Nativeint_val(Field(pair,1));
	ops->next = old_ops;
	target_custom_ops = Field(target_custom_ops,1);
    };

    mem_data = ((char *) Bigarray_val(memv)->data) + off;
    mem_end = mem_data + Bigarray_val(memv)->dim[0];

    /* note: the color of the new values does not matter because bigarrays
       are ignored by the GC. So we pass 0 (white).
    */
    
    code = netsys_init_value_1(stat_tab, stat_queue, mem_data, mem_end, orig, 
			       (cflags & 1) ? 2 : 0, 
			       (cflags & 2) ? 1 : 0, 
			       (cflags & 4) ? 2 : 0,
			       cflags & 8,
			       targetaddr, ops, 0,
			       &start_offset, &bytelen);
    if (code != 0) goto exit;

    unprep_stat_tab();
    unprep_stat_queue();

    while (ops != NULL) {
	next_ops = ops->next;
	stat_free(ops->name);
	stat_free(ops);
	ops = next_ops;
    };
    
    r = caml_alloc_small(2,0);
    Field(r,0) = Val_long(start_offset + off);
    Field(r,1) = Val_long(bytelen);

    return r;

 exit:
    unprep_stat_queue();
    unprep_stat_tab();

    switch(code) {
    case (-1):
	unix_error(errno, "netsys_init_value", Nothing);
    case (-2):
	failwith("Netsys_mem.init_value: Library error");
    case (-4):
	caml_raise_constant(*caml_named_value("Netsys_mem.Out_of_space"));
    default:
	failwith("Netsys_mem.init_value: Unknown error");
    }
}
CAMLprim value netsys_memory_address(value memv)
{
    struct caml_bigarray *mem = Bigarray_val(memv);
    return caml_copy_nativeint((intnat) mem->data);
}
CAMLprim value netsys_as_value(value memv, value offv) 
{
    struct caml_bigarray *b = Bigarray_val(memv);
    return (value) (b->data + Long_val(offv));
}