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