|
|
1.1 root 1: #include <stdio.h>
2: #include <sys/time.h>
3: #include <ctype.h>
4:
5: /*
6: ** promptdate
7: ** prompt user for a date specification which can be quite minimal
8: ** and print it in a form suitable for parsing by MH
9: */
10:
11: #define MAXLINE 128
12:
13: char *mname[12] ={
14: "Jan","Feb","Mar","Apr","May","Jun",
15: "Jul","Aug","Sep","Oct","Nov","Dec"};
16: char *dname[7] ={
17: "Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
18: struct tm now;
19: int dayspast = 0;
20: int monthlen[2][12] ={
21: 31,28,31,30,31,30,31,31,30,31,30,31,
22: 31,29,31,30,31,30,31,31,30,31,30,31};
23: char *defaultformat = "%d %N %y 00:00";
24:
25: main(argc, argv)
26: int argc;
27: char **argv;
28: {
29: register int c;
30: struct tm then;
31: extern int optind; /* defined in getopt */
32: extern char *optarg; /* defined in getopt */
33: int getopt();
34: long secsfr70();
35:
36: while ((c = getopt (argc, argv, "f:")) != EOF)
37: {
38: switch (c)
39: {
40: case 'f':
41: defaultformat = optarg;
42: break;
43: default:
44: fprintf(stderr, "usage: %s [-f format] [datespec]\n", argv[0]);
45: exit (1);
46: }
47: }
48: argc -= optind;
49: argv += optind;
50:
51: finddate(&now, dayspast = (int)(secsfr70()/86400L));
52:
53: if (argc <= 0) /* get from user */
54: {
55: if (!promptdate(&then))
56: exit(1);
57: printdate(&then, defaultformat);
58: }
59: else /* get from command line */
60: {
61: if (!decodedate(argv[0], &then))
62: exit(1);
63: printdate(&then, defaultformat);
64: }
65: exit(0);
66: }
67:
68: int promptdate(when)
69: struct tm *when;
70: {
71: char line[MAXLINE];
72: int decodedate();
73: char *gets();
74:
75: for (;;)
76: {
77: fprintf(stderr, "When? ");
78: if (gets(line) == NULL)
79: {
80: fprintf(stderr, "\n");
81: return (0);
82: }
83: if (decodedate(line, when))
84: return (1);
85: }
86: /*NOTREACHED*/
87: }
88:
89: int decodedate(line, when)
90: char *line;
91: struct tm *when;
92: /*
93: ** accept spec for date in several forms
94: ** legal are: sun,mon,tue,wed,thu,fri,sat,today,tomorrow,
95: ** <date><month>,+<relative number of days>
96: ** <month> should be alpha
97: ** upper case accepted too
98: */
99: {
100: char s[4];
101: register int i,targetdate;
102: int tem;
103: register char *lptr;
104:
105: when->tm_year = now.tm_year;
106: when->tm_mon = now.tm_mon;
107: targetdate = dayspast;
108: for (lptr = line; isspace(*lptr); lptr++)
109: ;
110: if (isdigit(*lptr))
111: {
112: i = sscanf(lptr, "%d%3s%d", &when->tm_mday, s, &tem);
113: switch(i)
114: {
115: case 3:
116: when->tm_year = tem;
117: case 2:
118: fold(s);
119: when->tm_mon = monthofyear(s);
120: if (i == 3)
121: break;
122: if (when->tm_mday != 0 && when->tm_mon != 0 && daysfr70(when) < dayspast)
123: when->tm_year++;
124: break;
125: case 1:
126: if (when->tm_mday != 0 && when->tm_mday < now.tm_mday)
127: {
128: if (++when->tm_mon > 12)
129: {
130: when->tm_mon = 1;
131: when->tm_year++;
132: }
133: }
134: }
135: return (validate(when));
136: }
137: if (isalpha(*lptr))
138: {
139: sscanf(lptr, "%3s", s);
140: fold(s);
141: if ((tem = dayofweek(s)) >= 0)
142: targetdate += (tem -= now.tm_wday) <= 0 ? tem + 7 : tem;
143: else if (strcmp(s, "Tom") == 0)
144: targetdate++;
145: else if (strcmp(s, "Tod") == 0)
146: ;
147: else /* mistake */
148: return (0);
149: }
150: else if (*lptr == '+')
151: {
152: if (sscanf(++lptr, "%d", &tem) == 0 || tem < 0) /* mistake */
153: return (0);
154: targetdate += tem;
155: }
156: else /* mistake by default */
157: return (0);
158: finddate(when, targetdate);
159: return (when->tm_mday != 0);
160: }
161:
162: int validate(datetm)
163: /*
164: ** check that a given date and month combination is legal
165: ** datetm->tm_year must hold the year in question
166: */
167: register struct tm *datetm;
168: {
169:
170: return (datetm->tm_mday <= monthlen[leapyear(datetm->tm_year)]
171: [datetm->tm_mon] && datetm->tm_mday > 0);
172: }
173:
174: finddate(datetm, df70)
175: /*
176: ** convert days from 1 jan 1970 to a date in struct datetm
177: */
178: register int df70;
179: register struct tm *datetm;
180: {
181: register struct tm *tdtm;
182: long longtime;
183: struct tm *gmtime();
184:
185: longtime = df70 * 86400L;
186: tdtm = gmtime(&longtime);
187: datetm->tm_yday = tdtm->tm_yday;
188: datetm->tm_wday = tdtm->tm_wday;
189: datetm->tm_year = tdtm->tm_year + 1900;
190: datetm->tm_mon = tdtm->tm_mon;
191: datetm->tm_mday = tdtm->tm_mday;
192: datetm->tm_hour = tdtm->tm_hour;
193: datetm->tm_min = tdtm->tm_min;
194: datetm->tm_sec = tdtm->tm_sec;
195: }
196:
197: fold(s)
198: /*
199: ** convert first character to uppercase
200: ** convert rest of string from uppercase to lower case
201: */
202: register char *s;
203: {
204: register char c;
205:
206: if ((c = *s) != '\0')
207: *s++ += islower(c) ? 'A' - 'a' : 0;
208: while ((c = *s) != '\0')
209: *s++ += isupper(c) ? 'a' - 'A' : 0;
210: }
211:
212: int leapyear(y)
213: /*
214: ** returns 1 if leapyear 0 otherwise
215: */
216: register int y;
217: {
218:
219: return (((y % 4) == 0 && (y % 100) != 0) || (y % 400) == 0);
220: }
221:
222: int daysfr70(datetm)
223: /*
224: ** returns the number of days from 1 Jan 1970
225: ** no checking for illegal date at all
226: */
227: register struct tm *datetm;
228: {
229: register int i, totdays;
230:
231:
232: totdays = 0;
233: for (i = 1970; i <= 2050 && i < datetm->tm_year; i++) /* prevent overflow */
234: totdays += 365 + leapyear(i);
235: for (i = 0; i < 12 && i < datetm->tm_mon; i++)
236: totdays += monthlen[leapyear(datetm->tm_year)][i];
237: totdays += datetm->tm_mday - 1;
238: return (totdays);
239: }
240:
241: int monthofyear(s)
242: /*
243: ** returns month of year in numeric form when given
244: ** the first three letters
245: */
246: register char *s;
247: {
248: register int i;
249:
250: fold(s);
251: for (i = 12; i-- && strcmp(s,mname[i]); )
252: ;
253: return (i);
254: }
255:
256: int dayofweek(s)
257: /*
258: ** sunday = 0,...,saturday = 6, nomatch = -1
259: */
260: register char *s;
261: {
262: register int i;
263:
264: fold(s);
265: for (i = 7; i-- && strcmp(s,dname[i]); )
266: ;
267: return (i);
268: }
269:
270: printdate(date, format)
271: /*
272: ** print date in MH acceptable format
273: ** kludge - general formats are not implemented
274: */
275: struct tm *date;
276: char *format;
277: {
278: printf("%d %s %d 00:00\n",
279: date->tm_mday, mname[date->tm_mon], date->tm_year);
280: }
281:
282: long secsfr70()
283: /*
284: ** This is system dependent
285: */
286: {
287: register int dst;
288: struct timeval tv;
289: struct timezone tz;
290: struct tm *localtime();
291:
292: gettimeofday(&tv, &tz);
293: dst = localtime(&tv.tv_sec)->tm_isdst;
294: return (tv.tv_sec - tz.tz_minuteswest * 60 + (dst ? 3600 : 0));
295: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.