1 /*
2  * kyureki.c -- ����(����������)��ơ��֥������
3  *
4  * Copyright (C) 1991,1997,1999,2001 by Yoshifumi Mori
5  *
6  * tab:4
7  */
8 
9 #include "cdefs.h"
10 #include "extern.h"
11 
12 /*
13  * �ե�����'kyureki.tbl' ���ɤ߹��ߤ����ʤ�����
14  * struct KYUREKI_T �� 4bytes �ˤʤ�ʤ����ϡ�
15  * ��¢����ơ��֥����Ѥ��뤳�ȡ�
16  *
17  * unix �ξ��ϡ�����ο��ۤ�ʤ��Τǻ��ꤹ�������ɤ����⡣
18  */
19 #if 0
20 #define INTERNAL_KYUREKI_TBL	/* ��¢����ơ��֥������� */
21 #endif
22 
23 #ifdef INTERNAL_KYUREKI_TBL
24 #include "kyutbl.c"
25 #else /* !INTERNAL_KYUREKI_TBL */
26 /*
27  * struct KYUREKI_T ��ɬ�� 4bytes �Ǥʤ���Фʤ�ʤ�
28  * �����Ϥˤ�äƤ� 4bytes �ˤʤ�ʤ���礬���롣
29  * �����ͤʻ��ϡ���¢����ơ��֥����Ѥ��롣
30  */
31 #ifdef _T_BIG_ENDIAN_BITFIELD
32 #ifdef _T_BITFIELD_USE_UNSIGNED_INT
33 struct KYUREKI_T {
34 	unsigned char	year;
35 	unsigned char	month;
36 	unsigned char	day;
37 	unsigned int	leap    : 1;
38 	unsigned int	        : 1;
39 	unsigned int	offset  : 2;
40 	unsigned int	month_k : 4;
41 };
42 #else /* bitfield unsigned char non ANSI-C */
43 struct KYUREKI_T {
44 	unsigned char	year;
45 	unsigned char	month;
46 	unsigned char	day;
47 	unsigned char	leap    : 1;
48 	unsigned char	        : 1;
49 	unsigned char	offset  : 2;
50 	unsigned char	month_k : 4;
51 };
52 #endif /* !_T_BITFIELD_USE_UNSIGNED_INT */
53 #endif /* _T_BIG_ENDIAN_BITFIELD */
54 #ifdef _T_LITTLE_ENDIAN_BITFIELD
55 #ifdef _T_BITFIELD_USE_UNSIGNED_INT
56 struct KYUREKI_T {
57 	unsigned char	year;
58 	unsigned char	month;
59 	unsigned char	day;
60 	unsigned int	month_k : 4;
61 	unsigned int	offset  : 2;
62 	unsigned int	        : 1;
63 	unsigned int	leap    : 1;
64 };
65 #else /* bitfield unsigned char non ANSI-C */
66 struct KYUREKI_T {
67 	unsigned char	year;
68 	unsigned char	month;
69 	unsigned char	day;
70 	unsigned char	month_k : 4;
71 	unsigned char	offset  : 2;
72 	unsigned char	        : 1;
73 	unsigned char	leap    : 1;
74 };
75 #endif /* !_T_BITFIELD_USE_UNSIGNED_INT */
76 #endif /* _T_LITTLE_ENDIAN_BITFIELD */
77 
78 #define MAGIC_KYUREKI	0x241A	/* kyureki.tbl magic number */
79 
80 struct TBL_HEAD {
81 	short	magic;
82 	short	rev;
83 	short	base_year;
84 	short	maxtblcnt;
85 	char	pad[8];
86 };
87 
88 static int	base_year;
89 static int	max_tblsize;
90 static int	loading_flag = FALSE;
91 static int	loading_err = FALSE;
92 static struct KYUREKI_T FAR *kyureki_tbl;
93 #endif /* !INTERNAL_KYUREKI_TBL */
94 
95 static const char	*rokuyou_name[6] = {
96 	"�辡", "ͧ��", "����", "ʩ��", "���", "�ָ�"
97 };
98 
99 #ifndef INTERNAL_KYUREKI_TBL
100 /*
101  * �����Ѵ��ơ��֥���ɤ߹���
102  *
103  * return value:
104  *   TRUE  �ɤ߹��ߴ�λ
105  *   FALSE �ɤ߹��ߥ��顼
106  */
107 static
loading_tbl(void)108 int loading_tbl(void)
109 {
110 	const char	*filepath;
111 	struct TBL_HEAD	tblhead;
112 	int		ifd;
113 	long	fsize;
114 #ifdef _T_SEPARATE_LOAD
115 	char FAR	*kp;
116 	int		rsize;
117 	char	rbuf[256];
118 #endif
119 
120 	if (loading_flag != FALSE) {
121 		return (TRUE);
122 	}
123 	if (loading_err != FALSE) {	/* 1���ɤ߹��߼��� */
124 		return (FALSE);
125 	}
126 
127 	filepath = search_filepath("kyureki.tbl");
128 	if (filepath == NULL) {
129 		goto load_err2;
130 	}
131 	ifd = open(filepath, _T_OPENFLAG);
132 	if (ifd == -1) {
133 		goto load_err2;
134 	}
135 
136 	fsize = lseek(ifd, 0L, SEEK_END);
137 	lseek(ifd, 0L, SEEK_SET);
138 	if (fsize < sizeof(tblhead) ||
139 	    read(ifd, &tblhead, sizeof(tblhead)) != sizeof(tblhead)) {
140 load_err:;
141 		close(ifd);
142 		errprint("search_kyureki", ERR_PANIC, "kyureki.tbl ���۾�Ǥ�");
143 load_err2:;
144 		loading_err = TRUE;
145 		return (FALSE);
146 	}
147 
148 #ifdef _T_LITTLE_ENDIAN
149 	swab((char *)&tblhead, (char *)&tblhead, sizeof(tblhead));
150 #endif
151 
152 	if (tblhead.magic != MAGIC_KYUREKI ||
153 	    fsize != (tblhead.maxtblcnt * sizeof(struct KYUREKI_T) + sizeof(tblhead))) {
154 		goto load_err;
155 	}
156 	base_year = tblhead.base_year;
157 	max_tblsize = tblhead.maxtblcnt;
158 
159 	fsize -= sizeof(tblhead);
160 	kyureki_tbl = XMALLOC(fsize);
161 
162 #ifdef _T_SEPARATE_LOAD
163 	kp = (char FAR *)kyureki_tbl;
164 
165 	while (fsize > 0L) {
166 		if (fsize > sizeof(rbuf)) {
167 			rsize = sizeof(rbuf);
168 		} else {
169 			rsize = fsize;
170 		}
171 		if (read(ifd, rbuf, rsize) != rsize) {
172 			XFREE(kyureki_tbl);
173 			goto load_err;
174 		}
175 		FMEMCPY(kp, (char FAR *)rbuf, rsize);
176 		kp += rsize;
177 		fsize -= rsize;
178 	}
179 #else /* !_T_SEPARATE_LOAD */
180 	if (read(ifd, kyureki_tbl, fsize) != fsize) {
181 		XFREE(kyureki_tbl);
182 		goto load_err;
183 	}
184 #endif /* !_T_SEPARATE_LOAD */
185 
186 	close(ifd);
187 
188 	loading_flag = TRUE;
189 
190 	return (TRUE);
191 }
192 #endif /* !INTERNAL_KYUREKI_TBL */
193 
194 /*
195  * �ơ��֥��ꡢ�������դ˺Ǥ�ᤤ�ǡ�����������
196  *
197  * return value:
198  *   �ơ��֥�ΰ���(index)
199  *   �ơ��֥���ϰϳ����ޤ��� kyureki.tbl ���ɤ߹��ߥ��顼
200  *   �ξ��ϡ�-1 ���֤�
201  *
202  * use file: kyureki.tbl
203  */
204 static
search_kyureki(int (* comp_func)(int index,int year,int month,int day,int leap),int year,int month,int day,int leap)205 int search_kyureki(int (*comp_func)(int index, int year, int month, int day, int leap), int year, int month, int day, int leap)
206 {
207 	int	left;
208 	int	right;
209 	int	middle;
210 	int	d;
211 
212 #ifndef INTERNAL_KYUREKI_TBL
213 	if (loading_flag == FALSE && loading_tbl() == FALSE) {
214 		return (-1);
215 	}
216 #endif
217 
218 	left = 0;
219 	right = max_tblsize - 1;
220 
221 	d = (*comp_func)(left, year, month, day, leap);
222 	if (d < 0) {
223 		return (-1);
224 	} else if (d == 0) {
225 		return (left);
226 	}
227 	d = (*comp_func)(right, year, month, day, leap);
228 	if (d > 0) {
229 		return (-1);
230 	} else if (d == 0) {
231 		return (right);
232 	}
233 
234 	while ((right - left) > 1) {
235 
236 		middle = (right + left) >> 1;
237 		d = (*comp_func)(middle, year, month, day, leap);
238 		if (d == 0) {
239 			return (middle);
240 		}
241 		if (d < 0) {
242 			right = middle;
243 		} else {
244 			left = middle;
245 		}
246 	}
247 	return (left);	/* return (right); */
248 }
249 
250 /*
251  * binary search �Ѥ�������Ӵؿ�
252  *
253  * �����������ؤ��Ѵ���
254  */
255 static
check_date(int index,int year,int month,int day,int leap)256 int check_date(int index, int year, int month, int day, int leap)
257 {
258 	int	diff;
259 
260 	diff = year - (kyureki_tbl[index].year + base_year);
261 	if (diff != 0) {
262 		return (diff);
263 	}
264 
265 	diff = month - kyureki_tbl[index].month;
266 	if (diff != 0) {
267 		return (diff);
268 	}
269 
270 	return (day - kyureki_tbl[index].day);
271 }
272 
273 /*
274  * ����(����������)�����
275  *
276  * �������դ����ݡ����ϰ���ξ��ϡ�������Ǽ����Ƥ���
277  * ��¤�� LUNAR_CALENDAR �Υݥ������֤�
278  * ���顼��ȯ���������ϡ�NULL ���֤�
279  *
280  * ���ߤϡ�1872ǯ12��30�� �� 2100ǯ3��11���ޤǥ��ݡ��Ȥ��Ƥ���
281  * �������¤ϡ��ե����� 'kyureki.tbl' �˰�¸���Ƥ�������ʤΤǡ�
282  * �ϰϤ���礷���ե�������Ѱդ��뤳�Ȥˤ�ꡢ�ϰϤ����Ǥ���
283  * ���������ơ��֥���Թ�ˤ������250ǯ�֤������ݡ��ȤǤ��ʤ�
284  */
GetLunarCalendar(int year,int month,int day)285 const struct LUNAR_CALENDAR *GetLunarCalendar(int year, int month, int day)
286 {
287 	static struct LUNAR_CALENDAR	lc;
288 	int	index;
289 	int	now_year, now_month;
290 	int	dayofweek;
291 
292 	index = search_kyureki(check_date, year, month, day, 0);
293 	if (index < 0) {
294 		return (NULL);
295 	}
296 
297 	now_year  = kyureki_tbl[index].year + base_year;
298 	now_month = kyureki_tbl[index].month;
299 	lc.year   = now_year - kyureki_tbl[index].offset;
300 	lc.month  = kyureki_tbl[index].month_k;
301 	lc.leap   = kyureki_tbl[index].leap;
302 	lc.day    = day - kyureki_tbl[index].day + 1;
303 	if (month != now_month) {
304 		lc.day += GetDayofMonth(now_year, now_month);
305 	}
306 
307 #if 0
308 	while (lc.day > 30) {
309 		lc.day -= 30;
310 		if (++lc.month > 12) {
311 			lc.year++;
312 		}
313 	}
314 #endif
315 
316 	dayofweek = (lc.month + lc.day - 2) % 6;
317 	lc.dayofweek = dayofweek;
318 	lc.rokuyou = rokuyou_name[dayofweek];
319 
320 	return (&lc);
321 }
322 
323 #ifndef INCLUDE_CALENDAR
324 /*
325  * binary search �Ѥ�������Ӵؿ�
326  *
327  * �����鸽����ؤ��Ѵ���
328  */
329 static
check_lc_date(int index,int year,int month,int day,int leap)330 int check_lc_date(int index, int year, int month, int day, int leap)
331 {
332 	int	diff;
333 
334 	diff = year - (kyureki_tbl[index].year + base_year - kyureki_tbl[index].offset);
335 	if (diff != 0) {
336 		return (diff);
337 	}
338 
339 	diff = month - kyureki_tbl[index].month_k;
340 	if (diff != 0) {
341 		return (diff);
342 	}
343 
344 	diff = leap - kyureki_tbl[index].leap;
345 	if (diff != 0) {
346 		return (diff);
347 	}
348 
349 	return (day - 1);
350 }
351 
352 /*
353  * �����鸽��������
354  *
355  * �������դ����ݡ����ϰ���ξ��ϡ���������Ǽ����Ƥ���
356  * ��¤�� DATE_T �Υݥ������֤�
357  * ���顼��ȯ���������ϡ�NULL ���֤�
358  *
359  * ���ߤϡ�1872ǯ12��1�� �� 2100ǯ2��1���ޤǥ��ݡ��Ȥ��Ƥ���
360  * ��ͳ�ϡ�'����(����������)�����'��Ʊ��
361  */
LunarToNowCalendar(int year,int month,int day,int leap)362 const struct DATE_T *LunarToNowCalendar(int year, int month, int day, int leap)
363 {
364 	static struct DATE_T	date;
365 	int	index;
366 
367 	index = search_kyureki(check_lc_date, year, month, day, leap);
368 	if (index < 0) {
369 		return (NULL);
370 	}
371 
372 	date.year = kyureki_tbl[index].year + base_year;
373 	date.month = kyureki_tbl[index].month;
374 	date.day = kyureki_tbl[index].day;
375 	date_inc(&date, day - 1);
376 	return (&date);
377 }
378 
379 /*
380  * ����η�����ơ��֥���������
381  *
382  * return value:
383  *   �ơ��֥뤬�����Ǥ��ʤ����ϡ�-1 ���֤�
384  *   ����ξ��ϡ�0 ���֤�
385  */
make_lc_monthtbl(struct LC_MONTHTBL * montbl,int tblcnt,int tblcenter,int year,int month,int day)386 int make_lc_monthtbl(struct LC_MONTHTBL *montbl, int tblcnt, int tblcenter, int year, int month, int day)
387 {
388 	int	i;
389 	int	index;
390 
391 	index = search_kyureki(check_date, year, month, day, 0);
392 	if (index < 0) {
393 		return (-1);
394 	}
395 
396 	for (i = 0; i < tblcnt; i++) {
397 		int	mindex;
398 		int	year_base;
399 		int	j;
400 		const struct KYUREKI_T FAR	*mp;
401 		const struct KYUREKI_T FAR	*np;
402 
403 		mindex = index + (i - tblcenter);
404 		if (mindex < 0 || mindex >= (max_tblsize - 1)) {
405 			return (-1);
406 		}
407 
408 		mp = &kyureki_tbl[mindex];
409 		np = &kyureki_tbl[mindex + 1];
410 
411 		year_base = mp->year + base_year;
412 		montbl[i].year = year_base - mp->offset;
413 		montbl[i].month = mp->month_k;
414 		montbl[i].leap = mp->leap;
415 		montbl[i].dayofmonth = (int)(Julian(np->year + base_year, np->month, np->day) - Julian(year_base, mp->month, mp->day));
416 		montbl[i].first_dayofweek = (mp->month_k + 1 - 2) % 6;
417 		montbl[i].last_dayofweek = (mp->month_k + montbl[i].dayofmonth - 2) % 6;
418 		montbl[i].offset_day = 0;
419 
420 		for (j = i - 1; j >= 0; j--) {
421 			montbl[i].offset_day += montbl[j].dayofmonth;
422 		}
423 	}
424 
425 	return (0);
426 }
427 #endif /* !INCLUDE_CALENDAR */
428