1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
43e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin * Glenn Fowler
25da2e3ebdSchin * AT&T Research
26da2e3ebdSchin *
27da2e3ebdSchin * Time_t conversion support
28da2e3ebdSchin *
29da2e3ebdSchin * scan date expression in s using format
30da2e3ebdSchin * if non-null, e points to the first invalid sequence in s
31da2e3ebdSchin * if non-null, f points to the first unused format char
32da2e3ebdSchin * t provides default values
33da2e3ebdSchin */
34da2e3ebdSchin
35da2e3ebdSchin #include <tmx.h>
36da2e3ebdSchin #include <ctype.h>
37da2e3ebdSchin
38da2e3ebdSchin typedef struct
39da2e3ebdSchin {
40da2e3ebdSchin int32_t nsec;
41da2e3ebdSchin int year;
42da2e3ebdSchin int mon;
43da2e3ebdSchin int week;
44da2e3ebdSchin int weektype;
45da2e3ebdSchin int yday;
46da2e3ebdSchin int mday;
47da2e3ebdSchin int wday;
48da2e3ebdSchin int hour;
49da2e3ebdSchin int min;
50da2e3ebdSchin int sec;
51da2e3ebdSchin int meridian;
52da2e3ebdSchin int zone;
53da2e3ebdSchin } Set_t;
54da2e3ebdSchin
55da2e3ebdSchin #define CLEAR(s) (s.year=s.mon=s.week=s.weektype=s.yday=s.mday=s.wday=s.hour=s.min=s.sec=s.meridian=(-1),s.nsec=1000000000L,s.zone=TM_LOCALZONE)
56da2e3ebdSchin
57da2e3ebdSchin #define INDEX(m,x) (((n)>=((x)-(m)))?((n)-=((x)-(m))):(n))
58da2e3ebdSchin
59da2e3ebdSchin #define NUMBER(d,m,x) do \
60da2e3ebdSchin { \
61da2e3ebdSchin n = 0; \
62da2e3ebdSchin u = (char*)s; \
63da2e3ebdSchin while (s < (const char*)(u + d) && *s >= '0' && *s <= '9') \
64da2e3ebdSchin n = n * 10 + *s++ - '0'; \
65da2e3ebdSchin if (u == (char*)s || n < m || n > x) \
66da2e3ebdSchin goto next; \
67da2e3ebdSchin } while (0)
68da2e3ebdSchin
69da2e3ebdSchin /*
70da2e3ebdSchin * generate a Time_t from tm + set
71da2e3ebdSchin */
72da2e3ebdSchin
73da2e3ebdSchin static Time_t
gen(register Tm_t * tm,register Set_t * set)74da2e3ebdSchin gen(register Tm_t* tm, register Set_t* set)
75da2e3ebdSchin {
76da2e3ebdSchin register int n;
7734f9b3eeSRoland Mainz int z;
78da2e3ebdSchin Time_t t;
79da2e3ebdSchin
80da2e3ebdSchin if (set->year >= 0)
81da2e3ebdSchin tm->tm_year = set->year;
82da2e3ebdSchin if (set->mon >= 0)
83da2e3ebdSchin {
84da2e3ebdSchin if (set->year < 0 && set->mon < tm->tm_mon)
85da2e3ebdSchin tm->tm_year++;
86da2e3ebdSchin tm->tm_mon = set->mon;
87da2e3ebdSchin if (set->yday < 0 && set->mday < 0)
88da2e3ebdSchin tm->tm_mday = set->mday = 1;
89da2e3ebdSchin }
90da2e3ebdSchin if (set->week >= 0)
91da2e3ebdSchin {
92da2e3ebdSchin if (set->mon < 0)
93da2e3ebdSchin {
94da2e3ebdSchin tmweek(tm, set->weektype, set->week, set->wday);
95da2e3ebdSchin set->wday = -1;
96da2e3ebdSchin }
97da2e3ebdSchin }
98da2e3ebdSchin else if (set->yday >= 0)
99da2e3ebdSchin {
100da2e3ebdSchin if (set->mon < 0)
101da2e3ebdSchin {
102da2e3ebdSchin tm->tm_mon = 0;
103da2e3ebdSchin tm->tm_mday = set->yday + 1;
104da2e3ebdSchin }
105da2e3ebdSchin }
106da2e3ebdSchin else if (set->mday >= 0)
107da2e3ebdSchin tm->tm_mday = set->mday;
108da2e3ebdSchin if (set->hour >= 0)
109da2e3ebdSchin {
110da2e3ebdSchin if (set->hour < tm->tm_hour && set->yday < 0 && set->mday < 0 && set->wday < 0)
111da2e3ebdSchin tm->tm_mday++;
112da2e3ebdSchin tm->tm_hour = set->hour;
113da2e3ebdSchin tm->tm_min = (set->min >= 0) ? set->min : 0;
114da2e3ebdSchin tm->tm_sec = (set->sec >= 0) ? set->sec : 0;
115da2e3ebdSchin }
116da2e3ebdSchin else if (set->min >= 0)
117da2e3ebdSchin {
118da2e3ebdSchin tm->tm_min = set->min;
119da2e3ebdSchin tm->tm_sec = (set->sec >= 0) ? set->sec : 0;
120da2e3ebdSchin }
121da2e3ebdSchin else if (set->sec >= 0)
122da2e3ebdSchin tm->tm_sec = set->sec;
123da2e3ebdSchin if (set->nsec < 1000000000L)
124da2e3ebdSchin tm->tm_nsec = set->nsec;
125da2e3ebdSchin if (set->meridian > 0)
126da2e3ebdSchin {
127da2e3ebdSchin if (tm->tm_hour < 12)
128da2e3ebdSchin tm->tm_hour += 12;
129da2e3ebdSchin }
130da2e3ebdSchin else if (set->meridian == 0)
131da2e3ebdSchin {
132da2e3ebdSchin if (tm->tm_hour >= 12)
133da2e3ebdSchin tm->tm_hour -= 12;
134da2e3ebdSchin }
135da2e3ebdSchin t = tmxtime(tm, set->zone);
136da2e3ebdSchin if (set->yday >= 0)
137da2e3ebdSchin {
13834f9b3eeSRoland Mainz z = 1;
13934f9b3eeSRoland Mainz tm = tmxtm(tm, t, tm->tm_zone);
140da2e3ebdSchin tm->tm_mday += set->yday - tm->tm_yday;
141da2e3ebdSchin }
142da2e3ebdSchin else if (set->wday >= 0)
143da2e3ebdSchin {
14434f9b3eeSRoland Mainz z = 1;
14534f9b3eeSRoland Mainz tm = tmxtm(tm, t, tm->tm_zone);
146da2e3ebdSchin if ((n = set->wday - tm->tm_wday) < 0)
147da2e3ebdSchin n += 7;
148da2e3ebdSchin tm->tm_mday += n;
149da2e3ebdSchin }
15034f9b3eeSRoland Mainz else
15134f9b3eeSRoland Mainz z = 0;
152da2e3ebdSchin if (set->nsec < 1000000000L)
153da2e3ebdSchin {
15434f9b3eeSRoland Mainz if (!z)
15534f9b3eeSRoland Mainz {
15634f9b3eeSRoland Mainz z = 1;
15734f9b3eeSRoland Mainz tm = tmxtm(tm, t, tm->tm_zone);
15834f9b3eeSRoland Mainz }
159da2e3ebdSchin tm->tm_nsec = set->nsec;
160da2e3ebdSchin }
16134f9b3eeSRoland Mainz return z ? tmxtime(tm, set->zone) : t;
162da2e3ebdSchin }
163da2e3ebdSchin
164da2e3ebdSchin /*
165da2e3ebdSchin * the format scan workhorse
166da2e3ebdSchin */
167da2e3ebdSchin
168da2e3ebdSchin static Time_t
scan(register const char * s,char ** e,const char * format,char ** f,Time_t t,long flags)169da2e3ebdSchin scan(register const char* s, char** e, const char* format, char** f, Time_t t, long flags)
170da2e3ebdSchin {
171da2e3ebdSchin register int d;
172da2e3ebdSchin register int n;
173da2e3ebdSchin register char* p;
174da2e3ebdSchin register Tm_t* tm;
175da2e3ebdSchin const char* b;
176da2e3ebdSchin char* u;
177da2e3ebdSchin char* stack[4];
178da2e3ebdSchin int m;
179da2e3ebdSchin int hi;
180da2e3ebdSchin int lo;
181da2e3ebdSchin int pedantic;
182da2e3ebdSchin Time_t x;
183da2e3ebdSchin Set_t set;
184da2e3ebdSchin Tm_zone_t* zp;
18534f9b3eeSRoland Mainz Tm_t ts;
186da2e3ebdSchin
187da2e3ebdSchin char** sp = &stack[0];
188da2e3ebdSchin
189da2e3ebdSchin while (isspace(*s))
190da2e3ebdSchin s++;
191da2e3ebdSchin b = s;
192da2e3ebdSchin again:
193da2e3ebdSchin CLEAR(set);
19434f9b3eeSRoland Mainz tm = tmxtm(&ts, t, NiL);
195da2e3ebdSchin pedantic = (flags & TM_PEDANTIC) != 0;
196da2e3ebdSchin for (;;)
197da2e3ebdSchin {
198da2e3ebdSchin if (!(d = *format++))
199da2e3ebdSchin {
200da2e3ebdSchin if (sp <= &stack[0])
201da2e3ebdSchin {
202da2e3ebdSchin format--;
203da2e3ebdSchin break;
204da2e3ebdSchin }
205da2e3ebdSchin format = (const char*)*--sp;
206da2e3ebdSchin }
207da2e3ebdSchin else if (!*s)
208da2e3ebdSchin {
209da2e3ebdSchin format--;
210da2e3ebdSchin break;
211da2e3ebdSchin }
212da2e3ebdSchin else if (d == '%' && (d = *format) && format++ && d != '%')
213da2e3ebdSchin {
214da2e3ebdSchin more:
215da2e3ebdSchin switch (d)
216da2e3ebdSchin {
217da2e3ebdSchin case 'a':
218da2e3ebdSchin lo = TM_DAY_ABBREV;
219da2e3ebdSchin hi = pedantic ? TM_DAY : TM_TIME;
220da2e3ebdSchin goto get_wday;
221da2e3ebdSchin case 'A':
222da2e3ebdSchin lo = pedantic ? TM_DAY : TM_DAY_ABBREV;
223da2e3ebdSchin hi = TM_TIME;
224da2e3ebdSchin get_wday:
225da2e3ebdSchin if ((n = tmlex(s, &u, tm_info.format + lo, hi - lo, NiL, 0)) < 0)
226da2e3ebdSchin goto next;
227da2e3ebdSchin s = u;
228da2e3ebdSchin INDEX(TM_DAY_ABBREV, TM_DAY);
229da2e3ebdSchin set.wday = n;
230da2e3ebdSchin continue;
231da2e3ebdSchin case 'b':
232da2e3ebdSchin case 'h':
233da2e3ebdSchin lo = TM_MONTH_ABBREV;
234da2e3ebdSchin hi = pedantic ? TM_MONTH : TM_DAY_ABBREV;
235da2e3ebdSchin goto get_mon;
236da2e3ebdSchin case 'B':
237da2e3ebdSchin lo = pedantic ? TM_MONTH : TM_MONTH_ABBREV;
238da2e3ebdSchin hi = TM_DAY_ABBREV;
239da2e3ebdSchin get_mon:
240da2e3ebdSchin if ((n = tmlex(s, &u, tm_info.format + lo, hi - lo, NiL, 0)) < 0)
241da2e3ebdSchin goto next;
242da2e3ebdSchin s = u;
243da2e3ebdSchin INDEX(TM_MONTH_ABBREV, TM_MONTH);
244da2e3ebdSchin set.mon = n;
245da2e3ebdSchin continue;
246da2e3ebdSchin case 'c':
247da2e3ebdSchin p = "%a %b %e %T %Y";
248da2e3ebdSchin break;
249da2e3ebdSchin case 'C':
250da2e3ebdSchin NUMBER(2, 19, 99);
251da2e3ebdSchin set.year = (n - 19) * 100 + tm->tm_year % 100;
252da2e3ebdSchin continue;
253da2e3ebdSchin case 'd':
254da2e3ebdSchin if (pedantic && !isdigit(*s))
255da2e3ebdSchin goto next;
256da2e3ebdSchin /*FALLTHROUGH*/
257da2e3ebdSchin case 'e':
258da2e3ebdSchin NUMBER(2, 1, 31);
259da2e3ebdSchin set.mday = n;
260da2e3ebdSchin continue;
261da2e3ebdSchin case 'D':
262da2e3ebdSchin p = "%m/%d/%y";
263da2e3ebdSchin break;
264da2e3ebdSchin case 'E':
265da2e3ebdSchin case 'O':
266da2e3ebdSchin if (*format)
267da2e3ebdSchin {
268da2e3ebdSchin d = *format++;
269da2e3ebdSchin goto more;
270da2e3ebdSchin }
271da2e3ebdSchin continue;
2727c2fbfb3SApril Chin case 'F':
2737c2fbfb3SApril Chin p = "%Y-%m-%d";
2747c2fbfb3SApril Chin break;
275da2e3ebdSchin case 'H':
276da2e3ebdSchin case 'k':
277da2e3ebdSchin NUMBER(2, 0, 23);
278da2e3ebdSchin set.hour = n;
279da2e3ebdSchin continue;
280da2e3ebdSchin case 'I':
281da2e3ebdSchin case 'l':
282da2e3ebdSchin NUMBER(2, 1, 12);
283da2e3ebdSchin set.hour = n;
284da2e3ebdSchin continue;
285da2e3ebdSchin case 'j':
286da2e3ebdSchin NUMBER(3, 1, 366);
287da2e3ebdSchin set.yday = n - 1;
288da2e3ebdSchin continue;
289da2e3ebdSchin case 'm':
290da2e3ebdSchin NUMBER(2, 1, 12);
291da2e3ebdSchin set.mon = n - 1;
292da2e3ebdSchin continue;
293da2e3ebdSchin case 'M':
294da2e3ebdSchin NUMBER(2, 0, 59);
295da2e3ebdSchin set.min = n;
296da2e3ebdSchin continue;
297da2e3ebdSchin case 'n':
298da2e3ebdSchin if (pedantic)
299da2e3ebdSchin while (*s == '\n')
300da2e3ebdSchin s++;
301da2e3ebdSchin else
302da2e3ebdSchin while (isspace(*s))
303da2e3ebdSchin s++;
304da2e3ebdSchin continue;
305da2e3ebdSchin case 'N':
306da2e3ebdSchin NUMBER(9, 0, 999999999L);
307da2e3ebdSchin set.nsec = n;
308da2e3ebdSchin continue;
309da2e3ebdSchin case 'p':
310da2e3ebdSchin if ((n = tmlex(s, &u, tm_info.format + TM_MERIDIAN, TM_UT - TM_MERIDIAN, NiL, 0)) < 0)
311da2e3ebdSchin goto next;
312da2e3ebdSchin set.meridian = n;
313da2e3ebdSchin s = u;
314da2e3ebdSchin continue;
315da2e3ebdSchin case 'r':
316da2e3ebdSchin p = "%I:%M:%S %p";
317da2e3ebdSchin break;
318da2e3ebdSchin case 'R':
319da2e3ebdSchin p = "%H:%M:%S";
320da2e3ebdSchin break;
321da2e3ebdSchin case 's':
322da2e3ebdSchin x = strtoul(s, &u, 0);
323da2e3ebdSchin if (s == u)
324da2e3ebdSchin goto next;
32534f9b3eeSRoland Mainz tm = tmxtm(tm, tmxsns(x, 0), tm->tm_zone);
326da2e3ebdSchin s = u;
327da2e3ebdSchin CLEAR(set);
328da2e3ebdSchin continue;
329da2e3ebdSchin case 'S':
330da2e3ebdSchin NUMBER(2, 0, 61);
331da2e3ebdSchin set.sec = n;
332da2e3ebdSchin continue;
333da2e3ebdSchin case 'u':
334da2e3ebdSchin NUMBER(2, 1, 7);
335da2e3ebdSchin set.wday = n % 7;
336da2e3ebdSchin continue;
337da2e3ebdSchin case 'U':
338da2e3ebdSchin NUMBER(2, 0, 52);
339da2e3ebdSchin set.week = n;
340da2e3ebdSchin set.weektype = 0;
341da2e3ebdSchin continue;
342da2e3ebdSchin case 'V':
343da2e3ebdSchin NUMBER(2, 1, 53);
344da2e3ebdSchin set.week = n;
345da2e3ebdSchin set.weektype = 2;
346da2e3ebdSchin continue;
347da2e3ebdSchin case 'w':
348da2e3ebdSchin NUMBER(2, 0, 6);
349da2e3ebdSchin set.wday = n;
350da2e3ebdSchin continue;
351da2e3ebdSchin case 'W':
352da2e3ebdSchin NUMBER(2, 0, 52);
353da2e3ebdSchin set.week = n;
354da2e3ebdSchin set.weektype = 1;
355da2e3ebdSchin continue;
356da2e3ebdSchin case 'x':
357da2e3ebdSchin p = tm_info.format[TM_DATE];
358da2e3ebdSchin break;
359da2e3ebdSchin case 'X':
360da2e3ebdSchin p = tm_info.format[TM_TIME];
361da2e3ebdSchin break;
362da2e3ebdSchin case 'y':
363da2e3ebdSchin NUMBER(2, 0, 99);
364da2e3ebdSchin if (n < TM_WINDOW)
365da2e3ebdSchin n += 100;
366da2e3ebdSchin set.year = n;
367da2e3ebdSchin continue;
368da2e3ebdSchin case 'Y':
369da2e3ebdSchin NUMBER(4, 1969, 2100);
370da2e3ebdSchin set.year = n - 1900;
371da2e3ebdSchin continue;
372da2e3ebdSchin case 'Z':
373da2e3ebdSchin case 'q':
374da2e3ebdSchin if (zp = tmtype(s, &u))
375da2e3ebdSchin {
376da2e3ebdSchin s = u;
377da2e3ebdSchin u = zp->type;
378da2e3ebdSchin }
379da2e3ebdSchin else
380da2e3ebdSchin u = 0;
381da2e3ebdSchin if (d == 'q')
382da2e3ebdSchin continue;
383*f592a640SToomas Soome case 'z':
384da2e3ebdSchin if ((zp = tmzone(s, &u, u, &m)))
385da2e3ebdSchin {
386da2e3ebdSchin s = u;
387da2e3ebdSchin set.zone = zp->west + m;
388da2e3ebdSchin tm_info.date = zp;
389da2e3ebdSchin }
390da2e3ebdSchin continue;
391da2e3ebdSchin case '|':
392da2e3ebdSchin s = b;
393da2e3ebdSchin goto again;
394da2e3ebdSchin case '&':
395da2e3ebdSchin x = gen(tm, &set);
396da2e3ebdSchin x = tmxdate(s, e, t);
397da2e3ebdSchin if (s == (const char*)*e)
398da2e3ebdSchin goto next;
399da2e3ebdSchin t = x;
400da2e3ebdSchin s = (const char*)*e;
401da2e3ebdSchin if (!*format || *format == '%' && *(format + 1) == '|')
402da2e3ebdSchin goto done;
403da2e3ebdSchin goto again;
404da2e3ebdSchin default:
405da2e3ebdSchin goto next;
406da2e3ebdSchin }
407da2e3ebdSchin if (sp >= &stack[elementsof(stack)])
408da2e3ebdSchin goto next;
409da2e3ebdSchin *sp++ = (char*)format;
410da2e3ebdSchin format = (const char*)p;
411da2e3ebdSchin }
412da2e3ebdSchin else if (isspace(d))
413da2e3ebdSchin while (isspace(*s))
414da2e3ebdSchin s++;
415da2e3ebdSchin else if (*s != d)
416da2e3ebdSchin break;
417da2e3ebdSchin else
418da2e3ebdSchin s++;
419da2e3ebdSchin }
420da2e3ebdSchin next:
421da2e3ebdSchin if (sp > &stack[0])
422da2e3ebdSchin format = (const char*)stack[0];
423da2e3ebdSchin if (*format)
424da2e3ebdSchin {
425da2e3ebdSchin p = (char*)format;
426da2e3ebdSchin if (!*s && *p == '%' && *(p + 1) == '|')
427da2e3ebdSchin format += strlen(format);
428da2e3ebdSchin else
429da2e3ebdSchin while (*p)
430da2e3ebdSchin if (*p++ == '%' && *p && *p++ == '|' && *p)
431da2e3ebdSchin {
432da2e3ebdSchin format = (const char*)p;
433da2e3ebdSchin s = b;
434da2e3ebdSchin goto again;
435da2e3ebdSchin }
436da2e3ebdSchin }
437da2e3ebdSchin t = gen(tm, &set);
438da2e3ebdSchin done:
439da2e3ebdSchin if (e)
440da2e3ebdSchin {
441da2e3ebdSchin while (isspace(*s))
442da2e3ebdSchin s++;
443da2e3ebdSchin *e = (char*)s;
444da2e3ebdSchin }
445da2e3ebdSchin if (f)
446da2e3ebdSchin {
447da2e3ebdSchin while (isspace(*format))
448da2e3ebdSchin format++;
449da2e3ebdSchin *f = (char*)format;
450da2e3ebdSchin }
451da2e3ebdSchin return t;
452da2e3ebdSchin }
453da2e3ebdSchin
454da2e3ebdSchin /*
455da2e3ebdSchin * format==0 DATEMSK
456da2e3ebdSchin * *format==0 DATEMSK and tmxdate()
457da2e3ebdSchin * *format!=0 format
458da2e3ebdSchin */
459da2e3ebdSchin
460da2e3ebdSchin Time_t
tmxscan(const char * s,char ** e,const char * format,char ** f,Time_t t,long flags)461da2e3ebdSchin tmxscan(const char* s, char** e, const char* format, char** f, Time_t t, long flags)
462da2e3ebdSchin {
463da2e3ebdSchin register char* v;
464da2e3ebdSchin register char** p;
465da2e3ebdSchin char* q;
466da2e3ebdSchin char* r;
467da2e3ebdSchin Time_t x;
468da2e3ebdSchin
469da2e3ebdSchin static int initialized;
470da2e3ebdSchin static char** datemask;
471da2e3ebdSchin
472da2e3ebdSchin tmlocale();
473da2e3ebdSchin if (!format || !*format)
474da2e3ebdSchin {
475da2e3ebdSchin if (!initialized)
476da2e3ebdSchin {
477da2e3ebdSchin register Sfio_t* sp;
478da2e3ebdSchin register int n;
479da2e3ebdSchin off_t m;
480da2e3ebdSchin
481da2e3ebdSchin initialized = 1;
482da2e3ebdSchin if ((v = getenv("DATEMSK")) && *v && (sp = sfopen(NiL, v, "r")))
483da2e3ebdSchin {
484da2e3ebdSchin for (n = 1; sfgetr(sp, '\n', 0); n++);
485da2e3ebdSchin m = sfseek(sp, 0L, SEEK_CUR);
486da2e3ebdSchin if (p = newof(0, char*, n, m))
487da2e3ebdSchin {
488da2e3ebdSchin sfseek(sp, 0L, SEEK_SET);
489da2e3ebdSchin v = (char*)(p + n);
490da2e3ebdSchin if (sfread(sp, v, m) != m)
491da2e3ebdSchin {
492da2e3ebdSchin free(p);
493da2e3ebdSchin p = 0;
494da2e3ebdSchin }
495da2e3ebdSchin else
496da2e3ebdSchin {
497da2e3ebdSchin datemask = p;
498da2e3ebdSchin v[m] = 0;
499da2e3ebdSchin while (*v)
500da2e3ebdSchin {
501da2e3ebdSchin *p++ = v;
502da2e3ebdSchin if (!(v = strchr(v, '\n')))
503da2e3ebdSchin break;
504da2e3ebdSchin *v++ = 0;
505da2e3ebdSchin }
506da2e3ebdSchin *p = 0;
507da2e3ebdSchin }
508da2e3ebdSchin }
509da2e3ebdSchin }
510da2e3ebdSchin }
511da2e3ebdSchin if (p = datemask)
512da2e3ebdSchin while (v = *p++)
513da2e3ebdSchin {
514da2e3ebdSchin x = scan(s, &q, v, &r, t, flags);
515da2e3ebdSchin if (!*q && !*r)
516da2e3ebdSchin {
517da2e3ebdSchin if (e)
518da2e3ebdSchin *e = q;
519da2e3ebdSchin if (f)
520da2e3ebdSchin *f = r;
521da2e3ebdSchin return x;
522da2e3ebdSchin }
523da2e3ebdSchin }
524da2e3ebdSchin if (f)
525da2e3ebdSchin *f = (char*)format;
526da2e3ebdSchin if (format)
527da2e3ebdSchin return tmxdate(s, e, t);
528da2e3ebdSchin if (e)
529da2e3ebdSchin *e = (char*)s;
530da2e3ebdSchin return 0;
531da2e3ebdSchin }
532da2e3ebdSchin return scan(s, e, format, f, t, flags);
533da2e3ebdSchin }
534da2e3ebdSchin