Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Mar 2002 13:35:20 +0000
From:      markm@freebsd.org
To:        audit@freebsd.org
Subject:   Make find(1) standalone - commit candidate
Message-ID:  <200203201335.g2KDZL4j025080@grimreaper.grondar.org>

next in thread | raw e-mail | index | archive | help
Index: Makefile
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/Makefile,v
retrieving revision 1.12
diff -u -d -r1.12 Makefile
--- Makefile	27 Feb 2002 17:57:00 -0000	1.12
+++ Makefile	20 Mar 2002 09:36:58 -0000
@@ -2,9 +2,7 @@
 # $FreeBSD: src/usr.bin/find/Makefile,v 1.12 2002/02/27 17:57:00 dwmalone Exp $
 
 PROG=	find
-SRCS=	find.c function.c ls.c main.c misc.c operator.c option.c getdate.y
-CLEANFILES+= getdate.c y.tab.h
-CFLAGS+= -I${.CURDIR}/../../gnu/usr.bin/cvs/lib -DHAVE_CONFIG_H
-.PATH:	${.CURDIR}/../../contrib/cvs/lib
+SRCS=	find.c function.c ls.c main.c misc.c operator.c option.c parsedate.y
+CLEANFILES+= parsedate.c y.tab.h
 
 .include <bsd.prog.mk>
Index: extern.h
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/extern.h,v
retrieving revision 1.16
diff -u -d -r1.16 extern.h
--- extern.h	20 Mar 2002 10:32:05 -0000	1.16
+++ extern.h	20 Mar 2002 10:50:45 -0000
@@ -43,6 +43,8 @@
 PLAN	*not_squish(PLAN *);
 PLAN	*or_squish(PLAN *);
 PLAN	*paren_squish(PLAN *);
+struct timeb;
+time_t	 parsedate(char *, struct timeb *);
 struct stat;
 void	 printlong(char *, char *, struct stat *);
 int	 queryuser(char **);
Index: function.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/function.c,v
retrieving revision 1.37
diff -u -d -r1.37 function.c
--- function.c	20 Mar 2002 10:32:05 -0000	1.37
+++ function.c	20 Mar 2002 10:51:23 -0000
@@ -69,7 +69,6 @@
 static long long find_parsenum(PLAN *, const char *, char *, char *);
 static long long find_parsetime(PLAN *, const char *, char *);
 static char *nextarg(OPTION *, char ***);
-time_t get_date(char *, struct timeb *);
 
 #define	COMPARE(a, b) do {						\
 	switch (plan->flags & F_ELG_MASK) {				\
@@ -999,7 +998,7 @@
 	new = palloc(option);
 	/* compare against what */
 	if (option->flags & F_TIME2_T) {
-		new->t_data = get_date(fn_or_tspec, (struct timeb *) 0);
+		new->t_data = parsedate(fn_or_tspec, (struct timeb *) 0);
 		if (new->t_data == (time_t) -1)
 			errx(1, "Can't parse date/time: %s", fn_or_tspec);
 	} else {
Index: parsedate.y
===================================================================
RCS file: parsedate.y
diff -N parsedate.y
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ parsedate.y	20 Mar 2002 12:00:46 -0000
@@ -0,0 +1,906 @@
+%{
+/*  $Id: parsedate.y,v 1.9.2.1 2000/12/26 08:39:49 kondou Exp $
+**
+**  Originally written by Steven M. Bellovin <smb@research.att.com> while
+**  at the University of North Carolina at Chapel Hill.  Later tweaked by
+**  a couple of people on Usenet.  Completely overhauled by Rich $alz
+**  <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
+**  Further revised (removed obsolete constructs and cleaned up timezone
+**  names) in August, 1991, by Rich.  Paul Eggert <eggert@twinsun.com>
+**  helped in September, 1992.
+**
+**  This grammar has six shift/reduce conflicts.
+**
+**  This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 530 *//* Empty body for statement */
+/* SUPPRESS 593 on yyerrlab *//* Label was not used */
+/* SUPPRESS 593 on yynewstate *//* Label was not used */
+/* SUPPRESS 595 on yypvt *//* Automatic variable may be used before set */
+
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <ctype.h>
+#include <fts.h>
+#include <time.h>
+
+#include "find.h"
+
+#define CTYPE(isXXXXX, c)	(isXXXXX((c)))
+#define SIZEOF(array)		(sizeof array / sizeof array[0])
+#define ENDOF(array)		(&array[SIZEOF(array)])
+
+typedef const char	*STRING;
+typedef struct timeb	TIMEINFO;
+
+#define yylhs		date_yylhs
+#define yylen		date_yylen
+#define yydefred	date_yydefred
+#define yydgoto		date_yydgoto
+#define yysindex	date_yysindex
+#define yyrindex	date_yyrindex
+#define yygindex	date_yygindex
+#define yytable		date_yytable
+#define yycheck		date_yycheck
+#define yyparse		date_parse
+#define yylex		date_lex
+#define yyerror		date_error
+
+
+static int date_lex(void);
+
+
+    /* See the LeapYears table in Convert. */
+#define EPOCH		1970
+#define END_OF_TIME	2038
+    /* Constants for general time calculations. */
+#define DST_OFFSET	1
+#define SECSPERDAY	(24L * 60L * 60L)
+    /* Readability for TABLE stuff. */
+#define HOUR(x)		(x * 60)
+
+#define LPAREN		'('
+#define RPAREN		')'
+#define IS7BIT(x)	((unsigned int)(x) < 0200)
+
+
+/*
+**  An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+    STRING	name;
+    int		type;
+    time_t	value;
+} TABLE;
+
+/*
+**  Daylight-savings mode:  on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+    DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+**  Meridian:  am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+    MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+**  Global variables.  We could get rid of most of them by using a yacc
+**  union, but this is more efficient.  (This routine predates the
+**  yacc %union construct.)
+*/
+static char	*yyInput;
+static DSTMODE	yyDSTmode;
+static int	yyHaveDate;
+static int	yyHaveRel;
+static int	yyHaveTime;
+static time_t	yyTimezone;
+static time_t	yyDay;
+static time_t	yyHour;
+static time_t	yyMinutes;
+static time_t	yyMonth;
+static time_t	yySeconds;
+static time_t	yyYear;
+static MERIDIAN	yyMeridian;
+static time_t	yyRelMonth;
+static time_t	yyRelSeconds;
+
+
+extern struct tm	*localtime();
+
+static void		date_error();
+%}
+
+%union {
+    time_t		Number;
+    enum _MERIDIAN	Meridian;
+}
+
+%token	tDAY tDAYZONE tMERIDIAN tMONTH tMONTH_UNIT tSEC_UNIT tSNUMBER
+%token	tUNUMBER tZONE
+
+%type	<Number>	tDAYZONE tMONTH tMONTH_UNIT tSEC_UNIT
+%type	<Number>	tSNUMBER tUNUMBER tZONE numzone zone
+%type	<Meridian>	tMERIDIAN o_merid
+
+%%
+
+spec	: /* NULL */
+	| spec item
+	;
+
+item	: time {
+	    yyHaveTime++;
+#if	defined(lint)
+	    /* I am compulsive about lint natterings... */
+	    if (yyHaveTime == -1) {
+		YYERROR;
+	    }
+#endif	/* defined(lint) */
+	}
+	| time zone {
+	    yyHaveTime++;
+	    yyTimezone = $2;
+	}
+	| date {
+	    yyHaveDate++;
+	}
+	| rel {
+	    yyHaveRel = 1;
+	}
+	;
+
+time	: tUNUMBER o_merid {
+	    if ($1 < 100) {
+		yyHour = $1;
+		yyMinutes = 0;
+	    }
+	    else {
+		yyHour = $1 / 100;
+		yyMinutes = $1 % 100;
+	    }
+	    yySeconds = 0;
+	    yyMeridian = $2;
+	}
+	| tUNUMBER ':' tUNUMBER o_merid {
+	    yyHour = $1;
+	    yyMinutes = $3;
+	    yySeconds = 0;
+	    yyMeridian = $4;
+	}
+	| tUNUMBER ':' tUNUMBER numzone {
+	    yyHour = $1;
+	    yyMinutes = $3;
+	    yyTimezone = $4;
+	    yyMeridian = MER24;
+	    yyDSTmode = DSToff;
+	}
+	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+	    yyHour = $1;
+	    yyMinutes = $3;
+	    yySeconds = $5;
+	    yyMeridian = $6;
+	}
+	| tUNUMBER ':' tUNUMBER ':' tUNUMBER numzone {
+	    yyHour = $1;
+	    yyMinutes = $3;
+	    yySeconds = $5;
+	    yyTimezone = $6;
+	    yyMeridian = MER24;
+	    yyDSTmode = DSToff;
+	}
+	;
+
+zone	: tZONE {
+	    $$ = $1;
+	    yyDSTmode = DSToff;
+	}
+	| tDAYZONE {
+	    $$ = $1;
+	    yyDSTmode = DSTon;
+	}
+	| tZONE numzone {
+	    /* Only allow "GMT+300" and "GMT-0800" */
+	    if ($1 != 0) {
+		YYABORT;
+	    }
+	    $$ = $2;
+	    yyDSTmode = DSToff;
+	}
+	| numzone {
+	    $$ = $1;
+	    yyDSTmode = DSToff;
+	}
+	;
+
+numzone	: tSNUMBER {
+	    int		i;
+
+	    /* Unix and GMT and numeric timezones -- a little confusing. */
+	    if ($1 < 0) {
+		/* Don't work with negative modulus. */
+		$1 = -$1;
+		if ($1 > 9999 || (i = $1 % 100) >= 60) {
+		    YYABORT;
+		}
+		$$ = ($1 / 100) * 60 + i;
+	    }
+	    else {
+		if ($1 > 9999 || (i = $1 % 100) >= 60) {
+		    YYABORT;
+		}
+		$$ = -(($1 / 100) * 60 + i);
+	    }
+	}
+	;
+
+date	: tUNUMBER '/' tUNUMBER {
+	    yyMonth = $1;
+	    yyDay = $3;
+	}
+	| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+	    if ($1 > 100) {
+		/* assume YYYY/MM/DD format, so need not to add 1900 */
+		if ($1 > 999) {
+		    yyYear = $1;
+		} else {
+		    yyYear = 1900 + $1;
+		}
+		yyMonth = $3;
+		yyDay = $5;
+	    }
+	    else {
+		/* assume MM/DD/YY* format */
+		yyMonth = $1;
+		yyDay = $3;
+		if ($5 > 999) {
+		    /* assume year is YYYY format, so need not to add 1900 */
+		    yyYear = $5;
+		} else if ($5 < 100) {
+		    /* assume year is YY format, so need to add 1900 */
+		    yyYear = $5 + (yyYear / 100 + (yyYear % 100 - $5) / 50) * 100;
+		} else {
+		    yyYear = 1900 + $5;
+		}
+	    }
+	}
+	| tMONTH tUNUMBER {
+	    yyMonth = $1;
+	    yyDay = $2;
+	}
+	| tMONTH tUNUMBER ',' tUNUMBER {
+	    yyMonth = $1;
+	    yyDay = $2;
+	    if ($4 > 999) {
+		/* assume year is YYYY format, so need not to add 1900 */
+		yyYear = $4;
+	    } else if ($4 < 100) {
+		/* assume year is YY format, so need to add 1900 */
+		yyYear = $4 + (yyYear / 100 + (yyYear % 100 - $4) / 50) * 100;
+	    } else {
+		yyYear = 1900 + $4;
+	    }
+	}
+	| tUNUMBER tMONTH {
+	    yyDay = $1;
+	    yyMonth = $2;
+	}
+	| tUNUMBER tMONTH tUNUMBER {
+	    yyDay = $1;
+	    yyMonth = $2;
+	    if ($3 > 999) {
+		/* assume year is YYYY format, so need not to add 1900 */
+		yyYear = $3;
+	    } else if ($3 < 100) {
+		/* assume year is YY format, so need to add 1900 */
+		yyYear = $3 + (yyYear / 100 + (yyYear % 100 - $3) / 50) * 100;
+	    } else {
+		yyYear = 1900 + $3;
+	    }
+	}
+	| tDAY ',' tUNUMBER tMONTH tUNUMBER {
+	    yyDay = $3;
+	    yyMonth = $4;
+	    if ($5 > 999) {
+		/* assume year is YYYY format, so need not to add 1900 */
+		yyYear = $5;
+	    } else if ($5 < 100) {
+		/* assume year is YY format, so need to add 1900 */
+		yyYear = $5 + (yyYear / 100 + (yyYear % 100 - $5) / 50) * 100;
+	    } else {
+		yyYear = 1900 + $5;
+	    }
+	}
+	;
+
+rel	: tSNUMBER tSEC_UNIT {
+	    yyRelSeconds += $1 * $2;
+	}
+	| tUNUMBER tSEC_UNIT {
+	    yyRelSeconds += $1 * $2;
+	}
+	| tSNUMBER tMONTH_UNIT {
+	    yyRelMonth += $1 * $2;
+	}
+	| tUNUMBER tMONTH_UNIT {
+	    yyRelMonth += $1 * $2;
+	}
+	;
+
+o_merid	: /* NULL */ {
+	    $$ = MER24;
+	}
+	| tMERIDIAN {
+	    $$ = $1;
+	}
+	;
+
+%%
+
+/* Month and day table. */
+static TABLE	MonthDayTable[] = {
+    { "january",	tMONTH,  1 },
+    { "february",	tMONTH,  2 },
+    { "march",		tMONTH,  3 },
+    { "april",		tMONTH,  4 },
+    { "may",		tMONTH,  5 },
+    { "june",		tMONTH,  6 },
+    { "july",		tMONTH,  7 },
+    { "august",		tMONTH,  8 },
+    { "september",	tMONTH,  9 },
+    { "october",	tMONTH, 10 },
+    { "november",	tMONTH, 11 },
+    { "december",	tMONTH, 12 },
+	/* The value of the day isn't used... */
+    { "sunday",		tDAY, 0 },
+    { "monday",		tDAY, 0 },
+    { "tuesday",	tDAY, 0 },
+    { "wednesday",	tDAY, 0 },
+    { "thursday",	tDAY, 0 },
+    { "friday",		tDAY, 0 },
+    { "saturday",	tDAY, 0 },
+};
+
+/* Time units table. */
+static TABLE	UnitsTable[] = {
+    { "year",		tMONTH_UNIT,	12 },
+    { "month",		tMONTH_UNIT,	1 },
+    { "week",		tSEC_UNIT,	7 * 24 * 60 * 60 },
+    { "day",		tSEC_UNIT,	1 * 24 * 60 * 60 },
+    { "hour",		tSEC_UNIT,	60 * 60 },
+    { "minute",		tSEC_UNIT,	60 },
+    { "min",		tSEC_UNIT,	60 },
+    { "second",		tSEC_UNIT,	1 },
+    { "sec",		tSEC_UNIT,	1 },
+};
+
+/* Timezone table. */
+static TABLE	TimezoneTable[] = {
+    { "gmt",	tZONE,     HOUR( 0) },	/* Greenwich Mean */
+    { "ut",	tZONE,     HOUR( 0) },	/* Universal */
+    { "utc",	tZONE,     HOUR( 0) },	/* Universal Coordinated */
+    { "cut",	tZONE,     HOUR( 0) },	/* Coordinated Universal */
+    { "z",	tZONE,     HOUR( 0) },	/* Greenwich Mean */
+    { "wet",	tZONE,     HOUR( 0) },	/* Western European */
+    { "bst",	tDAYZONE,  HOUR( 0) },	/* British Summer */
+    { "nst",	tZONE,     HOUR(3)+30 }, /* Newfoundland Standard */
+    { "ndt",	tDAYZONE,  HOUR(3)+30 }, /* Newfoundland Daylight */
+    { "ast",	tZONE,     HOUR( 4) },	/* Atlantic Standard */
+    { "adt",	tDAYZONE,  HOUR( 4) },	/* Atlantic Daylight */
+    { "est",	tZONE,     HOUR( 5) },	/* Eastern Standard */
+    { "edt",	tDAYZONE,  HOUR( 5) },	/* Eastern Daylight */
+    { "cst",	tZONE,     HOUR( 6) },	/* Central Standard */
+    { "cdt",	tDAYZONE,  HOUR( 6) },	/* Central Daylight */
+    { "mst",	tZONE,     HOUR( 7) },	/* Mountain Standard */
+    { "mdt",	tDAYZONE,  HOUR( 7) },	/* Mountain Daylight */
+    { "pst",	tZONE,     HOUR( 8) },	/* Pacific Standard */
+    { "pdt",	tDAYZONE,  HOUR( 8) },	/* Pacific Daylight */
+    { "yst",	tZONE,     HOUR( 9) },	/* Yukon Standard */
+    { "ydt",	tDAYZONE,  HOUR( 9) },	/* Yukon Daylight */
+    { "akst",	tZONE,     HOUR( 9) },	/* Alaska Standard */
+    { "akdt",	tDAYZONE,  HOUR( 9) },	/* Alaska Daylight */
+    { "hst",	tZONE,     HOUR(10) },	/* Hawaii Standard */
+    { "hast",	tZONE,     HOUR(10) },	/* Hawaii-Aleutian Standard */
+    { "hadt",	tDAYZONE,  HOUR(10) },	/* Hawaii-Aleutian Daylight */
+    { "ces",	tDAYZONE,  -HOUR(1) },	/* Central European Summer */
+    { "cest",	tDAYZONE,  -HOUR(1) },	/* Central European Summer */
+    { "mez",	tZONE,     -HOUR(1) },	/* Middle European */
+    { "mezt",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
+    { "cet",	tZONE,     -HOUR(1) },	/* Central European */
+    { "met",	tZONE,     -HOUR(1) },	/* Middle European */
+    { "eet",	tZONE,     -HOUR(2) },	/* Eastern Europe */
+    { "msk",	tZONE,     -HOUR(3) },	/* Moscow Winter */
+    { "msd",	tDAYZONE,  -HOUR(3) },	/* Moscow Summer */
+    { "wast",	tZONE,     -HOUR(8) },	/* West Australian Standard */
+    { "wadt",	tDAYZONE,  -HOUR(8) },	/* West Australian Daylight */
+    { "hkt",	tZONE,     -HOUR(8) },	/* Hong Kong */
+    { "cct",	tZONE,     -HOUR(8) },	/* China Coast */
+    { "jst",	tZONE,     -HOUR(9) },	/* Japan Standard */
+    { "kst",	tZONE,     -HOUR(9) },	/* Korean Standard */
+    { "kdt",	tZONE,     -HOUR(9) },	/* Korean Daylight */
+    { "cast",	tZONE,     -(HOUR(9)+30) }, /* Central Australian Standard */
+    { "cadt",	tDAYZONE,  -(HOUR(9)+30) }, /* Central Australian Daylight */
+    { "east",	tZONE,     -HOUR(10) },	/* Eastern Australian Standard */
+    { "eadt",	tDAYZONE,  -HOUR(10) },	/* Eastern Australian Daylight */
+    { "nzst",	tZONE,     -HOUR(12) },	/* New Zealand Standard */
+    { "nzdt",	tDAYZONE,  -HOUR(12) },	/* New Zealand Daylight */
+
+    /* For completeness we include the following entries. */
+#if	0
+
+    /* Duplicate names.  Either they conflict with a zone listed above
+     * (which is either more likely to be seen or just been in circulation
+     * longer), or they conflict with another zone in this section and
+     * we could not reasonably choose one over the other. */
+    { "fst",	tZONE,     HOUR( 2) },	/* Fernando De Noronha Standard */
+    { "fdt",	tDAYZONE,  HOUR( 2) },	/* Fernando De Noronha Daylight */
+    { "bst",	tZONE,     HOUR( 3) },	/* Brazil Standard */
+    { "est",	tZONE,     HOUR( 3) },	/* Eastern Standard (Brazil) */
+    { "edt",	tDAYZONE,  HOUR( 3) },	/* Eastern Daylight (Brazil) */
+    { "wst",	tZONE,     HOUR( 4) },	/* Western Standard (Brazil) */
+    { "wdt",	tDAYZONE,  HOUR( 4) },	/* Western Daylight (Brazil) */
+    { "cst",	tZONE,     HOUR( 5) },	/* Chile Standard */
+    { "cdt",	tDAYZONE,  HOUR( 5) },	/* Chile Daylight */
+    { "ast",	tZONE,     HOUR( 5) },	/* Acre Standard */
+    { "adt",	tDAYZONE,  HOUR( 5) },	/* Acre Daylight */
+    { "cst",	tZONE,     HOUR( 5) },	/* Cuba Standard */
+    { "cdt",	tDAYZONE,  HOUR( 5) },	/* Cuba Daylight */
+    { "est",	tZONE,     HOUR( 6) },	/* Easter Island Standard */
+    { "edt",	tDAYZONE,  HOUR( 6) },	/* Easter Island Daylight */
+    { "sst",	tZONE,     HOUR(11) },	/* Samoa Standard */
+    { "ist",	tZONE,     -HOUR(2) },	/* Israel Standard */
+    { "idt",	tDAYZONE,  -HOUR(2) },	/* Israel Daylight */
+    { "idt",	tDAYZONE,  -(HOUR(3)+30) }, /* Iran Daylight */
+    { "ist",	tZONE,     -(HOUR(3)+30) }, /* Iran Standard */
+    { "cst",	 tZONE,     -HOUR(8) },	/* China Standard */
+    { "cdt",	 tDAYZONE,  -HOUR(8) },	/* China Daylight */
+    { "sst",	 tZONE,     -HOUR(8) },	/* Singapore Standard */
+
+    /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
+    { "gst",	tZONE,     HOUR( 3) },	/* Greenland Standard */
+    { "wat",	tZONE,     -HOUR(1) },	/* West Africa */
+    { "at",	tZONE,     HOUR( 2) },	/* Azores */
+    { "gst",	tZONE,     -HOUR(10) },	/* Guam Standard */
+    { "nft",	tZONE,     HOUR(3)+30 }, /* Newfoundland */
+    { "idlw",	tZONE,     HOUR(12) },	/* International Date Line West */
+    { "mewt",	tZONE,     -HOUR(1) },	/* Middle European Winter */
+    { "mest",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
+    { "swt",	tZONE,     -HOUR(1) },	/* Swedish Winter */
+    { "sst",	tDAYZONE,  -HOUR(1) },	/* Swedish Summer */
+    { "fwt",	tZONE,     -HOUR(1) },	/* French Winter */
+    { "fst",	tDAYZONE,  -HOUR(1) },	/* French Summer */
+    { "bt",	tZONE,     -HOUR(3) },	/* Baghdad */
+    { "it",	tZONE,     -(HOUR(3)+30) }, /* Iran */
+    { "zp4",	tZONE,     -HOUR(4) },	/* USSR Zone 3 */
+    { "zp5",	tZONE,     -HOUR(5) },	/* USSR Zone 4 */
+    { "ist",	tZONE,     -(HOUR(5)+30) }, /* Indian Standard */
+    { "zp6",	tZONE,     -HOUR(6) },	/* USSR Zone 5 */
+    { "nst",	tZONE,     -HOUR(7) },	/* North Sumatra */
+    { "sst",	tZONE,     -HOUR(7) },	/* South Sumatra */
+    { "jt",	tZONE,     -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
+    { "nzt",	tZONE,     -HOUR(12) },	/* New Zealand */
+    { "idle",	tZONE,     -HOUR(12) },	/* International Date Line East */
+    { "cat",	tZONE,     HOUR(10) },	/* -- expired 1967 */
+    { "nt",	tZONE,     HOUR(11) },	/* -- expired 1967 */
+    { "ahst",	tZONE,     HOUR(10) },	/* -- expired 1983 */
+    { "hdt",	tDAYZONE,  HOUR(10) },	/* -- expired 1986 */
+#endif	/* 0 */
+};
+
+
+
+static int
+GetTimeInfo(TIMEINFO *Now)
+{
+    static time_t       NextHour;
+    static long         LastTzone;
+    struct tm           *tm;
+    int                 secondsUntilNextHour;
+    struct timespec     tv;
+
+    /* Get the basic time. */
+    if (gettimeofday(&tv, (struct timezone *) 0) == -1)
+        return -1;
+    Now->time = tv.tv_sec;
+    Now->millitm = tv.tv_nsec/1000;
+
+    /* Now get the timezone if the last time < HH:00:00 <= now for some HH.  */
+    if (NextHour <= Now->time) {
+        tm = localtime(&Now->time);
+        if (tm == NULL)
+            return -1;
+        secondsUntilNextHour = 60 * (60 - tm->tm_min) - tm->tm_sec;
+        LastTzone = (0 - tm->tm_gmtoff) / 60;
+        NextHour = Now->time + secondsUntilNextHour;
+    }
+    Now->timezone = LastTzone;
+    return 0;
+}
+
+
+/* ARGSUSED */
+static void
+date_error(s)
+    char	*s;
+{
+    /* NOTREACHED */
+}
+
+
+static time_t
+ToSeconds(Hours, Minutes, Seconds, Meridian)
+    time_t	Hours;
+    time_t	Minutes;
+    time_t	Seconds;
+    MERIDIAN	Meridian;
+{
+    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
+	return -1;
+    if (Meridian == MER24) {
+	if (Hours < 0 || Hours > 23)
+	    return -1;
+    }
+    else {
+	if (Hours < 1 || Hours > 12)
+	    return -1;
+	if (Hours == 12)
+	    Hours = 0;
+	if (Meridian == MERpm)
+	    Hours += 12;
+    }
+    return (Hours * 60L + Minutes) * 60L + Seconds;
+}
+
+
+static time_t
+Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
+    time_t	Month;
+    time_t	Day;
+    time_t	Year;
+    time_t	Hours;
+    time_t	Minutes;
+    time_t	Seconds;
+    MERIDIAN	Meridian;
+    DSTMODE	dst;
+{
+    static int	DaysNormal[13] = {
+	0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+    };
+    static int	DaysLeap[13] = {
+	0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+    };
+    static int	LeapYears[] = {
+	1972, 1976, 1980, 1984, 1988, 1992, 1996,
+	2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
+    };
+    int	                *yp;
+    int	                *mp;
+    time_t	        Julian;
+    int	                i;
+    time_t		tod;
+
+    /* Year should not be passed as a relative value, but absolute one.
+       so this should not happen, but just ensure it */
+    if (Year < 0)
+	Year = -Year;
+    if (Year < 100) {
+	Year += 1900;
+	if (Year < EPOCH)
+	    Year += 100;
+    }
+    for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
+	if (Year == *yp) {
+	    mp = DaysLeap;
+	    break;
+	}
+    if (Year < EPOCH || Year > END_OF_TIME
+     || Month < 1 || Month > 12
+     /* NOSTRICT *//* conversion from long may lose accuracy */
+     || Day < 1 || Day > mp[(int)Month])
+	return -1;
+
+    Julian = Day - 1 + (Year - EPOCH) * 365;
+    for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
+	if (Year <= *yp)
+	    break;
+    for (i = 1; i < Month; i++)
+	Julian += *++mp;
+    Julian *= SECSPERDAY;
+    Julian += yyTimezone * 60L;
+    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+	return -1;
+    Julian += tod;
+    tod = Julian;
+    if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
+	Julian -= DST_OFFSET * 60 * 60;
+    return Julian;
+}
+
+
+static time_t
+DSTcorrect(Start, Future)
+    time_t	Start;
+    time_t	Future;
+{
+    time_t	StartDay;
+    time_t	FutureDay;
+
+    StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+    FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+    return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60 * 60;
+}
+
+
+static time_t
+RelativeMonth(Start, RelMonth)
+    time_t	Start;
+    time_t	RelMonth;
+{
+    struct tm	*tm;
+    time_t	Month;
+    time_t	Year;
+
+    tm = localtime(&Start);
+    Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
+    Year = Month / 12;
+    Year += 1900;
+    Month = Month % 12 + 1;
+    return DSTcorrect(Start,
+	    Convert(Month, (time_t)tm->tm_mday, Year,
+		(time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+		MER24, DSTmaybe));
+}
+
+
+static int LookupWord(char *buff, int length)
+{
+    char	        *p;
+    STRING	        q;
+    TABLE	        *tp;
+    int	                c;
+
+    p = buff;
+    c = p[0];
+
+    /* See if we have an abbreviation for a month. */
+    if (length == 3 || (length == 4 && p[3] == '.'))
+	for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
+	    q = tp->name;
+	    if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
+		yylval.Number = tp->value;
+		return tp->type;
+	    }
+	}
+    else
+	for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
+	    if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
+		yylval.Number = tp->value;
+		return tp->type;
+	    }
+
+    /* Try for a timezone. */
+    for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
+	if (c == tp->name[0] && p[1] == tp->name[1]
+	 && strcmp(p, tp->name) == 0) {
+	    yylval.Number = tp->value;
+	    return tp->type;
+	}
+
+    /* Try the units table. */
+    for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
+	if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
+	    yylval.Number = tp->value;
+	    return tp->type;
+	}
+
+    /* Strip off any plural and try the units table again. */
+    if (--length > 0 && p[length] == 's') {
+	p[length] = '\0';
+	for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
+	    if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
+		p[length] = 's';
+		yylval.Number = tp->value;
+		return tp->type;
+	    }
+	p[length] = 's';
+    }
+    length++;
+
+    /* Drop out any periods. */
+    for (p = buff, q = (STRING)buff; *q; q++)
+	if (*q != '.')
+	    *p++ = *q;
+    *p = '\0';
+
+    /* Try the meridians. */
+    if (buff[1] == 'm' && buff[2] == '\0') {
+	if (buff[0] == 'a') {
+	    yylval.Meridian = MERam;
+	    return tMERIDIAN;
+	}
+	if (buff[0] == 'p') {
+	    yylval.Meridian = MERpm;
+	    return tMERIDIAN;
+	}
+    }
+
+    /* If we saw any periods, try the timezones again. */
+    if (p - buff != length) {
+	c = buff[0];
+	for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
+	    if (c == tp->name[0] && p[1] == tp->name[1]
+	    && strcmp(p, tp->name) == 0) {
+		yylval.Number = tp->value;
+		return tp->type;
+	    }
+    }
+
+    /* Unknown word -- assume GMT timezone. */
+    yylval.Number = 0;
+    return tZONE;
+}
+
+
+static int date_lex(void)
+{
+    char	        c;
+    char	        *p;
+    char		buff[20];
+    int	                sign;
+    int	                i;
+    int	                nesting;
+
+    for ( ; ; ) {
+	/* Get first character after the whitespace. */
+	for ( ; ; ) {
+	    while (CTYPE(isspace, (int)*yyInput))
+		yyInput++;
+	    c = *yyInput;
+
+	    /* Ignore RFC 822 comments, typically time zone names. */
+	    if (c != LPAREN)
+		break;
+	    for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
+		if (c == LPAREN)
+		    nesting++;
+		else if (!IS7BIT(c) || c == '\0' || c == '\r'
+		     || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
+		    /* Lexical error: bad comment. */
+		    return '?';
+	    yyInput++;
+	}
+
+	/* A number? */
+	if (CTYPE(isdigit, (int)c) || c == '-' || c == '+') {
+	    if (c == '-' || c == '+') {
+		sign = c == '-' ? -1 : 1;
+		yyInput++;
+		if (!CTYPE(isdigit, (int)*yyInput))
+		    /* Skip the plus or minus sign. */
+		    continue;
+	    }
+	    else
+		sign = 0;
+	    for (i = 0; (c = *yyInput++) != '\0' && CTYPE(isdigit, (int)c); )
+		i = 10 * i + c - '0';
+	    yyInput--;
+	    yylval.Number = sign < 0 ? -i : i;
+	    return sign ? tSNUMBER : tUNUMBER;
+	}
+
+	/* A word? */
+	if (CTYPE(isalpha, (int)c)) {
+	    for (p = buff; (c = *yyInput++) == '.' || CTYPE(isalpha, (int)c); )
+		if (p < &buff[sizeof buff - 1])
+		    *p++ = CTYPE(isupper, (int)c) ? tolower(c) : c;
+	    *p = '\0';
+	    yyInput--;
+	    return LookupWord(buff, p - buff);
+	}
+
+	return *yyInput++;
+    }
+}
+
+
+time_t parsedate(char *p, TIMEINFO *now)
+{
+    extern int		date_parse();
+    struct tm		*tm;
+    TIMEINFO		ti;
+    time_t		Start;
+
+    yyInput = p;
+    if (now == NULL) {
+	now = &ti;
+	(void)GetTimeInfo(&ti);
+    }
+
+    tm = localtime(&now->time);
+    yyYear = tm->tm_year + 1900;
+    yyMonth = tm->tm_mon + 1;
+    yyDay = tm->tm_mday;
+    yyTimezone = now->timezone;
+    yyDSTmode = DSTmaybe;
+    yyHour = 0;
+    yyMinutes = 0;
+    yySeconds = 0;
+    yyMeridian = MER24;
+    yyRelSeconds = 0;
+    yyRelMonth = 0;
+    yyHaveDate = 0;
+    yyHaveRel = 0;
+    yyHaveTime = 0;
+
+    if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
+	return -1;
+
+    if (yyHaveDate || yyHaveTime) {
+	Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+		    yyMeridian, yyDSTmode);
+	if (Start < 0)
+	    return -1;
+    }
+    else {
+	Start = now->time;
+	if (!yyHaveRel)
+	    Start -= (tm->tm_hour * 60L + tm->tm_min) * 60L + tm->tm_sec;
+    }
+
+    Start += yyRelSeconds;
+    if (yyRelMonth)
+	Start += RelativeMonth(Start, yyRelMonth);
+
+    /* Have to do *something* with a legitimate -1 so it's distinguishable
+     * from the error return value.  (Alternately could set errno on error.) */
+    return Start == -1 ? 0 : Start;
+}
+
+
+#if	defined(TEST)
+
+#if	YYDEBUG
+extern int	yydebug;
+#endif	/* YYDEBUG */
+
+/* ARGSUSED */
+int
+main(ac, av)
+    int		ac;
+    char	*av[];
+{
+    char	buff[128];
+    time_t	d;
+
+#if	YYDEBUG
+    yydebug = 1;
+#endif	/* YYDEBUG */
+
+    (void)printf("Enter date, or blank line to exit.\n\t> ");
+    for ( ; ; ) {
+	(void)printf("\t> ");
+	(void)fflush(stdout);
+	if (gets(buff) == NULL || buff[0] == '\n')
+	    break;
+#if	YYDEBUG
+	if (strcmp(buff, "yydebug") == 0) {
+	    yydebug = !yydebug;
+	    printf("yydebug = %s\n", yydebug ? "on" : "off");
+	    continue;
+	}
+#endif	/* YYDEBUG */
+	d = parsedate(buff, (TIMEINFO *)NULL);
+	if (d == -1)
+	    (void)printf("Bad format - couldn't convert.\n");
+	else
+	    (void)printf("%s", ctime(&d));
+    }
+
+    exit(0);
+    /* NOTREACHED */
+}
+#endif	/* defined(TEST) */

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200203201335.g2KDZL4j025080>