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