/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#include	<fcntl.h>
#include	"xlerror.h"
#include	"memory_debug.h"
#include	"xl.h"
#include	"long_char.h"
#include	"utils.h"
#include	"u_file.h"

XL_GETFILE * getfile_hash[GETFILE_HASH_SIZE];
L_CHAR * agent_name;
L_CHAR * docs_path;
L_CHAR * sys_path;

void
free_gf_cmd(XL_GF_CMD * c)
{
XL_GF_CMD * c1;
	for ( ; c ; ) {
		c1 = c->next;
		d_f_ree(c->cmd);
		d_f_ree(c);
		c = c1;
	}
}


unsigned int
getfile_hash_key(L_CHAR * prefix)
{
unsigned int key;
	key = 0;
	for ( ; *prefix ; prefix ++ )
		key += *prefix;
	return key%GETFILE_HASH_SIZE;
}


XL_GETFILE *
search_getfile(L_CHAR * prefix,L_CHAR * agent)
{
unsigned int key;
XL_GETFILE * gf;
	key = getfile_hash_key(prefix);
	for ( gf = getfile_hash[key];
			gf;
			gf = gf->next )
		if ( l_strcmp(gf->prefix,prefix) == 0 &&
			l_strcmp(gf->agent,agent) == 0 )
			return gf;
	return 0;
}


XL_GETFILE *
search_getfile_by_prefix(L_CHAR * prefix,XL_GETFILE * gfin)
{
unsigned int key;
XL_GETFILE * gf;
	if ( gfin == 0 ) { 
		key = getfile_hash_key(prefix);
		gf = getfile_hash[key];
	}
	else {
		gf = gfin->next;
	}
	for ( ;	gf ; gf = gf->next )
		if ( l_strcmp(gf->prefix,prefix) == 0 )
			return gf;
	return 0;
}



void
insert_getfile(L_CHAR * prefix,L_CHAR * agent,L_CHAR * mode,int flags,
	XL_SEXP * cmd)
{
XL_GETFILE * gf;
int key;
XL_GF_CMD * gfc;
XL_SEXP * c;
	gf = search_getfile(prefix,agent);
	if ( gf == 0 ) {
		gf = d_alloc(sizeof(*gf));
		gf->prefix = ll_copy_str(prefix);
		gf->agent = ll_copy_str(agent);
		gf->mode = ll_copy_str(mode);
		gf->flags = flags;
		key = getfile_hash_key(prefix);
		gf->next = getfile_hash[key];
		getfile_hash[key] = gf;
	}
	else {
		if ( gf->mode )
			d_f_ree(gf->mode);
		gf->mode = ll_copy_str(mode);
		gf->flags = flags;
		free_gf_cmd(gf->cmd);
	}
	gf->cmd = 0;
	for ( ; get_type(cmd) ; cmd = cdr(cmd) ) {
		c = car(cmd);
		if ( get_type(c) != XLT_STRING )
			er_panic("insert_getfile");
		gfc = d_alloc(sizeof(*gfc));
		gfc->cmd = ll_copy_str(c->string.data);
		gfc->next = gf->cmd;
		gf->cmd = gfc;
	}
}



XL_SEXP *
get_path(
	L_CHAR * target[2],
	XL_GETFILE ** gfp,
	L_CHAR * _filename,XL_SEXP * s,L_CHAR * func_name)
{
int p,len1,len2;
L_CHAR * ptr;
XL_GETFILE * gf;
int line;
XL_FILE * file;
	if ( s ) {
		file = s->h.file;
		line = s->h.line;
	}
	else {
		file = 0;
		line = 0;
	}
	if ( docs_path == 0 || agent_name == 0 )
		return get_error(
			file,
			line,
			XLE_SYSTEM_INTERNAL,
			func_name,
			n_get_string("dbpath and agent name is undefined"));

	p = l_strlen(_filename)-1;
	for ( ; p >= 0 && _filename[p] != '.' &&
			_filename[p] != '/' ; p -- );
	if ( p < 0 || _filename[p] == '/' )
		return get_error(
			file,
			line,
			XLE_PROTO_INV_PARAM,
			func_name,
			n_get_string("invalid file path"));
	if ( _filename[0] != '/' )
		return get_error(
			file,
			line,
			XLE_PROTO_INV_PARAM,
			func_name,
			n_get_string("invalid file path"));
	for ( ptr = _filename; *ptr ; ptr ++ ) {
		if ( *ptr != '.' )
			continue;
		if ( ptr[1] == '.' )
			return get_error(
				file,
				line,
				XLE_PROTO_INV_PARAM,
				func_name,
				n_get_string("invalid file path"));
	}

	gf = search_getfile(&_filename[p],agent_name);
	if ( gf == 0 )
		return get_error(
			file,
			line,
			XLE_PROTO_UNDEF_RESOURCE,
			func_name,
			n_get_string("undefined prefix"));
	*gfp = gf;
	len2 = l_strlen(_filename);

	target[0] = target[1] = 0;
	switch ( gf->flags & XLGFM_XLDIR ) {
	case XLGF_XLSYS_ONLY:
		if ( sys_path == 0 )
			break;
		len1 = l_strlen(sys_path);
		target[0] = d_alloc((len1+len2+1)*sizeof(L_CHAR));
		memcpy(target[0],sys_path,len1*sizeof(L_CHAR));
		memcpy(&target[0][len1],_filename,(len2+1)*sizeof(L_CHAR));
		break;
	case XLGF_XLDOC_ONLY:
		len1 = l_strlen(docs_path);
		target[0] = d_alloc((len1+len2+1)*sizeof(L_CHAR));
		memcpy(target[0],docs_path,len1*sizeof(L_CHAR));
		memcpy(&target[0][len1],_filename,(len2+1)*sizeof(L_CHAR));
		break;
	case XLGF_XLSYS_PRECEDENCE:
		len1 = l_strlen(sys_path);
		target[0] = d_alloc((len1+len2+1)*sizeof(L_CHAR));
		memcpy(target[0],sys_path,len1*sizeof(L_CHAR));
		memcpy(&target[0][len1],_filename,(len2+1)*sizeof(L_CHAR));

		len1 = l_strlen(docs_path);
		target[1] = d_alloc((len1+len2+1)*sizeof(L_CHAR));
		memcpy(target[1],docs_path,len1*sizeof(L_CHAR));
		memcpy(&target[1][len1],_filename,(len2+1)*sizeof(L_CHAR));
		break;
	case XLGF_XLDOC_PRECEDENCE:
		len1 = l_strlen(sys_path);
		target[1] = d_alloc((len1+len2+1)*sizeof(L_CHAR));
		memcpy(target[1],sys_path,len1*sizeof(L_CHAR));
		memcpy(&target[1][len1],_filename,(len2+1)*sizeof(L_CHAR));

		len1 = l_strlen(docs_path);
		target[0] = d_alloc((len1+len2+1)*sizeof(L_CHAR));
		memcpy(target[0],docs_path,len1*sizeof(L_CHAR));
		memcpy(&target[0][len1],_filename,(len2+1)*sizeof(L_CHAR));
		break;
	}
	return 0;
}

L_CHAR *
get_synth_path(L_CHAR * b,L_CHAR * filepath)
{
L_CHAR * path;
int len,len_f;
	path = ll_copy_str(b);
	len = l_strlen(path);
	len_f = l_strlen(filepath);
	path = d_re_alloc(path,(len+len_f+1)*sizeof(L_CHAR));
	memcpy(&path[len],filepath,(len_f+1)*sizeof(L_CHAR));
	return path;
}

int
path_check(L_CHAR * filepath)
{
L_CHAR * p;
char * p1,* p2;
int f;
int ret;
	ret = 0;
	p = get_synth_path(docs_path,filepath);
	p2 = change_delim_str(p1 = n_string(std_cm,p));
	f = u_open(p2,O_RDONLY);
	if ( p2 != p1 )
		d_f_ree(p2);
	d_f_ree(p);
	if ( f >= 0 ) {
		u_close(f);
		ret |= 1;
	}
	p = get_synth_path(sys_path,filepath);
	p2 = change_delim_str(p1 = n_string(std_cm,p));
	f = u_open(p2,O_RDONLY);
	if ( p2 != p1 )
		d_f_ree(p2);
	d_f_ree(p);
	if ( f >= 0 ) {
		u_close(f);
		ret |= 2;
	}
	return ret;
}



