3 ** Originally written by Steven M. Bellovin <smb@research.att.com> while
4 ** at the University of North Carolina at Chapel Hill. Later tweaked by
5 ** a couple of people on Usenet. Completely overhauled by Rich $alz
6 ** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
8 ** This grammar has 10 shift/reduce conflicts.
10 ** This code is in the public domain and has no copyright.
12 /* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
13 /* SUPPRESS 288 on yyerrlab *//* Label unused */
15 /* $FreeBSD: src/usr.bin/find/getdate.y,v 1.8 2012/05/22 16:33:10 bapt Exp $ */
20 /* The code at the top of get_date which figures out the offset of the
21 current time zone checks various CPP symbols to see if special
22 tricks are need, but defaults to using the gettimeofday system call.
23 Include <sys/time.h> if that will be used. */
27 #else /* defined(vms) */
28 # include <sys/types.h>
29 # include <sys/time.h>
30 #endif /* !defined(vms) */
32 #if defined (__STDC__) || defined (USG)
36 /* Some old versions of bison generate parsers that use bcopy.
37 That loses on systems that don't provide the function, so we have
38 to redefine it here. */
39 #if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
40 #define bcopy(from, to, len) memcpy ((to), (from), (len))
43 #if defined (__STDC__)
47 /* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
50 We don't want to mess with all the portability hassles of alloca.
51 In particular, most (all?) versions of bison will use alloca in
52 their parser. If bison works on your system (e.g. it should work
53 with gcc), then go ahead and use it, but the more general solution
54 is to use byacc instead of bison, which should generate a portable
55 parser. I played with adding "#define alloca dont_use_alloca", to
56 give an error if the parser generator uses alloca (and thus detect
57 unportable getdate.c's), but that seems to cause as many problems
62 #define yyparse getdate_yyparse
63 #define yylex getdate_yylex
64 #define yyerror getdate_yyerror
66 static int yylex(void);
67 static int yyerror(const char *);
69 time_t get_date
(char *);
72 #define HOUR(x) ((time_t)(x) * 60)
73 #define SECSPERDAY (24L * 60L * 60L)
77 ** An entry in the lexical lookup table.
79 typedef
struct _TABLE
{
87 ** Daylight-savings mode: on, off, or not yet known.
89 typedef
enum _DSTMODE
{
90 DSTon
, DSToff
, DSTmaybe
94 ** Meridian: am, pm, or 24-hour style.
96 typedef
enum _MERIDIAN
{
102 ** Global variables. We could get rid of most of these by using a good
103 ** union as the yacc stack. (This routine was originally written before
104 ** yacc had the %union construct.) Maybe someday; right now we only use
105 ** the %union very rarely.
107 static char *yyInput
;
108 static DSTMODE yyDSTmode
;
109 static time_t yyDayOrdinal
;
110 static time_t yyDayNumber
;
111 static int yyHaveDate
;
112 static int yyHaveDay
;
113 static int yyHaveRel
;
114 static int yyHaveTime
;
115 static int yyHaveZone
;
116 static time_t yyTimezone
;
118 static time_t yyHour
;
119 static time_t yyMinutes
;
120 static time_t yyMonth
;
121 static time_t yySeconds
;
122 static time_t yyYear
;
123 static MERIDIAN yyMeridian
;
124 static time_t yyRelMonth
;
125 static time_t yyRelSeconds
;
131 enum _MERIDIAN Meridian
;
134 %token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
135 %token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
137 %type
<Number
> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
138 %type
<Number
> tSEC_UNIT tSNUMBER tUNUMBER tZONE
139 %type
<Meridian
> tMERIDIAN o_merid
165 time
: tUNUMBER tMERIDIAN
{
171 | tUNUMBER
':' tUNUMBER o_merid
{
177 | tUNUMBER
':' tUNUMBER tSNUMBER
{
182 yyTimezone
= - ($4 %
100 + ($4 / 100) * 60);
184 | tUNUMBER
':' tUNUMBER
':' tUNUMBER o_merid
{
190 | tUNUMBER
':' tUNUMBER
':' tUNUMBER tSNUMBER
{
196 yyTimezone
= - ($6 %
100 + ($6 / 100) * 60);
229 date
: tUNUMBER
'/' tUNUMBER
{
233 | tUNUMBER
'/' tUNUMBER
'/' tUNUMBER
{
244 | tUNUMBER tSNUMBER tSNUMBER
{
245 /* ISO 8601 format. yyyy-mm-dd. */
250 | tUNUMBER tMONTH tSNUMBER
{
251 /* e.g. 17-JUN-1992. */
260 | tMONTH tUNUMBER
',' tUNUMBER
{
269 | tUNUMBER tMONTH tUNUMBER
{
277 yyRelSeconds
= -yyRelSeconds
;
278 yyRelMonth
= -yyRelMonth
;
283 relunit
: tUNUMBER tMINUTE_UNIT
{
284 yyRelSeconds
+= $1 * $2 * 60L;
286 | tSNUMBER tMINUTE_UNIT
{
287 yyRelSeconds
+= $1 * $2 * 60L;
290 yyRelSeconds
+= $1 * 60L;
292 | tSNUMBER tSEC_UNIT
{
295 | tUNUMBER tSEC_UNIT
{
301 | tSNUMBER tMONTH_UNIT
{
302 yyRelMonth
+= $1 * $2;
304 | tUNUMBER tMONTH_UNIT
{
305 yyRelMonth
+= $1 * $2;
313 if
(yyHaveTime
&& yyHaveDate
&& !yyHaveRel
)
319 yyMonth
= ($1/100)%
100;
330 yyMinutes
= $1 %
100;
339 o_merid
: /* NULL */ {
349 /* Month and day table. */
350 static TABLE
const MonthDayTable
[] = {
351 { "january", tMONTH
, 1 },
352 { "february", tMONTH
, 2 },
353 { "march", tMONTH
, 3 },
354 { "april", tMONTH
, 4 },
355 { "may", tMONTH
, 5 },
356 { "june", tMONTH
, 6 },
357 { "july", tMONTH
, 7 },
358 { "august", tMONTH
, 8 },
359 { "september", tMONTH
, 9 },
360 { "sept", tMONTH
, 9 },
361 { "october", tMONTH
, 10 },
362 { "november", tMONTH
, 11 },
363 { "december", tMONTH
, 12 },
364 { "sunday", tDAY
, 0 },
365 { "monday", tDAY
, 1 },
366 { "tuesday", tDAY
, 2 },
368 { "wednesday", tDAY
, 3 },
369 { "wednes", tDAY
, 3 },
370 { "thursday", tDAY
, 4 },
372 { "thurs", tDAY
, 4 },
373 { "friday", tDAY
, 5 },
374 { "saturday", tDAY
, 6 },
378 /* Time units table. */
379 static TABLE
const UnitsTable
[] = {
380 { "year", tMONTH_UNIT
, 12 },
381 { "month", tMONTH_UNIT
, 1 },
382 { "fortnight", tMINUTE_UNIT
, 14 * 24 * 60 },
383 { "week", tMINUTE_UNIT
, 7 * 24 * 60 },
384 { "day", tMINUTE_UNIT
, 1 * 24 * 60 },
385 { "hour", tMINUTE_UNIT
, 60 },
386 { "minute", tMINUTE_UNIT
, 1 },
387 { "min", tMINUTE_UNIT
, 1 },
388 { "second", tSEC_UNIT
, 1 },
389 { "sec", tSEC_UNIT
, 1 },
393 /* Assorted relative-time words. */
394 static TABLE
const OtherTable
[] = {
395 { "tomorrow", tMINUTE_UNIT
, 1 * 24 * 60 },
396 { "yesterday", tMINUTE_UNIT
, -1 * 24 * 60 },
397 { "today", tMINUTE_UNIT
, 0 },
398 { "now", tMINUTE_UNIT
, 0 },
399 { "last", tUNUMBER
, -1 },
400 { "this", tMINUTE_UNIT
, 0 },
401 { "next", tUNUMBER
, 2 },
402 { "first", tUNUMBER
, 1 },
403 /* { "second", tUNUMBER, 2 }, */
404 { "third", tUNUMBER
, 3 },
405 { "fourth", tUNUMBER
, 4 },
406 { "fifth", tUNUMBER
, 5 },
407 { "sixth", tUNUMBER
, 6 },
408 { "seventh", tUNUMBER
, 7 },
409 { "eighth", tUNUMBER
, 8 },
410 { "ninth", tUNUMBER
, 9 },
411 { "tenth", tUNUMBER
, 10 },
412 { "eleventh", tUNUMBER
, 11 },
413 { "twelfth", tUNUMBER
, 12 },
418 /* The timezone table. */
419 /* Some of these are commented out because a time_t can't store a float. */
420 static TABLE
const TimezoneTable
[] = {
421 { "gmt", tZONE
, HOUR
( 0) }, /* Greenwich Mean */
422 { "ut", tZONE
, HOUR
( 0) }, /* Universal (Coordinated) */
423 { "utc", tZONE
, HOUR
( 0) },
424 { "wet", tZONE
, HOUR
( 0) }, /* Western European */
425 { "bst", tDAYZONE
, HOUR
( 0) }, /* British Summer */
426 { "wat", tZONE
, HOUR
( 1) }, /* West Africa */
427 { "at", tZONE
, HOUR
( 2) }, /* Azores */
429 /* For completeness. BST is also British Summer, and GST is
430 * also Guam Standard. */
431 { "bst", tZONE
, HOUR
( 3) }, /* Brazil Standard */
432 { "gst", tZONE
, HOUR
( 3) }, /* Greenland Standard */
435 { "nft", tZONE
, HOUR
(3.5) }, /* Newfoundland */
436 { "nst", tZONE
, HOUR
(3.5) }, /* Newfoundland Standard */
437 { "ndt", tDAYZONE
, HOUR
(3.5) }, /* Newfoundland Daylight */
439 { "ast", tZONE
, HOUR
( 4) }, /* Atlantic Standard */
440 { "adt", tDAYZONE
, HOUR
( 4) }, /* Atlantic Daylight */
441 { "est", tZONE
, HOUR
( 5) }, /* Eastern Standard */
442 { "edt", tDAYZONE
, HOUR
( 5) }, /* Eastern Daylight */
443 { "cst", tZONE
, HOUR
( 6) }, /* Central Standard */
444 { "cdt", tDAYZONE
, HOUR
( 6) }, /* Central Daylight */
445 { "mst", tZONE
, HOUR
( 7) }, /* Mountain Standard */
446 { "mdt", tDAYZONE
, HOUR
( 7) }, /* Mountain Daylight */
447 { "pst", tZONE
, HOUR
( 8) }, /* Pacific Standard */
448 { "pdt", tDAYZONE
, HOUR
( 8) }, /* Pacific Daylight */
449 { "yst", tZONE
, HOUR
( 9) }, /* Yukon Standard */
450 { "ydt", tDAYZONE
, HOUR
( 9) }, /* Yukon Daylight */
451 { "hst", tZONE
, HOUR
(10) }, /* Hawaii Standard */
452 { "hdt", tDAYZONE
, HOUR
(10) }, /* Hawaii Daylight */
453 { "cat", tZONE
, HOUR
(10) }, /* Central Alaska */
454 { "ahst", tZONE
, HOUR
(10) }, /* Alaska-Hawaii Standard */
455 { "nt", tZONE
, HOUR
(11) }, /* Nome */
456 { "idlw", tZONE
, HOUR
(12) }, /* International Date Line West */
457 { "cet", tZONE
, -HOUR
(1) }, /* Central European */
458 { "met", tZONE
, -HOUR
(1) }, /* Middle European */
459 { "mewt", tZONE
, -HOUR
(1) }, /* Middle European Winter */
460 { "mest", tDAYZONE
, -HOUR
(1) }, /* Middle European Summer */
461 { "swt", tZONE
, -HOUR
(1) }, /* Swedish Winter */
462 { "sst", tDAYZONE
, -HOUR
(1) }, /* Swedish Summer */
463 { "fwt", tZONE
, -HOUR
(1) }, /* French Winter */
464 { "fst", tDAYZONE
, -HOUR
(1) }, /* French Summer */
465 { "eet", tZONE
, -HOUR
(2) }, /* Eastern Europe, USSR Zone 1 */
466 { "bt", tZONE
, -HOUR
(3) }, /* Baghdad, USSR Zone 2 */
468 { "it", tZONE
, -HOUR
(3.5) },/* Iran */
470 { "zp4", tZONE
, -HOUR
(4) }, /* USSR Zone 3 */
471 { "zp5", tZONE
, -HOUR
(5) }, /* USSR Zone 4 */
473 { "ist", tZONE
, -HOUR
(5.5) },/* Indian Standard */
475 { "zp6", tZONE
, -HOUR
(6) }, /* USSR Zone 5 */
477 /* For completeness. NST is also Newfoundland Stanard, and SST is
478 * also Swedish Summer. */
479 { "nst", tZONE
, -HOUR
(6.5) },/* North Sumatra */
480 { "sst", tZONE
, -HOUR
(7) }, /* South Sumatra, USSR Zone 6 */
482 { "wast", tZONE
, -HOUR
(7) }, /* West Australian Standard */
483 { "wadt", tDAYZONE
, -HOUR
(7) }, /* West Australian Daylight */
485 { "jt", tZONE
, -HOUR
(7.5) },/* Java (3pm in Cronusland!) */
487 { "cct", tZONE
, -HOUR
(8) }, /* China Coast, USSR Zone 7 */
488 { "jst", tZONE
, -HOUR
(9) }, /* Japan Standard, USSR Zone 8 */
490 { "cast", tZONE
, -HOUR
(9.5) },/* Central Australian Standard */
491 { "cadt", tDAYZONE
, -HOUR
(9.5) },/* Central Australian Daylight */
493 { "east", tZONE
, -HOUR
(10) }, /* Eastern Australian Standard */
494 { "eadt", tDAYZONE
, -HOUR
(10) }, /* Eastern Australian Daylight */
495 { "gst", tZONE
, -HOUR
(10) }, /* Guam Standard, USSR Zone 9 */
496 { "nzt", tZONE
, -HOUR
(12) }, /* New Zealand */
497 { "nzst", tZONE
, -HOUR
(12) }, /* New Zealand Standard */
498 { "nzdt", tDAYZONE
, -HOUR
(12) }, /* New Zealand Daylight */
499 { "idle", tZONE
, -HOUR
(12) }, /* International Date Line East */
503 /* Military timezone table. */
504 static TABLE
const MilitaryTable
[] = {
505 { "a", tZONE
, HOUR
( 1) },
506 { "b", tZONE
, HOUR
( 2) },
507 { "c", tZONE
, HOUR
( 3) },
508 { "d", tZONE
, HOUR
( 4) },
509 { "e", tZONE
, HOUR
( 5) },
510 { "f", tZONE
, HOUR
( 6) },
511 { "g", tZONE
, HOUR
( 7) },
512 { "h", tZONE
, HOUR
( 8) },
513 { "i", tZONE
, HOUR
( 9) },
514 { "k", tZONE
, HOUR
( 10) },
515 { "l", tZONE
, HOUR
( 11) },
516 { "m", tZONE
, HOUR
( 12) },
517 { "n", tZONE
, HOUR
(- 1) },
518 { "o", tZONE
, HOUR
(- 2) },
519 { "p", tZONE
, HOUR
(- 3) },
520 { "q", tZONE
, HOUR
(- 4) },
521 { "r", tZONE
, HOUR
(- 5) },
522 { "s", tZONE
, HOUR
(- 6) },
523 { "t", tZONE
, HOUR
(- 7) },
524 { "u", tZONE
, HOUR
(- 8) },
525 { "v", tZONE
, HOUR
(- 9) },
526 { "w", tZONE
, HOUR
(-10) },
527 { "x", tZONE
, HOUR
(-11) },
528 { "y", tZONE
, HOUR
(-12) },
529 { "z", tZONE
, HOUR
( 0) },
538 yyerror(const char *s __unused
)
545 ToSeconds
(time_t Hours
, time_t Minutes
, time_t Seconds
, MERIDIAN Meridian
)
547 if
(Minutes
< 0 || Minutes
> 59 || Seconds
< 0 || Seconds
> 59)
551 if
(Hours
< 0 || Hours
> 23)
553 return
(Hours
* 60L + Minutes
) * 60L + Seconds
;
555 if
(Hours
< 1 || Hours
> 12)
559 return
(Hours
* 60L + Minutes
) * 60L + Seconds
;
561 if
(Hours
< 1 || Hours
> 12)
565 return
((Hours
+ 12) * 60L + Minutes
) * 60L + Seconds
;
574 * A negative number, which means to use its absolute value (why?)
575 * A number from 0 to 99, which means a year from 1900 to 1999, or
576 * The actual year (>=100). */
578 Convert
(time_t Month
, time_t Day
, time_t Year
,
579 time_t Hours
, time_t Minutes
, time_t Seconds
,
580 MERIDIAN Meridian
, DSTMODE DSTmode
)
582 static int DaysInMonth
[12] = {
583 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
595 DaysInMonth
[1] = Year %
4 == 0 && (Year %
100 != 0 || Year %
400 == 0)
597 /* Checking for 2038 bogusly assumes that time_t is 32 bits. But
598 I'm too lazy to try to check for time_t overflow in another way. */
599 if
(Year
< EPOCH || Year
> 2038
600 || Month
< 1 || Month
> 12
601 /* Lint fluff: "conversion from long may lose accuracy" */
602 || Day
< 1 || Day
> DaysInMonth
[(int)--Month
])
605 for
(Julian
= Day
- 1, i
= 0; i
< Month
; i
++)
606 Julian
+= DaysInMonth
[i
];
607 for
(i
= EPOCH
; i
< Year
; i
++)
608 Julian
+= 365 + (i %
4 == 0);
609 Julian
*= SECSPERDAY
;
610 Julian
+= yyTimezone
* 60L;
611 if
((tod
= ToSeconds
(Hours
, Minutes
, Seconds
, Meridian
)) < 0)
615 ||
(DSTmode
== DSTmaybe
&& localtime
(&Julian
)->tm_isdst
))
622 DSTcorrect
(time_t Start
, time_t Future
)
627 StartDay
= (localtime
(&Start
)->tm_hour
+ 1) %
24;
628 FutureDay
= (localtime
(&Future
)->tm_hour
+ 1) %
24;
629 return
(Future
- Start
) + (StartDay
- FutureDay
) * 60L * 60L;
634 RelativeDate
(time_t Start
, time_t DayOrdinal
, time_t DayNumber
)
640 tm
= localtime
(&now
);
641 now
+= SECSPERDAY
* ((DayNumber
- tm
->tm_wday
+ 7) %
7);
642 now
+= 7 * SECSPERDAY
* (DayOrdinal
<= 0 ? DayOrdinal
: DayOrdinal
- 1);
643 return DSTcorrect
(Start
, now
);
648 RelativeMonth
(time_t Start
, time_t RelMonth
)
656 tm
= localtime
(&Start
);
657 Month
= 12 * (tm
->tm_year
+ 1900) + tm
->tm_mon
+ RelMonth
;
659 Month
= Month %
12 + 1;
660 return DSTcorrect
(Start
,
661 Convert
(Month
, (time_t)tm
->tm_mday
, Year
,
662 (time_t)tm
->tm_hour
, (time_t)tm
->tm_min
, (time_t)tm
->tm_sec
,
668 LookupWord
(char *buff
)
676 /* Make it lowercase. */
677 for
(p
= buff
; *p
; p
++)
681 if
(strcmp
(buff
, "am") == 0 || strcmp
(buff
, "a.m.") == 0) {
682 yylval.Meridian
= MERam
;
685 if
(strcmp
(buff
, "pm") == 0 || strcmp
(buff
, "p.m.") == 0) {
686 yylval.Meridian
= MERpm
;
690 /* See if we have an abbreviation for a month. */
691 if
(strlen
(buff
) == 3)
693 else if
(strlen
(buff
) == 4 && buff
[3] == '.') {
700 for
(tp
= MonthDayTable
; tp
->name
; tp
++) {
702 if
(strncmp
(buff
, tp
->name
, 3) == 0) {
703 yylval.Number
= tp
->value
;
707 else if
(strcmp
(buff
, tp
->name
) == 0) {
708 yylval.Number
= tp
->value
;
713 for
(tp
= TimezoneTable
; tp
->name
; tp
++)
714 if
(strcmp
(buff
, tp
->name
) == 0) {
715 yylval.Number
= tp
->value
;
719 if
(strcmp
(buff
, "dst") == 0)
722 for
(tp
= UnitsTable
; tp
->name
; tp
++)
723 if
(strcmp
(buff
, tp
->name
) == 0) {
724 yylval.Number
= tp
->value
;
728 /* Strip off any plural and try the units table again. */
729 i
= strlen
(buff
) - 1;
730 if
(buff
[i
] == 's') {
732 for
(tp
= UnitsTable
; tp
->name
; tp
++)
733 if
(strcmp
(buff
, tp
->name
) == 0) {
734 yylval.Number
= tp
->value
;
737 buff
[i
] = 's'; /* Put back for "this" in OtherTable. */
740 for
(tp
= OtherTable
; tp
->name
; tp
++)
741 if
(strcmp
(buff
, tp
->name
) == 0) {
742 yylval.Number
= tp
->value
;
746 /* Military timezones. */
747 if
(buff
[1] == '\0' && isalpha
(*buff
)) {
748 for
(tp
= MilitaryTable
; tp
->name
; tp
++)
749 if
(strcmp
(buff
, tp
->name
) == 0) {
750 yylval.Number
= tp
->value
;
755 /* Drop out any periods and try the timezone table again. */
756 for
(i
= 0, p
= q
= buff
; *q
; q
++)
763 for
(tp
= TimezoneTable
; tp
->name
; tp
++)
764 if
(strcmp
(buff
, tp
->name
) == 0) {
765 yylval.Number
= tp
->value
;
783 while
(isspace
(*yyInput
))
786 if
(isdigit
(c
= *yyInput
) || c
== '-' || c
== '+') {
787 if
(c
== '-' || c
== '+') {
788 sign
= c
== '-' ?
-1 : 1;
789 if
(!isdigit
(*++yyInput
))
790 /* skip the '-' sign */
795 for
(yylval.Number
= 0; isdigit
(c
= *yyInput
++); )
796 yylval.Number
= 10 * yylval.Number
+ c
- '0';
799 yylval.Number
= -yylval.Number
;
800 return sign ? tSNUMBER
: tUNUMBER
;
803 for
(p
= buff
; isalpha
(c
= *yyInput
++) || c
== '.'; )
804 if
(p
< &buff
[sizeof buff
- 1])
808 return LookupWord
(buff
);
825 #define TM_YEAR_ORIGIN 1900
827 /* Yield A - B, measured in seconds. */
829 difftm
(struct tm
*a
, struct tm
*b
)
831 int ay
= a
->tm_year
+ (TM_YEAR_ORIGIN
- 1);
832 int by
= b
->tm_year
+ (TM_YEAR_ORIGIN
- 1);
834 /* difference in day of year */
835 a
->tm_yday
- b
->tm_yday
836 /* + intervening leap days */
837 + ((ay
>> 2) - (by
>> 2))
839 + ((ay
/100 >> 2) - (by
/100 >> 2))
840 /* + difference in years * 365 */
841 + (long)(ay
-by
) * 365
843 return
(60*(60*(24*days
+ (a
->tm_hour
- b
->tm_hour
))
844 + (a
->tm_min
- b
->tm_min
))
845 + (a
->tm_sec
- b
->tm_sec
));
851 struct tm
*tm
, *gmt_ptr
, gmt
;
857 bzero
(&gmt
, sizeof
(struct tm
));
860 (void)time
(&nowtime
);
862 gmt_ptr
= gmtime
(&nowtime
);
865 /* Make a copy, in case localtime modifies *tm (I think
866 that comment now applies to *gmt_ptr, but I am too
867 lazy to dig into how gmtime and locatime allocate the
868 structures they return pointers to). */
872 if
(! (tm
= localtime
(&nowtime
)))
876 tzoff
= difftm
(&gmt
, tm
) / 60;
878 /* We are on a system like VMS, where the system clock is
879 in local time and the system has no concept of timezones.
880 Hopefully we can fake this out (for the case in which the
881 user specifies no timezone) by just saying the timezone
888 tm
= localtime
(&nowtime
);
889 yyYear
= tm
->tm_year
+ 1900;
890 yyMonth
= tm
->tm_mon
+ 1;
893 yyDSTmode
= DSTmaybe
;
907 || yyHaveTime
> 1 || yyHaveZone
> 1 || yyHaveDate
> 1 || yyHaveDay
> 1)
910 if
(yyHaveDate || yyHaveTime || yyHaveDay
) {
911 Start
= Convert
(yyMonth
, yyDay
, yyYear
, yyHour
, yyMinutes
, yySeconds
,
912 yyMeridian
, yyDSTmode
);
919 Start
-= ((tm
->tm_hour
* 60L + tm
->tm_min
) * 60L) + tm
->tm_sec
;
922 Start
+= yyRelSeconds
;
923 Start
+= RelativeMonth
(Start
, yyRelMonth
);
925 if
(yyHaveDay
&& !yyHaveDate
) {
926 tod
= RelativeDate
(Start
, yyDayOrdinal
, yyDayNumber
);
930 /* Have to do *something* with a legitimate -1 so it's distinguishable
931 * from the error return value. (Alternately could set errno on error.) */
932 return Start
== -1 ?
0 : Start
;
940 main
(int ac
, char *av
[])
945 (void)printf
("Enter date, or blank line to exit.\n\t> ");
946 (void)fflush
(stdout
);
947 while
(gets
(buff
) && buff
[0]) {
950 (void)printf
("Bad format - couldn't convert.\n");
952 (void)printf
("%s", ctime
(&d
));
953 (void)printf
("\t> ");
954 (void)fflush
(stdout
);
959 #endif /* defined(TEST) */