source: buchla-68k/orig/DATE/GREG.C@ 9bf0f86

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

Imported original source code.

  • Property mode set to 100755
File size: 5.0 KB
Line 
1/************************************************************************/
2/* Program: greg */
3/* Purpose: compute and verify information for Gregorian calendar */
4/* Copyright: W. M. McKeeman 1986. This program may be used or */
5/* modified for any purpose so long as this copyright */
6/* notice is incorporated in the resulting source code. */
7/* Compile: Use cc -Os -DMAIN -o greg greg.c to compile with main */
8/* delete the -DMAIN to compile as a function only. */
9/* Input: year, month, day */
10/* day of month week & year, week of month, julian day. */
11/* input values are zero (meaning "to be computed") or */
12/* positive integers (meaning "to be checked and used") */
13/* Output: consistent positive values for input: */
14/* return 0 if all output is valid, */
15/* return 1 if input is inconsistent, */
16/* return 2 if input is incomplete, */
17/* return 3 if int or long int is too short. */
18/* Example: */
19/* y = 1985; m = 12; d = 10; wd = 0; wk = 0; yd = 0; jd = 0; */
20/* greg(&y, &m, &d, &wd, &wk, &yd, &jd) returns 0 and leaves: */
21/* y = 1985; m = 12; d = 10; wd = 3; wk = 2; yd = 344; jd = 2446410; */
22/* Method: tableless. see man page */
23/************************************************************************/
24
25#include "stdio.h"
26
27#define SUCCESS 0
28#define INCONS 1
29#define INCOMP 2
30#define SYSFAIL 3
31
32#define Defined(e) ((e) != 0)
33
34#define MakeCon(v1, v2) \
35 {if (Defined(v1) && (v1) != (v2)) return(INCONS); else (v1) = (v2);}
36
37#define LeapsB4(y) (((y)-1)/4 - ((y)-1)/100 + ((y)-1)/400)
38
39#define AD0001Jan00 1721425L
40#define AD1582Oct15 2299161L
41#define AD14699Nov15 7090078L
42
43int
44greg(year, month, day0month, day0week, week0month, day0year, julianDay)
45int *year, *month, *day0month, *day0week, *week0month, *day0year;
46long int *julianDay; /* 7 significant digits */
47{
48 int d, w, m, y, ly, leaps;
49 long int td, jd;
50
51 if Defined(*julianDay) {
52
53 jd = *julianDay;
54
55 if (jd <= AD0001Jan00)
56 return(INCONS);
57
58 td = jd - AD0001Jan00 - 1;
59 y = 1 + (td -= (td+1)/146097, td += (td+1)/36524, td-(td+1)/1461)/365;
60 MakeCon(*year, y);
61 d = jd - ((y-1)*365 + LeapsB4(y) + AD0001Jan00);
62 MakeCon(*day0year, d);
63 }
64
65 if (!Defined(*year))
66 return(INCOMP);
67 else
68 y = *year;
69
70 leaps = LeapsB4(y);
71 ly = y%400 == 0 || (y%100 != 0 && y%4 == 0);
72
73 if (!Defined(*day0year)) {
74 if (!Defined(*month)) return(INCOMP);
75 if (!Defined(*day0month)) {
76 if (!Defined(*day0week)||!Defined(*week0month))return(INCOMP);
77 *day0month = 7*(*week0month-1) + *day0week -
78 (y+leaps+3055L*(*month+2)/100-84-(*month>2)*(2-ly))%7;
79 }
80 *day0year = 3055L*(*month+2)/100 - 91 + *day0month - (*month>2)*(2-ly);
81 }
82
83 td = (*day0year + (*day0year>59+ly)*(2-ly) + 91)*100L;
84 m = td/3055 - 2;
85 MakeCon(*month, m);
86 d = td%3055/100 + 1;
87 MakeCon(*day0month, d);
88
89 jd = AD0001Jan00 + (y-1)*365 + LeapsB4(y) + *day0year;
90 MakeCon(*julianDay, jd);
91 w = (jd+1)%7 + 1;
92 MakeCon(*day0week, w);
93 w = (13 + *day0month - *day0week)/7;
94 MakeCon(*week0month, w);
95
96 return(*month) > 12 || *julianDay < AD1582Oct15 || *day0month >
97 (*month == 2 ? 28+ly : 30+(*month == 1 || *month%5%3 != 1));
98}
99
100#ifdef MAIN
101
102main(argc, argv) /* driver for greg */
103int argc; char *argv[];
104{
105 int r, i, p[7];
106 long int jd; /* 7 significant digits */
107
108 if (sizeof (long int) < 4 || sizeof (int) < 2) r = SYSFAIL;
109 else if (argc > 8) r = INCONS; /* too many inputs */
110 else if (argc < 4) r = INCOMP; /* need y m d at least */
111 else {
112 r = SUCCESS;
113 for (i=1;i<=6;i++) {
114 p[i] = i < argc ? atoi(argv[i]) : 0;
115 if (p[i] < 0) r = INCONS; /* no negative input */
116 }
117 jd = argc == 8 ? atol(argv[7]) : 0L; /* julian day is (long) */
118 if (r != INCONS)
119 r = greg(&p[1], &p[2], &p[3], &p[4], &p[5], &p[6], &jd);
120 }
121
122 switch (r) {
123
124 case INCONS:
125 puts("greg: input does not describe a valid gregorian date");
126
127 case SUCCESS:
128 printf("%d %d %d %d %d %d %ld\n", p[1],p[2],p[3],p[4],p[5],p[6],jd);
129 break;
130
131 case INCOMP:
132 puts("greg: insufficient information");
133 puts("usage: greg year month day [day0week week0month day0year jd]");
134 break;
135
136 case SYSFAIL:
137 puts("greg: insufficient precision in either (int) or (long int)");
138 break;
139 }
140 exit(r);
141}
142
143#endif
Note: See TracBrowser for help on using the repository browser.