📄 getdate.c
字号:
/* A Bison parser, made by GNU Bison 2.3. *//* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *//* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. *//* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. *//* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. *//* Identify Bison output. */#define YYBISON 1/* Bison version. */#define YYBISON_VERSION "2.3"/* Skeleton name. */#define YYSKELETON_NAME "yacc.c"/* Pure parsers. */#define YYPURE 1/* Using locations. */#define YYLSP_NEEDED 0/* Tokens. */#ifndef YYTOKENTYPE# define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { tAGO = 258, tDST = 259, tYEAR_UNIT = 260, tMONTH_UNIT = 261, tHOUR_UNIT = 262, tMINUTE_UNIT = 263, tSEC_UNIT = 264, tDAY_UNIT = 265, tDAY = 266, tDAYZONE = 267, tLOCAL_ZONE = 268, tMERIDIAN = 269, tMONTH = 270, tORDINAL = 271, tZONE = 272, tSNUMBER = 273, tUNUMBER = 274, tSDECIMAL_NUMBER = 275, tUDECIMAL_NUMBER = 276 };#endif/* Tokens. */#define tAGO 258#define tDST 259#define tYEAR_UNIT 260#define tMONTH_UNIT 261#define tHOUR_UNIT 262#define tMINUTE_UNIT 263#define tSEC_UNIT 264#define tDAY_UNIT 265#define tDAY 266#define tDAYZONE 267#define tLOCAL_ZONE 268#define tMERIDIAN 269#define tMONTH 270#define tORDINAL 271#define tZONE 272#define tSNUMBER 273#define tUNUMBER 274#define tSDECIMAL_NUMBER 275#define tUDECIMAL_NUMBER 276/* Copy the first part of user declarations. */#line 1 "getdate.y"/* Parse a string into an internal time stamp. Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. *//* 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@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990. Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do the right thing about local DST. Also modified by Paul Eggert <eggert@cs.ucla.edu> in February 2004 to support nanosecond-resolution time stamps, and in October 2004 to support TZ strings in dates. *//* FIXME: Check for arithmetic overflow in all cases, not just some of them. */#include <config.h>#include "getdate.h"#include "intprops.h"#include "timespec.h"#include "verify.h"/* There's no need to extend the stack, so there's no need to involve alloca. */#define YYSTACK_USE_ALLOCA 0/* Tell Bison how much stack space is needed. 20 should be plenty for this grammar, which is not right recursive. Beware setting it too high, since that might cause problems on machines whose implementations have lame stack-overflow checking. */#define YYMAXDEPTH 20#define YYINITDEPTH YYMAXDEPTH/* Since the code of getdate.y is not included in the Emacs executable itself, there is no need to #define static in this file. Even if the code were included in the Emacs executable, it probably wouldn't do any harm to #undef it here; this will only cause problems if we try to write to a static variable, which I don't think this code needs to do. */#ifdef emacs# undef static#endif#include <ctype.h>#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "xalloc.h"/* ISDIGIT differs from isdigit, as follows: - Its arg may be any int or unsigned int; it need not be an unsigned char or EOF. - It's typically faster. POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to isdigit unless it's important to use the locale's definition of `digit' even when the host does not conform to POSIX. */#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)#ifndef __attribute__# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__# define __attribute__(x)# endif#endif#ifndef ATTRIBUTE_UNUSED# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))#endif/* Shift A right by B bits portably, by dividing A by 2**B and truncating towards minus infinity. A and B should be free of side effects, and B should be in the range 0 <= B <= INT_BITS - 2, where INT_BITS is the number of useful bits in an int. GNU code can assume that INT_BITS is at least 32. ISO C99 says that A >> B is implementation-defined if A < 0. Some implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift right in the usual way when A < 0, so SHR falls back on division if ordinary A >> B doesn't seem to be the usual signed shift. */#define SHR(a, b) \ (-1 >> 1 == -1 \ ? (a) >> (b) \ : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))#define EPOCH_YEAR 1970#define TM_YEAR_BASE 1900#define HOUR(x) ((x) * 60)/* Lots of this code assumes time_t and time_t-like values fit into long int. It also assumes that signed integer overflow silently wraps around, but there's no portable way to check for that at compile-time. */verify (TYPE_IS_INTEGER (time_t));verify (LONG_MIN <= TYPE_MINIMUM (time_t) && TYPE_MAXIMUM (time_t) <= LONG_MAX);/* An integer value, and the number of digits in its textual representation. */typedef struct{ bool negative; long int value; size_t digits;} textint;/* An entry in the lexical lookup table. */typedef struct{ char const *name; int type; int value;} table;/* Meridian: am, pm, or 24-hour style. */enum { MERam, MERpm, MER24 };enum { BILLION = 1000000000, LOG10_BILLION = 9 };/* Relative times. */typedef struct{ /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */ long int year; long int month; long int day; long int hour; long int minutes; long int seconds; long int ns;} relative_time;#if HAVE_COMPOUND_LITERALS# define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })#elsestatic relative_time const RELATIVE_TIME_0;#endif/* Information passed to and from the parser. */typedef struct{ /* The input string remaining to be parsed. */ const char *input; /* N, if this is the Nth Tuesday. */ long int day_ordinal; /* Day of week; Sunday is 0. */ int day_number; /* tm_isdst flag for the local zone. */ int local_isdst; /* Time zone, in minutes east of UTC. */ long int time_zone; /* Style used for time. */ int meridian; /* Gregorian year, month, day, hour, minutes, seconds, and nanoseconds. */ textint year; long int month; long int day; long int hour; long int minutes; struct timespec seconds; /* includes nanoseconds */ /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */ relative_time rel; /* Presence or counts of nonterminals of various flavors parsed so far. */ bool timespec_seen; bool rels_seen; size_t dates_seen; size_t days_seen; size_t local_zones_seen; size_t dsts_seen; size_t times_seen; size_t zones_seen; /* Table of local time zone abbrevations, terminated by a null entry. */ table local_time_zone_table[3];} parser_control;union YYSTYPE;static int yylex (union YYSTYPE *, parser_control *);static int yyerror (parser_control const *, char const *);static long int time_zone_hhmm (textint, long int);/* Extract into *PC any date and time info from a string of digits of the form e.g., YYYYMMDD, YYMMDD, HHMM, HH (and sometimes YYY, YYYY, ...). */static voiddigits_to_date_time (parser_control *pc, textint text_int){ if (pc->dates_seen && ! pc->year.digits && ! pc->rels_seen && (pc->times_seen || 2 < text_int.digits)) pc->year = text_int; else { if (4 < text_int.digits) { pc->dates_seen++; pc->day = text_int.value % 100; pc->month = (text_int.value / 100) % 100; pc->year.value = text_int.value / 10000; pc->year.digits = text_int.digits - 4; } else { pc->times_seen++; if (text_int.digits <= 2) { pc->hour = text_int.value; pc->minutes = 0; } else { pc->hour = text_int.value / 100; pc->minutes = text_int.value % 100; } pc->seconds.tv_sec = 0; pc->seconds.tv_nsec = 0; pc->meridian = MER24; } }}/* Enabling traces. */#ifndef YYDEBUG# define YYDEBUG 0#endif/* Enabling verbose error messages. */#ifdef YYERROR_VERBOSE# undef YYERROR_VERBOSE# define YYERROR_VERBOSE 1#else# define YYERROR_VERBOSE 0#endif/* Enabling the token table. */#ifndef YYTOKEN_TABLE# define YYTOKEN_TABLE 0#endif#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLAREDtypedef union YYSTYPE#line 261 "getdate.y"{ long int intval; textint textintval; struct timespec timespec; relative_time rel;}/* Line 187 of yacc.c. */#line 395 "getdate.c" YYSTYPE;# define yystype YYSTYPE /* obsolescent; will be withdrawn */# define YYSTYPE_IS_DECLARED 1# define YYSTYPE_IS_TRIVIAL 1#endif/* Copy the second part of user declarations. *//* Line 216 of yacc.c. */#line 408 "getdate.c"#ifdef short# undef short#endif#ifdef YYTYPE_UINT8typedef YYTYPE_UINT8 yytype_uint8;#elsetypedef unsigned char yytype_uint8;#endif#ifdef YYTYPE_INT8typedef YYTYPE_INT8 yytype_int8;#elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER)typedef signed char yytype_int8;#elsetypedef short int yytype_int8;#endif#ifdef YYTYPE_UINT16typedef YYTYPE_UINT16 yytype_uint16;#elsetypedef unsigned short int yytype_uint16;#endif#ifdef YYTYPE_INT16typedef YYTYPE_INT16 yytype_int16;#elsetypedef short int yytype_int16;#endif#ifndef YYSIZE_T# ifdef __SIZE_TYPE__# define YYSIZE_T __SIZE_TYPE__# elif defined size_t# define YYSIZE_T size_t# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER)# include <stddef.h> /* INFRINGES ON USER NAME SPACE */# define YYSIZE_T size_t# else# define YYSIZE_T unsigned int# endif#endif#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)#ifndef YY_# if YYENABLE_NLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -