#line 1 "/tmp/pkgbuild/lang/ecl/work/ecl-16.1.2/src/c/ffi/mmap.d"
/* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*- */
/* vim: set filetype=c tabstop=8 shiftwidth=4 expandtab: */

/*
    mmap.d -- Mapping of binary files.
*/
/*
    Copyright (c) 2011, Juan Jose Garcia Ripoll.

    ECL is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    See file '../Copyright' for full details.
*/

#include <ecl/ecl.h>
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
#include <ecl/ecl-inl.h>
#include <ecl/internal.h>

#line 33
cl_object si_mmap(cl_narg narg, cl_object filename, ...)
{
#line 33

#line 35
	const cl_env_ptr the_env = ecl_process_env();
#line 35
	static cl_object KEYS[7] = {(cl_object)(cl_symbols+1268), (cl_object)(cl_symbols+1284), (cl_object)(cl_symbols+1221), (cl_object)(cl_symbols+1227), (cl_object)(cl_symbols+1249), (cl_object)(cl_symbols+1247), (cl_object)(cl_symbols+1239)};
	cl_object length;
	cl_object offset;
	cl_object direction;
	cl_object element_type;
	cl_object if_exists;
	cl_object if_does_not_exist;
	cl_object external_format;
#line 35
	cl_object KEY_VARS[14];
#line 35
	ecl_va_list ARGS;
	ecl_va_start(ARGS, filename, narg, 1);
#line 35
	if (ecl_unlikely(narg < 1)) FEwrong_num_arguments(ecl_make_fixnum(1853));
#line 35
	cl_parse_key(ARGS, 7, KEYS, KEY_VARS, NULL, 0);
#line 35
	if (KEY_VARS[7]==ECL_NIL) {
#line 35
	  length = ECL_NIL;
	} else {
#line 35
	  length = KEY_VARS[0];
	}
#line 35
	if (KEY_VARS[8]==ECL_NIL) {
#line 35
	  offset = ecl_make_fixnum(0);
	} else {
#line 35
	  offset = KEY_VARS[1];
	}
#line 35
	if (KEY_VARS[9]==ECL_NIL) {
#line 35
	  direction = ECL_SYM(":INPUT",1259);
	} else {
#line 35
	  direction = KEY_VARS[2];
	}
#line 35
	if (KEY_VARS[10]==ECL_NIL) {
#line 35
	  element_type = ECL_SYM("BASE-CHAR",120);
	} else {
#line 35
	  element_type = KEY_VARS[3];
	}
#line 35
	if (KEY_VARS[11]==ECL_NIL) {
#line 35
	  if_exists = ECL_SYM(":NEW-VERSION",1280);
	} else {
#line 35
	  if_exists = KEY_VARS[4];
	}
#line 35
	if (KEY_VARS[12]==ECL_NIL) {
#line 35
	  if_does_not_exist = ECL_SYM(":ERROR",1232);
	} else {
#line 35
	  if_does_not_exist = KEY_VARS[5];
	}
#line 35
	if (KEY_VARS[13]==ECL_NIL) {
#line 35
	  external_format = ECL_SYM(":DEFAULT",1218);
	} else {
#line 35
	  external_format = KEY_VARS[6];
	}
#line 35
#ifdef HAVE_SYS_MMAN_H
{
        cl_object output, stream;
        int c_prot, c_flags, fd;
        size_t len;
        void *pa;
        if (direction == ECL_SYM(":INPUT",1259))
                c_prot = PROT_READ;
        else if (direction == ECL_SYM(":OUTPUT",1287))
                c_prot = PROT_WRITE;
        else if (direction == ECL_SYM(":IO",1265))
                c_prot = PROT_READ | PROT_WRITE;
        else
                c_prot = PROT_NONE;
        if (Null(filename)) {
                c_flags = MAP_ANON | MAP_PRIVATE;
                fd = -1;
                len = ecl_to_unsigned_integer(length);
                stream = ECL_NIL;
        } else {
                c_flags = MAP_SHARED;
                stream = cl_open(13, filename,
                                 ECL_SYM(":DIRECTION",1221), direction,
                                 ECL_SYM(":ELEMENT-TYPE",1227), element_type,
                                 ECL_SYM(":IF-EXISTS",1249), if_exists,
                                 ECL_SYM(":IF-DOES-NOT-EXIST",1247), if_does_not_exist,
                                 ECL_SYM(":EXTERNAL-FORMAT",1239), ECL_SYM(":DEFAULT",1218),
                                 ECL_SYM(":CSTREAM",1329), ECL_NIL);
                fd = ecl_to_int(si_file_stream_fd(stream));
                if (Null(length))
                        len = ecl_to_unsigned_integer(ecl_file_length(stream));
                else
                        len = ecl_to_unsigned_integer(length);
        }
        output = si_make_vector(element_type, ecl_make_fixnum(0), ECL_NIL,
                                ECL_NIL, ECL_NIL, ECL_NIL);
        pa = mmap(0, len, c_prot, c_flags, fd,
                  ecl_integer_to_off_t(offset));
        if (pa == MAP_FAILED) {
                FElibc_error("EXT::MMAP failed.", 0);
        } else {
                output->base_string.self = pa;
                output->base_string.dim =
                        output->base_string.fillp = len;
        }
        {
#line 80
	#line 80
	cl_object __value0 = CONS(output, stream);
#line 80
	the_env->nvalues = 1;
#line 80
	return __value0;
#line 80
}

}
#else
{
        cl_object output, vector;
        if (Null(filename)) {
                output = si_make_vector(element_type, length, ECL_NIL,
                                ECL_NIL, ECL_NIL, ECL_NIL);
        } else {
                cl_object stream = cl_open(13, filename,
                                           ECL_SYM(":DIRECTION",1221), direction,
                                           ECL_SYM(":ELEMENT-TYPE",1227), element_type,
                                           ECL_SYM(":IF-EXISTS",1249), if_exists,
                                           ECL_SYM(":IF-DOES-NOT-EXIST",1247), if_does_not_exist,
                                           ECL_SYM(":EXTERNAL-FORMAT",1239), ECL_SYM(":PASS-THROUGH",1781),
                                           ECL_SYM(":CSTREAM",1329), ECL_T);
                if (Null(length))
                        length = ecl_file_length(stream);
                else
                        length = ecl_to_unsigned_integer(length);
                output = si_make_vector(element_type, length, ECL_NIL,
                                        ECL_NIL, ECL_NIL, ECL_NIL);
                cl_read_sequence(2, output, stream);
                cl_close(1, stream);
        }
        {
#line 105
	#line 105
	cl_object __value0 = output;
#line 105
	the_env->nvalues = 1;
#line 105
	return __value0;
#line 105
}

}
#endif
}

cl_object
si_mmap_array(cl_object map)
{
#ifdef HAVE_SYS_MMAN_H
        {
#line 114
	const cl_env_ptr the_env = ecl_process_env();
#line 114
	#line 114
	cl_object __value0 = cl_car(map);
#line 114
	the_env->nvalues = 1;
#line 114
	return __value0;
#line 114
}
;
#else
        {
#line 116
	const cl_env_ptr the_env = ecl_process_env();
#line 116
	#line 116
	cl_object __value0 = map;
#line 116
	the_env->nvalues = 1;
#line 116
	return __value0;
#line 116
}
;
#endif
}

cl_object
si_munmap(cl_object map)
{
#ifdef HAVE_SYS_MMAN_H
        cl_object array = cl_car(map);
        cl_object stream = cl_cdr(map);
        int code = munmap(array->base_string.self, array->base_string.dim);
        if (code < 0) {
                FElibc_error("Error when unmapping file.", 0);
        }
        cl_close(1, stream);
#endif
        {
#line 132
	const cl_env_ptr the_env = ecl_process_env();
#line 132
	#line 132
	cl_object __value0 = ECL_NIL;
#line 132
	the_env->nvalues = 1;
#line 132
	return __value0;
#line 132
}

}
