vary.c (7ca215a69037714e5f3cb65c394d3467621daa4c) vary.c (698f86e401d193b01b09cf1ae7d1a26a5652deac)
1#include <time.h>
2#include <string.h>
3#include <stdlib.h>
4#include "vary.h"
5
6struct trans {
7 int val;
8 char *str;
9};
10
11static struct trans trans_mon[] = {
1#include <time.h>
2#include <string.h>
3#include <stdlib.h>
4#include "vary.h"
5
6struct trans {
7 int val;
8 char *str;
9};
10
11static struct trans trans_mon[] = {
12 { 1, "jan" }, { 2, "feb" }, { 3, "mar" }, { 4, "apr" }, { 5, "may" },
13 { 6, "jun" }, { 7, "jul" }, { 8, "aug" }, { 9, "sep" }, { 10, "oct" },
14 { 11, "nov" }, { 12, "dec" },
15 { 1, "january" }, { 2, "february" }, { 3, "march" }, { 4, "april" },
16 { 6, "june" }, { 7, "july" }, { 8, "august" }, { 9, "september" },
17 { 10, "october" }, { 11, "november" }, { 12, "december" },
18 { -1, NULL }
19};
20
21static struct trans trans_wday[] = {
12 { 1, "january" }, { 2, "february" }, { 3, "march" }, { 4, "april" },
13 { 6, "june" }, { 7, "july" }, { 8, "august" }, { 9, "september" },
14 { 10, "october" }, { 11, "november" }, { 12, "december" },
15 { -1, NULL }
16};
17
18static struct trans trans_wday[] = {
22 { 0, "sun" }, { 1, "mon" }, { 2, "tue" }, { 3, "wed" }, { 4, "thr" },
23 { 4, "thu" }, { 5, "fri" }, { 6, "sat" },
24 { 0, "sunday" }, { 1, "monday" }, { 2, "tuesday" }, { 3, "wednesday" },
25 { 4, "thursday" }, { 5, "friday" }, { 6, "saturday" },
26 { -1, NULL }
27};
28
29static char digits[] = "0123456789";
30
31static int
32trans(const struct trans t[], const char *arg)
33{
34 int f;
35
19 { 0, "sunday" }, { 1, "monday" }, { 2, "tuesday" }, { 3, "wednesday" },
20 { 4, "thursday" }, { 5, "friday" }, { 6, "saturday" },
21 { -1, NULL }
22};
23
24static char digits[] = "0123456789";
25
26static int
27trans(const struct trans t[], const char *arg)
28{
29 int f;
30
36 if (strspn(arg, digits) == strlen(arg))
37 return atoi(arg);
38
39 for (f = 0; t[f].val != -1; f++)
31 for (f = 0; t[f].val != -1; f++)
40 if (!strcasecmp(t[f].str, arg))
32 if (!strncasecmp(t[f].str, arg, 3) ||
33 !strncasecmp(t[f].str, arg, strlen(t[f].str)))
41 return t[f].val;
42
43 return -1;
44}
45
46struct vary *
34 return t[f].val;
35
36 return -1;
37}
38
39struct vary *
47vary_append(struct vary *v, char flag, char *arg)
40vary_append(struct vary *v, char *arg)
48{
49 struct vary *result, **nextp;
50
41{
42 struct vary *result, **nextp;
43
51 if (!strchr("DWMY", flag))
52 return 0;
53
54 if (v) {
55 result = v;
56 while (v->next)
57 v = v->next;
58 nextp = &v->next;
59 } else
60 nextp = &result;
61
62 *nextp = (struct vary *)malloc(sizeof(struct vary));
44 if (v) {
45 result = v;
46 while (v->next)
47 v = v->next;
48 nextp = &v->next;
49 } else
50 nextp = &result;
51
52 *nextp = (struct vary *)malloc(sizeof(struct vary));
63 (*nextp)->flag = flag;
64 (*nextp)->arg = arg;
65 (*nextp)->next = NULL;
66 return result;
67}
68
69static int mdays[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
70
71static int

--- 36 unchanged lines hidden (view full) ---

108 else if (t->tm_year > 1900)
109 t->tm_year -= 1900; /* struct tm holds years since 1900 */
110 break;
111 }
112 return mktime(t) != -1;
113}
114
115static int
53 (*nextp)->arg = arg;
54 (*nextp)->next = NULL;
55 return result;
56}
57
58static int mdays[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
59
60static int

--- 36 unchanged lines hidden (view full) ---

97 else if (t->tm_year > 1900)
98 t->tm_year -= 1900; /* struct tm holds years since 1900 */
99 break;
100 }
101 return mktime(t) != -1;
102}
103
104static int
116sadjyear(struct tm *t, char *arg)
117{
118 switch (*arg) {
119 case '+':
120 case '-':
121 return adjyear(t, *arg, atoi(arg+1));
122 default:
123 return adjyear(t, '\0', atoi(arg));
124 }
125}
126
127static int
128adjmon(struct tm *t, char type, int val, int istext)
129{
130 if (val < 0)
131 return 0;
132
133 switch (type) {
134 case '+':
135 if (istext)

--- 31 unchanged lines hidden (view full) ---

167 return 0;
168 t->tm_mon = --val;
169 }
170
171 return mktime(t) != -1;
172}
173
174static int
105adjmon(struct tm *t, char type, int val, int istext)
106{
107 if (val < 0)
108 return 0;
109
110 switch (type) {
111 case '+':
112 if (istext)

--- 31 unchanged lines hidden (view full) ---

144 return 0;
145 t->tm_mon = --val;
146 }
147
148 return mktime(t) != -1;
149}
150
151static int
175sadjmon(struct tm *t, char *arg)
176{
177 int istext;
178 int val;
179
180 switch (*arg) {
181 case '+':
182 case '-':
183 istext = strspn(arg+1, digits) != strlen(arg+1);
184 val = trans(trans_mon, arg+1);
185 return adjmon(t, *arg, val, istext);
186 default:
187 istext = strspn(arg, digits) != strlen(arg);
188 val = trans(trans_mon, arg);
189 return adjmon(t, '\0', val, istext);
190 }
191}
192
193static int
194adjday(struct tm *t, char type, int val)
195{
196 int mdays;
197 switch (type) {
198 case '+':
199 while (val) {
200 mdays = daysinmonth(t);
201 if (val > mdays - t->tm_mday) {

--- 27 unchanged lines hidden (view full) ---

229 return 0;
230 break;
231 }
232
233 return mktime(t) != -1;
234}
235
236static int
152adjday(struct tm *t, char type, int val)
153{
154 int mdays;
155 switch (type) {
156 case '+':
157 while (val) {
158 mdays = daysinmonth(t);
159 if (val > mdays - t->tm_mday) {

--- 27 unchanged lines hidden (view full) ---

187 return 0;
188 break;
189 }
190
191 return mktime(t) != -1;
192}
193
194static int
237sadjwday(struct tm *t, char *arg)
195adjwday(struct tm *t, char type, int val, int istext)
238{
196{
239 int istext;
240 int val;
241
242 switch (*arg) {
243 case '+':
244 case '-':
245 istext = strspn(arg+1, digits) != strlen(arg+1);
246 val = trans(trans_wday, arg+1);
247 break;
248 default:
249 istext = 0;
250 val = trans(trans_wday, arg);
251 break;
252 }
253
254 if (val < 0)
255 return 0;
256
197 if (val < 0)
198 return 0;
199
257 switch (*arg) {
200 switch (type) {
258 case '+':
259 if (istext)
260 if (val < t->tm_wday)
261 val = 7 - t->tm_wday + val; /* early next week */
262 else
263 val -= t->tm_wday; /* later this week */
264 else
265 val *= 7; /* "-W +5" == "5 weeks in the future" */

--- 14 unchanged lines hidden (view full) ---

280 return 0;
281 else if (val > t->tm_wday)
282 return adjday(t, '+', val - t->tm_wday);
283 }
284 return 1;
285}
286
287static int
201 case '+':
202 if (istext)
203 if (val < t->tm_wday)
204 val = 7 - t->tm_wday + val; /* early next week */
205 else
206 val -= t->tm_wday; /* later this week */
207 else
208 val *= 7; /* "-W +5" == "5 weeks in the future" */

--- 14 unchanged lines hidden (view full) ---

223 return 0;
224 else if (val > t->tm_wday)
225 return adjday(t, '+', val - t->tm_wday);
226 }
227 return 1;
228}
229
230static int
288sadjday(struct tm *t, char *arg)
231adjhour(struct tm *t, char type, int val)
289{
232{
290 switch (*arg) {
233 if (val < 0)
234 return 0;
235
236 switch (type) {
291 case '+':
237 case '+':
238 if (!adjday(t, '+', (t->tm_hour + val) / 24))
239 return 0;
240 val %= 24;
241 t->tm_hour += val;
242 if (t->tm_hour > 23)
243 t->tm_hour -= 24;
244 break;
245
292 case '-':
246 case '-':
293 return adjday(t, *arg, atoi(arg+1));
247 if (!adjday(t, '-', val / 24))
248 return 0;
249 val %= 24;
250 if (val > t->tm_hour) {
251 if (!adjday(t, '-', 1))
252 return 0;
253 val -= 24;
254 }
255 t->tm_hour -= val;
256 break;
257
294 default:
258 default:
295 return adjday(t, '\0', atoi(arg));
259 if (val > 23)
260 return 0;
261 t->tm_hour = val;
296 }
262 }
263
264 return mktime(t) != -1;
297}
298
265}
266
267static int
268adjmin(struct tm *t, char type, int val)
269{
270 if (val < 0)
271 return 0;
272
273 switch (type) {
274 case '+':
275 if (!adjhour(t, '+', (t->tm_min + val) / 60))
276 return 0;
277 val %= 60;
278 t->tm_min += val;
279 if (t->tm_min > 59)
280 t->tm_min -= 60;
281 break;
282
283 case '-':
284 if (!adjhour(t, '-', val / 60))
285 return 0;
286 val %= 60;
287 if (val > t->tm_min) {
288 if (!adjhour(t, '-', 1))
289 return 0;
290 val -= 60;
291 }
292 t->tm_min -= val;
293 break;
294
295 default:
296 if (val > 59)
297 return 0;
298 t->tm_min = val;
299 }
300
301 return mktime(t) != -1;
302}
303
299const struct vary *
300vary_apply(const struct vary *v, struct tm *t)
301{
304const struct vary *
305vary_apply(const struct vary *v, struct tm *t)
306{
307 char type;
308 char which;
309 char *arg;
310 int len;
311 int val;
312
302 for (; v; v = v->next) {
313 for (; v; v = v->next) {
303 switch (v->flag) {
304 case 'D':
305 if (!sadjday(t, v->arg))
314 type = *v->arg;
315 arg = v->arg;
316 if (type == '+' || type == '-')
317 arg++;
318 else
319 type = '\0';
320 len = strlen(arg);
321 if (len < 2)
322 return v;
323
324 if (strspn(arg, digits) != len-1) {
325 val = trans(trans_wday, arg);
326 if (val != -1) {
327 if (!adjwday(t, type, val, 1))
328 return v;
329 } else {
330 val = trans(trans_mon, arg);
331 if (val != -1) {
332 if (!adjmon(t, type, val, 1))
333 return v;
334 } else
306 return v;
335 return v;
307 break;
308 case 'W':
309 if (!sadjwday(t, v->arg))
336 }
337 } else {
338 val = atoi(arg);
339 which = arg[len-1];
340
341 switch (which) {
342 case 'M':
343 if (!adjmin(t, type, val))
344 return v;
345 break;
346 case 'H':
347 if (!adjhour(t, type, val))
348 return v;
349 break;
350 case 'd':
351 if (!adjday(t, type, val))
352 return v;
353 break;
354 case 'w':
355 if (!adjwday(t, type, val, 0))
356 return v;
357 break;
358 case 'm':
359 if (!adjmon(t, type, val, 0))
360 return v;
361 break;
362 case 'y':
363 if (!adjyear(t, type, val))
364 return v;
365 break;
366 default:
310 return v;
367 return v;
311 break;
312 case 'M':
313 if (!sadjmon(t, v->arg))
314 return v;
315 break;
316 case 'Y':
317 if (!sadjyear(t, v->arg))
318 return v;
319 break;
320 default:
321 return v;
368 }
322 }
323 }
324 return 0;
325}
326
327void
328vary_destroy(struct vary *v)
329{
330 struct vary *n;
331
332 while (v) {
333 n = v->next;
334 free(v);
335 v = n;
336 }
337}
369 }
370 }
371 return 0;
372}
373
374void
375vary_destroy(struct vary *v)
376{
377 struct vary *n;
378
379 while (v) {
380 n = v->next;
381 free(v);
382 v = n;
383 }
384}