source: buchla-68k/orig/DATE/DATEBOOK.C@ 0170798

Last change on this file since 0170798 was 3ae31e9, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Imported original source code.

  • Property mode set to 100755
File size: 14.8 KB
RevLine 
[3ae31e9]1/*
2 =============================================================================
3 datebook.c -- F A S T C A L E N D A R
4 Version 11 -- 1989-02-06 -- D.N. Lynx Crowe
5
6 Adapted from public domain source code retrieved from Usenet.
7
8 This C program is a faster, more general version of the
9 standard UNIX utility CALENDAR(1), only modified for GEMDOS
10 and with a few kinks added...
11
12 It recognizes the following formats for dates:
13
14 numeric/numeric As in: 1/12, 01/12, 12/1, ...
15 month/day format
16
17 3-charmonth[any chars] numeric As in: January 12, Jan. 12,
18 jan. 12, JAN. 12, ...
19
20 3-charweekday[any chars] As in: Friday, Monday, MON.,
21 mon., tue, wed, ...
22
23 numeric month A month from 1 to 12 as in:
24 1, 2, 04, 12, ...
25
26 Any lines, following a line that is matched, that have "whitespace"
27 in the first column will be printed along with the matched line.
28 =============================================================================
29*/
30
31#define HASARGS 0 /* define non-zero to allow file arg */
32
33#include "stdio.h"
34#include "ctype.h"
35
36#include "types.h"
37#include "time.h"
38#include "math.h"
39
40#include "stddefs.h"
41
42#define CALFILE "c:\\datebook.dat" /* default name for datebook file */
43
44#define DAY (24*3600) /* Number of seconds in a day. */
45
46#define EPOCH 1985
47#define EPSILONg 279.611371 /* solar ecliptic long at EPOCH */
48#define RHOg 282.680403 /* solar ecliptic long of perigee at EPOCH */
49#define e 0.01671542 /* solar orbit eccentricity */
50#define lzero 18.251907 /* lunar mean long at EPOCH */
51#define Pzero 192.917585 /* lunar mean long of perigee at EPOCH */
52#define Nzero 55.204723 /* lunar mean long of node at EPOCH */
53
54/* Remove this for SYS5 machines, or others with strchr instead of index. */
55/* #define strchr index */
56
57/*
58
59*/
60
61char mstring[128];
62
63char datebuf[300]; /* Global input line. */
64
65char *months[] = { /* Month definitions. */
66
67 "JAN", "FEB", "MAR",
68 "APR", "MAY", "JUN",
69 "JUL", "AUG", "SEP",
70 "OCT", "NOV", "DEC"
71};
72
73char *nm_mon[] = {
74
75 "January", "February", "March",
76 "April", "May", "June",
77 "July", "August", "September",
78 "October", "November", "December"
79};
80
81char *weekdays[] = { /* Weekday definitions. */
82
83 "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"
84};
85
86char *nm_day[] = {
87
88 "Sunday" , "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
89 "Saturday"
90};
91
92short tisnow;
93short seen;
94
95FILE *outfp = stdout;
96
97int
98ly(yr)
99int yr;
100{
101 /* returns 1 if leapyear, 0 otherwise */
102
103 return (yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0);
104}
105
106double
107dtor(deg)
108double deg;
109{
110 /* convert degrees to radians */
111
112 return (deg * PI / 180);
113}
114
115double
116adj360(deg)
117double *deg;
118{
119 /* adjust value so 0 <= deg <= 360 */
120
121 do {
122
123 if (*deg < 0)
124 *deg += 360;
125 else if (*deg > 360)
126 *deg -= 360;
127
128 } while (*deg < 0 || *deg > 360);
129}
130
131double
132potm(days)
133double days;
134{
135 double N;
136 double Msol;
137 double Ec;
138 double LambdaSol;
139 double l;
140 double Mm;
141 double Ev;
142 double Ac;
143 double A3;
144 double Mmprime;
145 double A4;
146 double lprime;
147 double V;
148 double ldprime;
149 double D;
150 double Nm;
151
152 N = 360 * days / 365.2422; /* sec 42 #3 */
153 adj360(&N);
154
155 Msol = N + EPSILONg - RHOg; /* sec 42 #4 */
156 adj360(&Msol);
157
158 Ec = 360 / PI * e * sin(dtor(Msol)); /* sec 42 #5 */
159
160 LambdaSol = N + Ec + EPSILONg; /* sec 42 #6 */
161 adj360(&LambdaSol);
162
163 l = 13.1763966 * days + lzero; /* sec 61 #4 */
164 adj360(&l);
165
166 Mm = l - (0.1114041 * days) - Pzero; /* sec 61 #5 */
167 adj360(&Mm);
168
169 Nm = Nzero - (0.0529539 * days); /* sec 61 #6 */
170 adj360(&Nm);
171
172 Ev = 1.2739 * sin(dtor(2*(l - LambdaSol) - Mm)); /* sec 61 #7 */
173
174 Ac = 0.1858 * sin(dtor(Msol)); /* sec 61 #8 */
175 A3 = 0.37 * sin(dtor(Msol));
176
177 Mmprime = Mm + Ev - Ac - A3; /* sec 61 #9 */
178
179 Ec = 6.2886 * sin(dtor(Mmprime)); /* sec 61 #10 */
180
181 A4 = 0.214 * sin(dtor(2 * Mmprime)); /* sec 61 #11 */
182
183 lprime = l + Ev + Ec - Ac + A4; /* sec 61 #12 */
184
185 V = 0.6583 * sin(dtor(2 * (lprime - LambdaSol))); /* sec 61 #13 */
186
187 ldprime = lprime + V; /* sec 61 #14 */
188
189 D = ldprime - LambdaSol; /* sec 63 #2 */
190
191 return((double)(50 * (1 - cos(dtor(D))))); /* sec 63 #3 */
192}
193
194moontxt(buf)
195char buf[];
196{
197 char *cp = buf;
198 long *lo; /* used by time calls */
199 long curtime;
200 double days; /* days since EPOCH */
201 double phase; /* percent of lunar surface illuminated */
202 double phase2; /* percent of lunar surface illuminated one day later */
203 int i = EPOCH;
204 struct tm *pt; /* ptr to time structure */
205
206 lo = &curtime;
207 time(lo); /* get system time */
208 pt = gmtime(lo); /* get ptr to gmt time struct */
209
210 /* calculate days since EPOCH */
211
212 days = (pt->tm_yday +1) + ((pt->tm_hour + (pt->tm_min / 60.0)
213 + (pt->tm_sec / 3600.0)) / 24.0);
214
215 while (i < pt->tm_year + 1900)
216 days = days + 365 + ly(i++);
217
218 phase = potm(days);
219 sprintf(cp,"The Moon is ");
220 cp += strlen(buf);
221
222 if ((int)(phase + .5) == 100)
223 sprintf(cp,"Full");
224 else if ((int)(phase + 0.5) == 0)
225 sprintf(cp,"New");
226 else if ((int)(phase + 0.5) == 50) {
227
228 phase2 = potm(++days);
229
230 if (phase2 > phase)
231 sprintf(cp,"at the First Quarter");
232 else
233 sprintf(cp,"at the Last Quarter");
234
235 } else if ((int)(phase + 0.5) > 50) {
236
237 phase2 = potm(++days);
238
239 if (phase2 > phase)
240 sprintf(cp,"Waxing ");
241 else
242 sprintf(cp,"Waning ");
243
244 cp = buf + strlen(buf);
245 sprintf(cp,"Gibbous (%1.0f%% of Full)", phase);
246
247 } else if ((int)(phase + 0.5) < 50) {
248
249 phase2 = potm(++days);
250
251 if (phase2 > phase)
252 sprintf(cp,"Waxing ");
253 else
254 sprintf(cp,"Waning ");
255
256 cp = buf + strlen(buf);
257 sprintf(cp,"Crescent (%1.0f%% of Full)", phase);
258 }
259}
260
261/*
262
263*/
264
265/*
266 =============================================================================
267 chinayr() -- returns a pointer to a static string for the Chinese year
268 =============================================================================
269*/
270
271char *
272chinayr(year)
273register int year;
274{
275 static char *chyrs[] = { /* Chinese Year cycle */
276
277 "Rat", /* 0 */
278 "Ox", /* 1 */
279 "Tiger", /* 2 */
280 "Rabbit", /* 3 */
281 "Dragon", /* 4 */
282 "Snake", /* 5 */
283 "Horse", /* 6 */
284 "Ram", /* 7 */
285 "Monkey", /* 8 */
286 "Cock", /* 9 */
287 "Dog", /* 10 */
288 "Boar" /* 11 */
289 };
290
291 year -= 4;
292
293 if (year < 0)
294 return((char *)"?????");
295 else
296 return(chyrs[year % 12]);
297}
298
299/*
300
301*/
302
303/*
304 =============================================================================
305 getdate() -- Check the input line, and get only the lines without
306 leading "whitespace". Conditionally print those lines with leading
307 blanks, based on the "success" flag.
308 =============================================================================
309*/
310
311char *
312getdate(fp, success)
313char *success;
314register FILE *fp;
315{
316 register int c;
317 static char inbuf[300];
318 register char *t, *s;
319
320 t = inbuf;
321 s = datebuf;
322
323 while ((c = getc(fp)) LE ' ' AND c NE EOF) { /* Skip leading space. */
324
325 ungetc(c, fp);
326 fgets(inbuf, 300, fp);
327
328 /* Print the line if we previously printed a match. */
329
330 if (*success)
331 fprintf(outfp,"%s\t%s", (tisnow ? ">" : " "), inbuf);
332 }
333
334 *success = 1; /* Assume success for now. */
335
336 if (c EQ EOF) /* Return EOF if we are there. */
337 return((char *)0);
338
339 ungetc(c, fp); /* Unget the character. */
340 fgets(t, 300, fp); /* Get the input line. */
341 strcpy(s, t); /* Make a copy of it. */
342
343 return(inbuf);
344}
345
346/*
347
348*/
349
350/*
351 =============================================================================
352 isnow() -- See if the passed string has a "NOW" date in it.
353 =============================================================================
354*/
355
356int
357isnow(datebuf)
358char *datebuf;
359{
360 char *s, *t;
361 long l;
362 register int before, after, offset, month, day;
363 register struct tm *tmptr;
364 long timenow;
365
366 time(&timenow); /* Get the current time. */
367 tmptr = localtime(&timenow);
368
369 before = 0;
370 after = 0;
371
372 t = datebuf;
373
374/*
375
376*/
377 /* Is the first character a digit in a Month? */
378
379 if (isdigit(*t) AND (month = getnum(&t) - 1) GE 0 AND month < 12) {
380
381 tisnow = (tmptr->tm_mon EQ month);
382
383 /* Find the separating slash. */
384
385 if (s = (char *)strchr(t, '/'))
386 t = s + 1;
387 else if (tmptr->tm_mon EQ month)
388 return(1);
389 else
390 return(0);
391
392 /* Is the string a month name? */
393
394 } else if ((month = ischmonth(t)) GE 0) {
395
396 /* Skip till while space. */
397
398 while (!isspace(*t) AND *t)
399 ++t;
400
401 /* Skip to first NON-white space. */
402
403 while (isspace(*t) AND *t)
404 ++t;
405
406 /* Not a month, so try a DAY as in Friday, Saturday, etc... */
407
408 } else if ((day = ischday(datebuf)) GE 0) {
409
410 tisnow = (day EQ tmptr->tm_wday);
411
412 /* Is this today? */
413
414 if (day EQ tmptr->tm_wday OR ((day + 6)%7) EQ tmptr->tm_wday)
415 return(1);
416 else
417 return(0);
418
419 } else {
420
421 /* Fail to recognize any other data as a valid date. */
422
423 return(0);
424 }
425/*
426
427*/
428 /* Is there only what looks to be a month? If so, then OK. */
429
430 if (! *t OR ! isdigit(*t)) {
431
432 /* Is it this month? */
433
434 if (tmptr->tm_mon EQ month)
435 return(1);
436
437 return(0);
438 }
439
440 /* Calculate the value of the day. */
441
442 day = getnum(&t);
443
444 /* Check for *w or *W extended week specifiers. */
445
446 if (*t EQ '*') {
447
448 if (t[1] EQ 'w')
449 ++before;
450
451 if (t[1] EQ 'W')
452 ++after;
453
454 if (t[2] EQ 'W')
455 ++after;
456
457 if (t[2] EQ 'w')
458 ++before;
459 }
460
461/*
462
463*/
464 offset = 1; /* Set weekend offset. */
465
466 switch (tmptr->tm_wday) { /* Get offset based on the weekend. */
467
468 case 5: ++offset;
469
470 case 6: ++offset;
471
472 default: ++offset;
473
474 }
475
476 tisnow = istoday(timenow, month, day);
477
478 /* Step through all dates by DAY. */
479
480 l = timenow - (after * 7 * DAY);
481
482 while (l < timenow + (before * 7 * DAY) + (offset * DAY)) {
483
484 if (istoday(l, month, day))
485 return(1);
486
487 l += DAY;
488 }
489
490 return(0); /* Return failure. */
491}
492
493/*
494
495*/
496
497/*
498 =============================================================================
499 ischday() -- Check if the string s is a DAY of the week as in monday,
500 tues, wed, THU., or any derivative thereof.
501 =============================================================================
502*/
503
504int
505ischday(s)
506register char *s;
507{
508 register char *tt;
509 register int i, found = 0, c;
510 register char t[30];
511
512 /* Copy the input, and capitalize it. */
513
514 for (tt = t, i=0; isalpha(*s) AND i < 28; ++i)
515 *tt++ = islower(c = *s++) ? toupper(c) : c;
516
517 *tt = '\0';
518
519 /* Search the list of valid day names for the string. */
520
521 for (i = 0; i < 7; ++i) {
522
523 if (strncmp(t, weekdays[i], 3) EQ 0) {
524
525 found++;
526 break;
527 }
528 }
529
530 /* Return the numeric equivalent if we found it. */
531
532 if (found)
533 return(i);
534
535 /* Return invalid day name. */
536
537 return(-1);
538}
539
540/*
541
542*/
543
544/*
545 =============================================================================
546 ischmonth() -- Check if the string s is a valid derivative of the name
547 of a month as in JUNE, jun, August, etc...
548 =============================================================================
549*/
550
551int
552ischmonth(s)
553register char *s;
554{
555 register char *tt;
556 register int i, found = 0, c;
557 register char t[30];
558
559 /* Copy and capitalize. */
560
561 for (tt = t, i=0; isalpha(*s) AND i < 28; ++i)
562 *tt++ = islower(c = *s++) ? toupper(c) : c;
563
564 *tt = '\0';
565
566 /* Look through the list for a match. */
567
568 for (i = 0; i < 12; ++i) {
569
570 if (strncmp(t, months[i], 3) EQ 0) {
571
572 found++;
573 break;
574 }
575 }
576
577 /* Return the numeric equivalent if we found it. */
578
579 if (found)
580 return(i);
581
582 /* Return faliure. */
583
584 return(-1);
585}
586
587/*
588
589*/
590
591/*
592 =============================================================================
593 getnum() -- Scan the string *t, and evaluate any integer contained
594 there. It is assumed that at least 1 digit exists (**t).
595 =============================================================================
596*/
597
598int
599getnum(t)
600char **t;
601{
602 register int i, c;
603 register char *s;
604
605 i = 0;
606
607 /* Get the starting address. */
608 s = *t;
609
610 /* Get the starting value from the first digit. */
611 i = (c = *s++) - '0';
612
613 /* Evaluate the rest of the digits (if any). */
614
615 while (isdigit(c = *s++))
616 i = i * 10 + (c - '0');
617
618 /* Set the new address. */
619 *t = --s;
620
621 /* Return the value. */
622 return(i);
623}
624
625/*
626
627*/
628
629/*
630 =============================================================================
631 istoday() -- Return whether or not the time t corresponds to
632 the month and day.
633 =============================================================================
634*/
635
636int
637istoday(t, month, day)
638long t;
639register int month, day;
640{
641 register struct tm *tm;
642
643 tm = localtime(&t);
644
645 return(tm->tm_mon EQ month AND tm->tm_mday EQ day);
646}
647
648/*
649
650*/
651
652/*
653 =============================================================================
654 main function for datebook.c
655 =============================================================================
656*/
657
658main(argc, argv)
659int argc;
660char **argv;
661{
662 register char *s;
663 char success;
664 register char file[200];
665 register FILE *fp;
666 long intime;
667 long *timeloc;
668 int year;
669 struct tm *intmp;
670
671 /* Use file passed as an argument if it is there,
672 otherwise use default file. */
673
674#if HASARGS
675 if (argc LE 1)
676#endif
677 strcpy(file, CALFILE);
678#if HASARGS
679 else
680 strcpy(file, argv[1]);
681#endif
682
683 if ((fp = fopen(file, "r")) EQ NULL) { /* Open the input file. */
684
685 perror(file);
686 exit(1);
687 }
688
689 time(timeloc = &intime);
690 intmp = localtime(timeloc);
691 year = intmp->tm_year+1900;
692
693 fprintf(outfp,"\nThe time is %02d:%02d and ",
694 intmp->tm_hour, intmp->tm_min);
695
696 fprintf(outfp,"today is %s,\n%s %d, %d - the year of the %s.\n\n",
697 nm_day[intmp->tm_wday], nm_mon[intmp->tm_mon],
698 intmp->tm_mday, year, chinayr(year));
699
700 moontxt(mstring);
701 fprintf(outfp, "%s\n\n", mstring);
702
703 if ((intmp->tm_wday EQ 5) AND (intmp->tm_mday EQ 13))
704 fprintf(outfp,"!\tWatch out -- It's Friday the Thirteenth!\n\n");
705
706 success = 0; /* Initially, no success. */
707 seen = FALSE;
708
709 while (s = getdate(fp, &success)) { /* Loop till EOF is encountered. */
710
711 if (isnow(datebuf)) { /* Check date for "NOW" */
712
713 /* Print it, it is valid. */
714
715 fprintf(outfp,"%s\t%s", (tisnow ? ">" : " "), s);
716 seen = TRUE;
717
718 } else {
719
720 /* Reset the "print lines with leading blanks" flag. */
721
722 success = 0;
723 }
724 }
725
726 if (NOT seen)
727 fprintf(outfp, "No reminders for today.\n");
728
729 fclose(fp); /* Close up and exit. */
730 exit(0);
731}
Note: See TracBrowser for help on using the repository browser.