Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/tests/date.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1999-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* tmscan(3) tmfmt(3) tester
23
*
24
* testdate [-c] [-v] < testre.dat
25
*
26
* -c catch signals and non-terminating tmscan()
27
* -v list each test line
28
*
29
* see comments in testdate.dat for description of format
30
*/
31
32
static const char id[] = "\n@(#)$Id: testdate (AT&T Research) 2005-01-04 $\0\n";
33
34
#include <ast.h>
35
#include <ctype.h>
36
#include <setjmp.h>
37
#include <signal.h>
38
#include <tm.h>
39
40
#ifdef __STDC__
41
#include <stdlib.h>
42
#endif
43
44
#ifndef NiL
45
#ifdef __STDC__
46
#define NiL 0
47
#else
48
#define NiL (char*)0
49
#endif
50
#endif
51
52
#ifndef elementsof
53
#define elementsof(x) (sizeof(x)/sizeof(x[0]))
54
#endif
55
56
#ifndef streq
57
#define streq(a,b) (*(a)==*(b)&&!strcmp(a,b))
58
#endif
59
60
static struct
61
{
62
int errors;
63
int lineno;
64
int sig;
65
int signals;
66
int warnings;
67
jmp_buf gotcha;
68
} state;
69
70
static void
71
normal(char* s)
72
{
73
unsigned char* u = (unsigned char*)s;
74
int c;
75
76
if (!u)
77
sfprintf(sfstdout, "NIL");
78
else if (!*u)
79
sfprintf(sfstdout, "NULL");
80
else for (;;)
81
switch (c = *u++)
82
{
83
case 0:
84
return;
85
case '\n':
86
sfprintf(sfstdout, "\\n");
87
break;
88
case '\r':
89
sfprintf(sfstdout, "\\r");
90
break;
91
case '\t':
92
sfprintf(sfstdout, "\\t");
93
break;
94
default:
95
if (isprint(c))
96
sfputc(sfstdout, c);
97
else
98
sfprintf(sfstdout, "\\x%02x", c);
99
break;
100
}
101
}
102
103
static void
104
report(char* comment, char* str, char* pat, char* rem, int flags)
105
{
106
state.errors++;
107
sfprintf(sfstdout, "%d:\t", state.lineno);
108
if (str)
109
{
110
normal(str);
111
if (pat)
112
{
113
sfprintf(sfstdout, " vs ");
114
normal(pat);
115
}
116
}
117
if (flags & TM_PEDANTIC)
118
sfprintf(sfstdout, " PEDANTIC");
119
if (state.sig)
120
{
121
sfprintf(sfstdout, " %s", fmtsignal(state.sig));
122
state.sig = 0;
123
}
124
if (rem && *rem)
125
{
126
if (*rem == '\n')
127
{
128
if (comment)
129
{
130
sfprintf(sfstdout, " %s", comment);
131
comment = 0;
132
}
133
sfprintf(sfstdout, "%s", rem);
134
}
135
else
136
{
137
sfprintf(sfstdout, " at ");
138
normal(rem);
139
}
140
}
141
if (comment)
142
sfprintf(sfstdout, " %s", comment);
143
sfprintf(sfstdout, "\n");
144
}
145
146
static void
147
bad(char* comment, char* str, char* pat)
148
{
149
sfprintf(sfstdout, "bad test case ");
150
report(comment, str, pat, NiL, 0);
151
exit(1);
152
}
153
154
static int
155
hex(int c)
156
{
157
return isdigit(c) ? (c - '0') : (c - (isupper(c) ? 'A' : 'a') + 10);
158
}
159
160
static void
161
escape(char* s)
162
{
163
char* t;
164
165
for (t = s; *t = *s; s++, t++)
166
{
167
if (*s != '\\')
168
continue;
169
switch (*++s)
170
{
171
case 0:
172
*++t = 0;
173
break;
174
case 'n':
175
*t = '\n';
176
break;
177
case 'r':
178
*t = '\r';
179
break;
180
case 't':
181
*t = '\t';
182
break;
183
case 'x':
184
if (!isxdigit(s[1]) || !isxdigit(s[2]))
185
bad("bad \\x\n", NiL, NiL);
186
*t = hex(*++s) << 4;
187
*t |= hex(*++s);
188
break;
189
default:
190
s--;
191
break;
192
}
193
}
194
}
195
196
static void
197
sigunblock(int s)
198
{
199
#ifdef SIG_SETMASK
200
int op;
201
sigset_t mask;
202
203
sigemptyset(&mask);
204
if (s)
205
{
206
sigaddset(&mask, s);
207
op = SIG_UNBLOCK;
208
}
209
else
210
op = SIG_SETMASK;
211
sigprocmask(op, &mask, NiL);
212
#else
213
#ifdef sigmask
214
sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L);
215
#endif
216
#endif
217
}
218
219
static void
220
gotcha(int sig)
221
{
222
signal(sig, gotcha);
223
alarm(0);
224
state.signals++;
225
state.sig = sig;
226
sigunblock(sig);
227
longjmp(state.gotcha, 1);
228
}
229
230
int
231
main(int argc, char** argv)
232
{
233
int i;
234
long flags;
235
char* p;
236
char* s;
237
char* e;
238
char* f;
239
char* str;
240
char* fmt;
241
char* ans;
242
char* field[6];
243
time_t t_str;
244
time_t t_now;
245
time_t t_ans;
246
247
int catch = 0;
248
int testno = 0;
249
int verbose = 0;
250
251
sfprintf(sfstdout, "TEST tmscan");
252
while ((p = *++argv) && *p == '-')
253
for (;;)
254
{
255
switch (*++p)
256
{
257
case 0:
258
break;
259
case 'c':
260
catch = 1;
261
sfprintf(sfstdout, ", catch");
262
continue;
263
case 'v':
264
verbose = 1;
265
sfprintf(sfstdout, ", verbose");
266
continue;
267
default:
268
sfprintf(sfstdout, ", invalid option %c", *p);
269
continue;
270
}
271
break;
272
}
273
if (p)
274
sfprintf(sfstdout, ", argument(s) ignored");
275
sfprintf(sfstdout, "\n");
276
if (catch)
277
{
278
signal(SIGALRM, gotcha);
279
signal(SIGBUS, gotcha);
280
signal(SIGSEGV, gotcha);
281
}
282
t_now = time(NiL);
283
while (p = sfgetr(sfstdin, '\n', 1))
284
{
285
state.lineno++;
286
287
/* parse: */
288
289
if (*p == 0 || *p == '#')
290
continue;
291
if (*p == ':')
292
{
293
while (*++p == ' ');
294
sfprintf(sfstdout, "NOTE %s\n", p);
295
continue;
296
}
297
i = 0;
298
field[i++] = p;
299
for (;;)
300
{
301
switch (*p++)
302
{
303
304
case 0:
305
p--;
306
goto checkfield;
307
case '\t':
308
*(p - 1) = 0;
309
checkfield:
310
s = field[i - 1];
311
if (streq(s, "NIL"))
312
field[i - 1] = 0;
313
else if (streq(s, "NULL"))
314
*s = 0;
315
while (*p == '\t')
316
p++;
317
if (!*p)
318
break;
319
if (i >= elementsof(field))
320
bad("too many fields\n", NiL, NiL);
321
field[i++] = p;
322
/*FALLTHROUGH*/
323
default:
324
continue;
325
}
326
break;
327
}
328
329
/* interpret: */
330
331
if (i < 3)
332
bad("too few fields\n", NiL, NiL);
333
while (i < elementsof(field))
334
field[i++] = 0;
335
if (str = field[0])
336
escape(str);
337
if (fmt = field[1])
338
escape(fmt);
339
if (!(ans = field[2]))
340
bad("NIL answer", NiL, NiL);
341
if (str)
342
{
343
if (streq(str, "SET"))
344
{
345
if (!fmt)
346
bad("NIL SET variable", NiL, NiL);
347
if (streq(fmt, "NOW"))
348
{
349
t_now = tmdate(ans, &e, &t_now);
350
if (*e)
351
bad("invalid NOW", ans, NiL);
352
sfprintf(sfstdout, "NOTE base date is %s\n", fmttime(NiL, t_now));
353
}
354
else
355
bad("unknown SET variable", fmt, NiL);
356
continue;
357
}
358
if (streq(str, "FMT"))
359
{
360
str = 0;
361
if (!fmt)
362
{
363
bad("NIL format", NiL, NiL);
364
continue;
365
}
366
t_now = tmdate(fmt, &e, &t_now);
367
if (*e)
368
bad("invalid NOW", fmt, NiL);
369
if (fmt = ans)
370
escape(fmt);
371
if (!(ans = field[3]))
372
bad("NIL answer", NiL, NiL);
373
}
374
}
375
flags = 0;
376
sfsync(sfstdout);
377
if (verbose)
378
sfprintf(sfstdout, "%d: str=`%s' fmt=`%s' ans=`%s'\n", state.lineno, str, fmt, ans);
379
if (!str)
380
{
381
testno++;
382
s = fmttime(fmt, t_now);
383
escape(ans);
384
if (strcmp(s, ans))
385
report("FAILED", s, ans, NiL, 0);
386
continue;
387
}
388
t_ans = tmdate(ans, &e, &t_now);
389
if (*e)
390
report("answer FAILED", e, NiL, NiL, 0);
391
s = fmttime("%k", t_ans);
392
if (strcmp(ans, s))
393
{
394
testno++;
395
report("FAILED", s, ans, NiL, 0);
396
}
397
else for (;;)
398
{
399
testno++;
400
t_str = tmscan(str, &e, fmt, &f, &t_now, flags);
401
if (*e)
402
{
403
report("subject FAILED", str, fmt, e, flags);
404
break;
405
}
406
else if (*f)
407
{
408
report("format FAILED", str, fmt, f, flags);
409
break;
410
}
411
else if (t_str != t_ans)
412
{
413
int n;
414
char tmp[128];
415
416
n = sfsprintf(tmp, sizeof(tmp), "\n\t[%s] expecting", fmttime(NiL, t_str));
417
sfsprintf(tmp + n, sizeof(tmp) - n, " [%s]", fmttime(NiL, t_ans));
418
report("FAILED", str, fmt, tmp, flags);
419
break;
420
}
421
if (flags & TM_PEDANTIC)
422
break;
423
flags |= TM_PEDANTIC;
424
}
425
}
426
sfprintf(sfstdout, "TEST tmscan, %d test%s", testno, testno == 1 ? "" : "s");
427
if (state.warnings)
428
sfprintf(sfstdout, ", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s");
429
if (state.signals)
430
sfprintf(sfstdout, ", %d signals", state.signals);
431
sfprintf(sfstdout, ", %d error%s\n", state.errors, state.errors == 1 ? "" : "s");
432
return 0;
433
}
434
435