rousseau@osf.org (John Rousseau) (04/22/91)
FYI. Here is a copy of a letter I sent to a few people who also
were seeing the 01/00 date problem.
Thanks to the help of a few people and a lot of hacking I have fixed the
problem. I had to do two things to get it to work. I do not know if
Jim Valero's lex start state fix is required, but I currently don't
have time to back it out of my code and test it. I will send you the
changes below.
The other fix was that the version of lex that I am using creates
a slightly different output file than other lex'es. MH can not handle
these changes.
What I did was convert Jim Valero's MH 6.5 changes to the MH 6.7.1
dtimep.lex (in zotnet/tws). Then I ran 'make dtimep.c' from an Ultrix
machine. This created a good dtimep.c (which is where the problem lies).
I compiled from there without difficulty.
I would appreciate if one of you would try building without the
dtimep.lex changes to see if they are necessary.
If you need any help building MH, let me know. NetWisdom got me
through this, and it's only fair that I offer my help now too.
If you do not have the ability to run lex on a different machine,
try making dtimep.c and then look at the types for yymatch and yyextra.
They should be just 'char' for MH to grok it. My lex generated 'unsigned
char' for both of these which thoroughly broke dtimep.c. Change these to
'char' and compile. The _right_ way to fix this is to find where MH
is depending on these types and #ifdef it appropriately. Hopefully I
will get to it someday.
The following enclosure is my patched zotnet/tws/dtimep.lex for MH 6.7.1 .
Good luck!
-John
John Rousseau rousseau@osf.org
Postmaster uunet!osf.org!rousseau
Open Software Foundation (617) 621-8719
-------------------------------------------------
----cut here----
%e 2000
%p 5000
%n 1000
%a 4000
%START X,Z
sun (sun(day)?)
mon (mon(day)?)
tue (tue(sday)?)
wed (wed(nesday)?)
thu (thu(rsday)?)
fri (fri(day)?)
sat (sat(urday)?)
DAY ({sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat})
jan (jan(uary)?)
feb (feb(ruary)?)
mar (mar(ch)?)
apr (apr(il)?)
may (may)
jun (jun(e)?)
jul (jul(y)?)
aug (aug(ust)?)
sep (sep(tember)?)
oct (oct(ober)?)
nov (nov(ember)?)
dec (dec(ember)?)
MONTH ({jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec})
w ([ \t]*)
W ([ \t]+)
D ([0-9]?[0-9])
d [0-9]
%{
#ifndef lint
static char ident[] = "@(#)$Id: dtimep.lex,v 1.10 90/04/05 15:55:07 sources Exp $";
#endif
#include "tws.h"
#include "../h/strings.h"
#include <ctype.h>
#include <sys/types.h>
#ifndef SYS5
#include <sys/timeb.h>
#endif not SYS5
#ifdef SYS5
extern int daylight;
extern long timezone;
extern char *tzname[];
#endif SYS5
/*
* Patchable flag that says how to interpret NN/NN/NN dates. When
* true, we do it European style: DD/MM/YY. When false, we do it
* American style: MM/DD/YY. Of course, these are all non-RFC822
* compliant.
*/
int europeandate = 0;
/*
* Table to convert month names to numeric month. We use the
* fact that the low order 5 bits of the sum of the 2nd & 3rd
* characters of the name is a hash with no collisions for the 12
* valid month names. (The mask to 5 bits maps any combination of
* upper and lower case into the same hash value).
*/
static int month_map[] = {
0,
6, /* 1 - Jul */
3, /* 2 - Apr */
5, /* 3 - Jun */
0,
10, /* 5 - Nov */
0,
1, /* 7 - Feb */
11, /* 8 - Dec */
0,
0,
0,
0,
0,
0,
0, /*15 - Jan */
0,
0,
0,
2, /*19 - Mar */
0,
8, /*21 - Sep */
0,
9, /*23 - Oct */
0,
0,
4, /*26 - May */
0,
7 /*28 - Aug */
};
/*
* Same trick for day-of-week using the hash function
* (c1 & 7) + (c2 & 4)
*/
static int day_map[] = {
0,
0,
0,
6, /* 3 - Sat */
4, /* 4 - Thu */
0,
5, /* 6 - Fri */
0, /* 7 - Sun */
2, /* 8 - Tue */
1 /* 9 - Mon */,
0,
3 /*11 - Wed */
};
#define SETDAY { tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)];\
tw.tw_flags &= ~TW_SDAY; tw.tw_flags |= TW_SEXP;\
cp += 2; }
#define SETMONTH { tw.tw_mon = month_map[(cp[0] + cp[1]) & 0x1f]; gotdate++;\
cp += 2;\
SKIPD;}
#define CVT2 (i=(*cp++ - '0'),isdigit(*cp)? i*10 + (*cp++ - '0') : i)
#define SKIPD { while ( !isdigit(*cp++) ) ; --cp; }
#define EXPZONE { tw.tw_flags &= ~TW_SZONE; tw.tw_flags |= TW_SZEXP; }
#define ZONE(x) { tw.tw_zone=(x); EXPZONE; }
#define ZONED(x) { ZONE(x); tw.tw_flags |= TW_DST; }
#define LC(c) (isupper (c) ? tolower (c) : (c))
#ifdef DSTXXX
#ifndef BSD42
#include <time.h>
#else BSD42
#include <sys/time.h>
#endif BSD42
static zonehack (tw)
register struct tws *tw;
{
register struct tm *tm;
if (twclock (tw) == -1L)
return;
tm = localtime (&tw -> tw_clock);
if (tm -> tm_isdst) {
tw -> tw_flags |= TW_DST;
tw -> tw_zone -= 60;
}
}
#endif DSTXXX
%}
%%
%{
struct tws *dparsetime (str)
char *str;
{
register int i;
static struct tws tw;
register char *cp;
register int gotdate = 0;
#ifndef SYS5
struct timeb tb;
#endif not SYS5
start_cond = X;
/* Zero out the struct. */
bzero( (char *) &tw, sizeof tw);
/* Set default time zone. */
#ifndef SYS5
ftime( &tb );
tw.tw_zone = -tb.timezone;
#else SYS5
tzset( );
tw.tw_zone = -(timezone / 60);
#endif SYS5
while (isspace(*str))
str++;
while ( 1 )
switch (cp = str, *cp ? lex_string( &str, start_cond) : 0) {
case -1:
if (!gotdate || tw.tw_year == 0)
return 0;
/* fall through */
case 0:
return &tw;
%}
<X>{DAY}","?{w} SETDAY;
<X>"("{DAY}")"(","?) {
cp++;
SETDAY;
}
<X>{D}"/"{D}"/"(19)?[0-9][0-9]{w} {
if (europeandate) {
/* European: DD/MM/YY */
tw.tw_mday = CVT2;
cp++;
tw.tw_mon = CVT2 - 1;
} else {
/* American: MM/DD/YY */
tw.tw_mon = CVT2 - 1;
cp++;
tw.tw_mday = CVT2;
}
cp++;
for (i = 0; isdigit(*cp); )
i = i*10 + (*cp++ - '0');
tw.tw_year = i % 100;
}
<X>{D}{w}(-)?{w}{MONTH}{w}(-)?{w}(19)?{D}{w}(\,{w}|at{W})? {
tw.tw_mday = CVT2;
while ( !isalpha(*cp++) )
;
SETMONTH;
for (i = 0; isdigit(*cp); )
i = i*10 + (*cp++ - '0');
tw.tw_year = i % 100;
}
<X>{MONTH}{W}{D}","{W}(19)?{D}{w} {
cp++;
SETMONTH;
tw.tw_mday = CVT2;
SKIPD;
for (i = 0; isdigit(*cp); )
i = i*10 + (*cp++ - '0');
tw.tw_year = i % 100;
}
<X>{MONTH}{W}{D}{w} {
cp++;
SETMONTH;
tw.tw_mday = CVT2;
}
<X>{D}:{D}:{D}{W}19[6-9]{d} { /* hack: ctime w/o TZ */
tw.tw_hour = CVT2; cp++;
tw.tw_min = CVT2; cp++;
tw.tw_sec = CVT2;
while( !isdigit(*cp++) )
;
cp++;
tw.tw_year = CVT2;
}
<X>{D}:{D}:{D}{w} {
tw.tw_hour = CVT2; cp++;
tw.tw_min = CVT2; cp++;
tw.tw_sec = CVT2;
BEGIN Z;
}
<X>{D}:{D}{w} {
tw.tw_hour = CVT2; cp++;
tw.tw_min = CVT2;
BEGIN Z;
}
<X>{D}:{D}{w}am{w} {
tw.tw_hour = CVT2; cp++;
if (tw.tw_hour == 12)
tw.tw_hour = 0;
tw.tw_min = CVT2;
BEGIN Z;
}
<X>{D}:{D}{w}pm{w} {
tw.tw_hour = CVT2; cp++;
if (tw.tw_hour != 12)
tw.tw_hour += 12;
tw.tw_min = CVT2;
BEGIN Z;
}
<X>[0-2]{d}{d}{d}{d}{d}{w} {
tw.tw_hour = CVT2;
tw.tw_min = CVT2;
tw.tw_sec = CVT2;
BEGIN Z;
}
<X>19[6-9]{d}{w} {
/*
* Luckly, 4 digit times in the range
* 1960-1999 aren't legal as hour
* and minutes.
*/
cp += 2;
tw.tw_year = CVT2;
}
<X>[0-2]{d}{d}{d}{w} {
if (tw.tw_hour) {
cp += 2;
tw.tw_year = CVT2;
tw.tw_zone = 0;
} else {
tw.tw_hour = CVT2;
tw.tw_min = CVT2;
BEGIN Z;
}
}
<Z>"-"?ut ZONE(0 * 60);
<Z>"-"?gmt ZONE(0 * 60);
<Z>"-"?jst ZONE(2 * 60);
<Z>"-"?jdt ZONED(2 * 60);
<Z>"-"?est ZONE(-5 * 60);
<Z>"-"?edt ZONED(-5 * 60);
<Z>"-"?cst ZONE(-6 * 60);
<Z>"-"?cdt ZONED(-6 * 60);
<Z>"-"?mst ZONE(-7 * 60);
<Z>"-"?mdt ZONED(-7 * 60);
<Z>"-"?pst ZONE(-8 * 60);
<Z>"-"?pdt ZONED(-8 * 60);
<Z>"-"?nst ZONE(-(3 * 60 + 30));
<Z>"-"?ast ZONE(-4 * 60);
<Z>"-"?adt ZONED(-4 * 60);
<Z>"-"?yst ZONE(-9 * 60);
<Z>"-"?ydt ZONED(-9 * 60);
<Z>"-"?hst ZONE(-10 * 60);
<Z>"-"?hdt ZONED(-10 * 60);
<Z>"-"?bst ZONED(0 * 60);
<Z>[a-i] {
tw.tw_zone = 60 * (('a'-1) - LC(*cp));
EXPZONE;
}
<Z>[k-m] {
tw.tw_zone = 60 * ('a' - LC(*cp));
EXPZONE;
}
<Z>[n-y] {
tw.tw_zone = 60 * (LC(*cp) - 'm');
EXPZONE;
}
<Z>"+"[0-1]{d}{d}{d} {
cp++;
tw.tw_zone = ((cp[0] * 10 + cp[1])
-('0' * 10 + '0'))*60
+((cp[2] * 10 + cp[3])
-('0' * 10 + '0'));
EXPZONE;
#ifdef DSTXXX
zonehack (&tw);
#endif DSTXXX
cp += 4;
}
<Z>"-"[0-1]{d}{d}{d} {
cp++;
tw.tw_zone = (('0' * 10 + '0')
-(cp[0] * 10 + cp[1]))*60
+(('0' * 10 + '0')
-(cp[2] * 10 + cp[3]));
EXPZONE;
#ifdef DSTXXX
zonehack (&tw);
#endif DSTXXX
cp += 4;
}
<Z>19[6-9]{d} {
while( !isdigit(*cp++) )
;
cp++;
tw.tw_year = CVT2;
}
\n |
{W} ;
%%paul@caen.engin.umich.edu (Paul Killey) (04/23/91)
Are there cases of legal date syntaxes being turned into 01/00? I've seen that, but only with not strictly proper syntax. --paul