summaryrefslogtreecommitdiff
path: root/lib/posixtm.y
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1992-11-01 05:44:29 +0000
committerJim Meyering <jim@meyering.net>1992-11-01 05:44:29 +0000
commitccbd1d7dc5189f4637468a8136f672e60ee0e531 (patch)
treef07938daa9443c4a699efa77d88eb9eb2c2e663b /lib/posixtm.y
parent144b82c6c22abaa2a3247dc33b286662a7aa90d9 (diff)
downloadcoreutils-ccbd1d7dc5189f4637468a8136f672e60ee0e531.tar.xz
Initial revision
Diffstat (limited to 'lib/posixtm.y')
-rw-r--r--lib/posixtm.y173
1 files changed, 173 insertions, 0 deletions
diff --git a/lib/posixtm.y b/lib/posixtm.y
new file mode 100644
index 000000000..bb5b40e75
--- /dev/null
+++ b/lib/posixtm.y
@@ -0,0 +1,173 @@
+/* Parse dates for touch.
+ Copyright (C) 1989, 1990, 1991 Free Software Foundation Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Jim Kingdon and David MacKenzie. */
+%{
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#ifdef sparc
+#include <alloca.h>
+#else
+#ifdef _AIX
+ #pragma alloca
+#else
+char *alloca ();
+#endif
+#endif
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <time.h>
+
+#define YYDEBUG 1
+
+/* Lexical analyzer's current scan position in the input string. */
+static char *curpos;
+
+/* The return value. */
+static struct tm t;
+
+time_t mktime ();
+
+#define yyparse posixtime_yyparse
+static int yylex ();
+static int yyerror ();
+%}
+
+%token DIGIT
+
+%%
+date :
+ digitpair /* month */
+ digitpair /* day */
+ digitpair /* hours */
+ digitpair /* minutes */
+ year
+ seconds {
+ if ($1 >= 1 && $1 <= 12)
+ t.tm_mon = $1 - 1;
+ else {
+ YYABORT;
+ }
+ if ($2 >= 1 && $2 <= 31)
+ t.tm_mday = $2;
+ else {
+ YYABORT;
+ }
+ if ($3 >= 0 && $3 <= 23)
+ t.tm_hour = $3;
+ else {
+ YYABORT;
+ }
+ if ($4 >= 0 && $4 <= 59)
+ t.tm_min = $4;
+ else {
+ YYABORT;
+ }
+ }
+
+year : digitpair {
+ t.tm_year = $1;
+ /* Deduce the century based on the year.
+ See POSIX.2 section 4.63.3. */
+ if ($1 <= 68)
+ t.tm_year += 100;
+ }
+ | digitpair digitpair {
+ t.tm_year = $1 * 100 + $2;
+ if (t.tm_year < 1900) {
+ YYABORT;
+ } else
+ t.tm_year -= 1900;
+ }
+ | /* empty */ {
+ time_t now;
+ struct tm *tmp;
+
+ /* Use current year. */
+ time (&now);
+ tmp = localtime (&now);
+ t.tm_year = tmp->tm_year;
+ }
+ ;
+
+seconds : /* empty */ {
+ t.tm_sec = 0;
+ }
+ | '.' digitpair {
+ if ($2 >= 0 && $2 <= 61)
+ t.tm_sec = $2;
+ else {
+ YYABORT;
+ }
+ }
+ ;
+
+digitpair : DIGIT DIGIT {
+ $$ = $1 * 10 + $2;
+ }
+ ;
+%%
+static int
+yylex ()
+{
+ char ch = *curpos++;
+
+ if (ch >= '0' && ch <= '9')
+ {
+ yylval = ch - '0';
+ return DIGIT;
+ }
+ else if (ch == '.' || ch == 0)
+ return ch;
+ else
+ return '?'; /* Cause an error. */
+}
+
+static int
+yyerror ()
+{
+ return 0;
+}
+
+/* Parse a POSIX-style date and return it, or (time_t)-1 for an error. */
+
+time_t
+posixtime (s)
+ char *s;
+{
+ curpos = s;
+ /* Let mktime decide whether it is daylight savings time. */
+ t.tm_isdst = -1;
+ if (yyparse ())
+ return (time_t)-1;
+ else
+ return mktime (&t);
+}
+
+/* Parse a POSIX-style date and return it, or NULL for an error. */
+
+struct tm *
+posixtm (s)
+ char *s;
+{
+ if (posixtime (s) == -1)
+ return NULL;
+ return &t;
+}