#include "ansi.h"
#include "hostinfo.h"
#include "host.h"
#include "config.h"

#include <sys/types.h>
#include "files.h"

#include <sys/stat.h>

#ifdef HAS_MMAP
#include <sys/mman.h>
#else
#include <unistd.h>
#include <stdlib.h>
#endif

#undef NULL
#define NULL	0

static char *fnames[MAX_UNIQ_FNAMES];
static int findex;

int
num_files()
{
	return findex;
}

char*
file_name_from_ord(ord)
	int ord;
{
	return fnames[ord];
}

char *
file_name(pos)
	file_pos_t pos;
{
	return fnames[FILE_ORD(pos)];
}

file_pos_t
add_file(path)
	char *path;
{
	file_pos_t i;

	if ((i = find_file(path)) != -1) {
		return i;
	}

	assert(findex < MAX_UNIQ_FNAMES);

	i = findex++;
	fnames[i] = path;

	return (i << LINE_NUMBER_BITS) | 1;
}

file_pos_t
set_file_pos(path, line)
	char *path;
	int line;
{
	file_pos_t pos;

	pos = add_file(path);
	pos = pos & ~((1 << LINE_NUMBER_BITS) - 1);
	return pos | line;
}

file_pos_t
find_file(path)
	char *path;
{
	file_pos_t i;

	for (i = 0; i < findex; i++) {
		if (!strcmp(fnames[i], path)) {
			return (i << LINE_NUMBER_BITS) | 1;
		}
	}

	return -1;
}

size_t 
sizeof_file(fd)
	int fd;
{
	struct stat stat_buf;

	if (fstat(fd, &stat_buf) == -1) {
		return -1;
	}

	return stat_buf.st_size;
}

#ifdef HAS_MMAP			/* Use Unix mmap() and munmap() */
void *
map_file(fd, fsize)
	int fd;
	size_t fsize;
{
	return mmap(0, fsize, PROT_READ, MAP_PRIVATE, fd, 0);
}

int 
unmap_file(addr, len)
	void *addr;
	size_t len;
{
	return munmap(addr, (int)len);
}

#else	/* This system doesn't support mmap() and munmap() */

void *
map_file(fd, fsize)
	int fd;
	size_t fsize;
{
	char *addr;
	int len;

	addr = (char*) malloc(fsize);
	assert(addr != NULL);

	len = read(fd, addr, (unsigned) fsize);
	assert(len == (int)fsize);

	return addr;
}

int 
unmap_file(addr, len)
	void *addr;
	size_t len;
{
	free(addr);
}
#endif


syntax highlighted by Code2HTML, v. 0.9.1