Make find(1) standalone - commit candidate

[email protected]
Newsgroups gmane.os.freebsd.devel.audit
Message-ID <[email protected]>
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 <[email protected]> while
+**  at the University of North Carolina at Chapel Hill.  Later tweaked by
+**  a couple of people on Usenet.  Completely overhauled by Rich $alz
+**  <[email protected]> and Jim Berets <[email protected]> in August, 1990.
+**  Further revised (removed obsolete constructs and cleaned up timezone
+**  names) in August, 1991, by Rich.  Paul Eggert <[email protected]>
+**  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 [email protected]
with "unsubscribe freebsd-audit" in the body of the message
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.