/**********************************************************************
 
	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	"xlerror.h"
#include	"utils.h"
#include	"xl.h"
#include	"memory_debug.h"
#include	"xldir.h"

XL_SEXP * xl_FindFile();

void
init_FindFile(XLISP_ENV * env)
{
	set_env(env,l_string(std_cm,"FindFile"),
		get_func_prim(xl_FindFile,FO_APPLICATIVE,0,2,4));
}


XL_SEXP *
get_ret_dir_list(DIR_LIST * d)
{
XL_SEXP * ret;
void gc_gb_sexp();
	gc_push(0,0,"get_ret_dir_list");
	ret = 0;
	for ( ; d ; d = d->next )
		ret = cons(
			n_get_string(d->name),
			ret);
	gc_pop(ret,gc_gb_sexp);
	return ret;
}

int
get_condition(L_CHAR * cond)
{
int flags;
L_CHAR * _c, * p, * q;
	flags = 0;
	_c = ll_copy_str(cond,123);
	for ( p = _c ; *p ; ) {
		for ( q = p ; *q && *q != ',' ; q ++ );
		if ( *q )
			*q ++ = 0;
		if ( l_strcmp(p,l_string(std_cm,"dir")) == 0 )
			flags |= DLF_DIR;
		else if ( l_strcmp(p,l_string(std_cm,"file")) == 0 )
			flags |= DLF_FILE;
		else if ( l_strcmp(p,l_string(std_cm,"exist")) == 0 )
			flags |= DLF_T_EXIST;
		else if ( l_strcmp(p,l_string(std_cm,"notexist")) == 0 )
			flags |= DLF_T_NOTEXIST;
		else if ( l_strcmp(p,l_string(std_cm,"DCexist")) == 0 )
			flags |= DLF_T_EXIST_D;
		else if ( l_strcmp(p,l_string(std_cm,"touch")) == 0 )
			flags |= DLF_T_TOUCH;
		else if ( l_strcmp(p,l_string(std_cm,"notouch")) == 0 )
			flags |= DLF_T_NOTOUCH;
		else if ( l_strcmp(p,l_string(std_cm,"DCtimestamp"))
				 == 0 )
			flags |= DLF_T_STAMP_D;
		else 
			return -1;
		p = q;
	}
	d_f_ree(_c);
	if ( (flags & DLF_TYPE_M) == 0 )
		flags |= DLF_DIR|DLF_FILE;
	if ( (flags & DLF_T_EXIST_M) == 0 )
		flags |= DLF_T_EXIST_D;
	if ( (flags & DLF_T_STAMP_M) == 0 )
		flags |= DLF_T_STAMP_D;
	return flags;
}

XL_SEXP *
xl_FindFile(XLISP_ENV * env,XL_SEXP * s,
	XLISP_ENV * a,XL_SYM_FIELD * sf)
{
L_CHAR * cond;
int _cond;
DIR_LIST * ret;
XL_SEXP * w,* b,* t;
XL_SEXP * _ret;
L_CHAR * prefix;
	prefix = 0;
	cond = get_sf_attribute(sf,
			l_string(std_cm,"condition"));
	if ( cond == 0 )
		_cond = DLF_FILE|DLF_DIR|DLF_T_EXIST_D|DLF_T_STAMP_D;
	else {
		_cond = get_condition(cond);
		if ( _cond == -1 )
			goto inv_param_attr;
	}

	prefix = get_sf_attribute(sf,
			l_string(std_cm,"prefix"));
	w = get_el(s,1);
	if ( get_type(w) != XLT_STRING )
		goto type_missmatch;
	switch ( list_length(s) ) {
	case 2:
		if ( prefix ) {
			ret = get_dir(
				n_string(std_cm,w->string.data),
				0,0,
				n_string(std_cm,prefix),
				_cond);
		}
		else {
			ret = get_dir(
				n_string(std_cm,w->string.data),
				0,0,
				0,
				_cond);
		}
		break;
	case 4:
		b = get_el(s,2);
		if ( get_type(b) != XLT_STRING )
			goto type_missmatch;
		t = get_el(s,3);
		if ( get_type(t) != XLT_STRING )
			goto type_missmatch;
		ret = get_dir(
			n_string(std_cm,w->string.data),
			n_string(std_cm,b->string.data),
			n_string(std_cm,t->string.data),
			n_string(std_cm,prefix),
			_cond);
		break;
	default:
		goto inv_param;
	}
	_ret = get_ret_dir_list(ret);
	free_dir_list(ret);
	return _ret;
type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"FindFile"),
		n_get_string("type_missmatch"));
inv_param:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"FindFile"),
		n_get_string("invalid parameter length"));
inv_param_attr:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"FindFile"),
		n_get_string("invalid attribute parameter (condition)"));
}
