/**********************************************************************
 
	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.

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



#ifndef ___UTILS_H___
#define ___UTILS_H___

#include	"machine/include.h"
#include	"long_char.h"
#include	"xllisp.h"
#include	"u_file.h"
#include	"log.h"


typedef struct thread_area_header {
	struct thread_area_header *	next;
	unsigned int			tid;
} THREAD_AREA_HEADER;

typedef struct thread_area {
	struct thread_area *	next;
	void			(*close_gc)();
	int			area_size;
	int			ent_size;
	THREAD_AREA_HEADER **	ent;
} THREAD_AREA;

typedef struct div_str {
	short		term;
#define DST_TERMINATE	0
#define DST_DATA	1
	char		type;
#define DST_STRING	0
#define DST_LIST	1
	char		flags;
#define DSF_DONTFREE	0
#define DSF_FREE	1
	union {
		L_CHAR *		str;
		struct div_str *	ds;
	}		d;
} DIV_STR;

typedef struct nested_lock {
	int		tid;
	int		cnt;
} NESTED_LOCK;


typedef struct waitsync_node {
	struct waitsync_node *	server_next;
	struct waitsync_node *	client_next;
	struct waitsync_server *	server;
	struct waitsync_client *	client;
} WAITSYNC_NODE;

typedef struct waitsync_server {
	WAITSYNC_NODE *		list;
	int			wait_type;
#define WST_WAIT		0
#define WST_FORCE_STOP		1
} WAITSYNC_SERVER;

typedef struct waitsync_client {
	int			count;
	WAITSYNC_NODE *		list;
} WAITSYNC_CLIENT;

typedef struct attr_table {
	char *		flag_name;
	int		flag;
} ATTR_TABLE;

typedef struct pri_ctl_thread {
	struct pri_ctl_thread *	next;
	int			tid;
	int			pri;
} PRI_CTL_THREAD;

typedef struct pri_ctl {
	int			base_pri;
	int			ctl_pri;
	PRI_CTL_THREAD *	threads;
} PRI_CTL;

void init_thread_area(THREAD_AREA * ta,THREAD_AREA * ta_param);
void * get_my_area(THREAD_AREA *);
void close_thread_area();
int scan_ta(THREAD_AREA * ta,int (*func)(),void * work);

char * xx_copy_str(char *,char *,int);
#define copy_str(x)	xx_copy_str(x,__FILE__,__LINE__)


L_CHAR * xx_ll_copy_str(L_CHAR *,char *,int);
#define ll_copy_str(p)	xx_ll_copy_str((p),__FILE__,__LINE__)
L_CHAR * _xx_nl_copy_str_1(CODE_METHOD *,char *,char*,int);
L_CHAR * _xx_nl_copy_str_2(CODE_METHOD *,char *,char*,int);



#define xx_nl_copy_str(cm,p,f,ln)	\
	((#p)[0] == '\"' ? _xx_nl_copy_str_2((cm),(p),(f),(ln)) : \
			_xx_nl_copy_str_1((cm),(p),(f),(ln)))
#define nl_copy_str(cm,p)	xx_nl_copy_str((cm),(p),__FILE__,__LINE__)

char * ln_copy_str(CODE_METHOD *,L_CHAR*);
int get_url(URL *,L_CHAR *);
void copy_url(URL*,URL*);
int xx_get_url2(URL *,L_CHAR *,char*,int);
#define get_url2(u,str)		xx_get_url2(u,str,__FILE__,__LINE__)
int url_cmp(URL *,URL *);
int url_cmp_str(URL*,URL*);
void zero_url(URL *);
void free_url(URL *);
L_CHAR * get_url_str2(URL *);
L_CHAR * get_url_filepath(URL *);
int get_wkp(L_CHAR *);
char* get_proto_name(int port);
void xx_set_buffer(void *,char *,int);
#define set_buffer(x)	xx_set_buffer(x,__FILE__,__LINE__)
char * get_preference_path();
char * get_peripheral_path();
int get_field(XL_SEXP * s,...);
int launch_proc(
	char * str,
	char ** argv,
	STREAM ** stp,
	char * close_flags,
	char * ret_str_parent,
	char * ret_str_children);
void divide_string(DIV_STR * str,L_CHAR * div);
void init_tick();
void new_tick(void (*func)(int),int interval,int data);
void del_tick(void (*func)(int));
void del_tick_with_data(void (*func)(),int);
void new_timeout(int,int);
void del_timeout(int);
void timeout_exit(int,int,int (*)());
int get_xltime();
char * get_xltime_str(unsigned int t,int fmt);
int check_pid(int,char*);
L_CHAR * compose_url(L_CHAR * path1,L_CHAR * path2);
int stabilizer();
void exit_stabilizer(char);
int cmp_part(L_CHAR * target,L_CHAR * data);
L_CHAR * url_regulation(L_CHAR *);
char * which(char*);
char * xlwhich(char*);
L_CHAR * get_script(L_CHAR *,L_CHAR *);
void set_script_path(L_CHAR * script);
L_CHAR * get_script_path();
L_CHAR * optimize_path(L_CHAR*);
L_CHAR * get_absolute_path(L_CHAR*);
L_CHAR * get_relative_path(L_CHAR * path);

char * get_locale();
int u_mkdir(char*,int);
DIR * u_opendir(char *);
int b_hostcmp(char *,int,char *, int);

void http_system(char *,int,char *);
struct dirent * u_readdir(DIR * dp);

extern char * command_arg;

void u_rm(char * ,int);
#define RMF_REC		0x00000001
#define RMF_FILE	0x00000002
#define RMF_DIR		0x00000004

#define E_DB_FORMAT		(-3)
#define E_NO_DATA		(-2)
#define E_TYPE_MISSMATCH	(-1)

#define C_CANCEL	3

NESTED_LOCK * new_nlock();
void nlock_task(NESTED_LOCK *);
void unnlock_task(NESTED_LOCK *);
void destroy_nlock(NESTED_LOCK*);

STREAM * bl_new_connection(
	int * cerr,
	char * hostname,
	int ip,
	short port,
	int (*func)(),
	void * work);

void gcv_url(URL *);
char * change_delim_str(const char * buf);
L_CHAR * change_delim_l_char(const L_CHAR * buf);
char * normalize_delim_str(const char * buf);


void set_cpu_thr_type(int type);
void set_cpu_msg(int pos);

void
waitsync_ack(WAITSYNC_CLIENT * c,WAITSYNC_SERVER * s,int);
void
waitsync_wakeup(WAITSYNC_SERVER * s);
int
waitsync_sleep(WAITSYNC_CLIENT * c);
void
waitsync_clear(WAITSYNC_CLIENT * c);


void memory_watchdog(void(*)());

int get_attr_flags(int *,L_CHAR *,ATTR_TABLE *);

L_CHAR *xx_safety_string(L_CHAR * str,char * __file,int __line);
#define safety_string(str) xx_safety_string(str,__FILE__,__LINE__);

void er_panic(char*);
void er_panic_x(char*);
int stabilizer();
void exit_stabilizer(char ch);
void init_gv_cpu(XLISP_ENV * e);
void gv_cpu_direct();
L_CHAR * compose_path(L_CHAR * d1,L_CHAR * d2);
void mcopy_url(URL * a,URL * b);
void print_div_str(DIV_STR * str);
void  divide_string_str(DIV_STR * str,L_CHAR * div);
void free_div_str_list(DIV_STR ds);
void gf_conv_ii(XL_SEXP * s,void * d,void * d2);
void gf_conv_di(XL_SEXP * s,void * d,void * d2);
void gf_conv_if(XL_SEXP * s,void * d,void * d2);
void gf_conv_df(XL_SEXP * s,void * d,void * d2);
void gf_conv_id(XL_SEXP * s,void * d,void * d2);
void gf_conv_dd(XL_SEXP * s,void * d,void * d2);
void gf_conv_ss(XL_SEXP * s,void * d);
void gf_conv_sexp(XL_SEXP * s,void * d);
int set_data(XL_SEXP * s,
	 L_CHAR * f,int buf_type,void * d,void * d2,int * r);
void make_regular(L_CHAR ** str);
L_CHAR * seek_ptr(L_CHAR * ptr);

void init_set_buffer();

void init_cpu_msg();

void change_tick(int interval);
void new_timeout_func(int key);
#ifndef m_mkdir
#ifndef _m_mkdir
int m_mkdir(char *path,...);
#endif
#endif
int _cmp(L_CHAR * a,L_CHAR *b);
int _cmp_server(L_CHAR * s1,L_CHAR * s2);

void free_div_str(DIV_STR ds);

int launch_proc_stdio(
	STREAM ** st_in,
	STREAM ** st_out,
	STREAM ** st_err,
	char * str);
void launch_devnull(char * proc);
void launch_normal(char * proc);
int launch_proc_stdio(
	STREAM ** st_in,
	STREAM ** st_out,
	STREAM ** st_err,
	char * str);
void _waitsync_ack(WAITSYNC_CLIENT * c,WAITSYNC_SERVER * s,int);
void _waitsync_wakeup(WAITSYNC_SERVER * s);
void _waitsync_clear(WAITSYNC_CLIENT * c);
int _waitsync_sleep(WAITSYNC_CLIENT * c);

int is_safe_as_filename(char* name);

int push_pri(int);
int push_pri_pctl(PRI_CTL * target);
void enter_pri_ctl(PRI_CTL * target,PRI_CTL_THREAD *);
void exit_pri_ctl(PRI_CTL * target);
void clean_empty_dir(L_CHAR * dir,int len);

void force_scheduling();
XL_SEXP*
get_xlrc(char * home,char * file,L_CHAR * symbol);
char * get_homepath();
char * get_root_preference_path();


#endif
