⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getdate.y

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 Y
📖 第 1 页 / 共 3 页
字号:
%{/* 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;	}    }}%}/* We want a reentrant parser, even if the TZ manipulation and the calls to   localtime and gmtime are not reentrant.  */%pure-parser%parse-param { parser_control *pc }%lex-param { parser_control *pc }/* This grammar has 20 shift/reduce conflicts. */%expect 20%union{  long int intval;  textint textintval;  struct timespec timespec;  relative_time rel;}%token tAGO tDST%token tYEAR_UNIT tMONTH_UNIT tHOUR_UNIT tMINUTE_UNIT tSEC_UNIT%token <intval> tDAY_UNIT%token <intval> tDAY tDAYZONE tLOCAL_ZONE tMERIDIAN%token <intval> tMONTH tORDINAL tZONE%token <textintval> tSNUMBER tUNUMBER%token <timespec> tSDECIMAL_NUMBER tUDECIMAL_NUMBER%type <intval> o_colon_minutes o_merid%type <timespec> seconds signed_seconds unsigned_seconds%type <rel> relunit relunit_snumber%%spec:    timespec  | items  ;timespec:    '@' seconds      {	pc->seconds = $2;	pc->timespec_seen = true;      }  ;items:    /* empty */  | items item  ;item:    time      { pc->times_seen++; }  | local_zone      { pc->local_zones_seen++; }  | zone      { pc->zones_seen++; }  | date      { pc->dates_seen++; }  | day      { pc->days_seen++; }  | rel      { pc->rels_seen = true; }  | number  | hybrid  ;time:    tUNUMBER tMERIDIAN      {	pc->hour = $1.value;	pc->minutes = 0;	pc->seconds.tv_sec = 0;	pc->seconds.tv_nsec = 0;	pc->meridian = $2;      }  | tUNUMBER ':' tUNUMBER o_merid      {	pc->hour = $1.value;	pc->minutes = $3.value;	pc->seconds.tv_sec = 0;	pc->seconds.tv_nsec = 0;	pc->meridian = $4;      }  | tUNUMBER ':' tUNUMBER tSNUMBER o_colon_minutes      {	pc->hour = $1.value;	pc->minutes = $3.value;	pc->seconds.tv_sec = 0;	pc->seconds.tv_nsec = 0;	pc->meridian = MER24;	pc->zones_seen++;	pc->time_zone = time_zone_hhmm ($4, $5);      }  | tUNUMBER ':' tUNUMBER ':' unsigned_seconds o_merid      {	pc->hour = $1.value;	pc->minutes = $3.value;	pc->seconds = $5;	pc->meridian = $6;      }  | tUNUMBER ':' tUNUMBER ':' unsigned_seconds tSNUMBER o_colon_minutes      {	pc->hour = $1.value;	pc->minutes = $3.value;	pc->seconds = $5;	pc->meridian = MER24;	pc->zones_seen++;	pc->time_zone = time_zone_hhmm ($6, $7);      }  ;local_zone:    tLOCAL_ZONE      {	pc->local_isdst = $1;	pc->dsts_seen += (0 < $1);      }  | tLOCAL_ZONE tDST      {	pc->local_isdst = 1;	pc->dsts_seen += (0 < $1) + 1;      }  ;zone:    tZONE      { pc->time_zone = $1; }  | tZONE relunit_snumber      { pc->time_zone = $1;	pc->rel.ns += $2.ns;	pc->rel.seconds += $2.seconds;	pc->rel.minutes += $2.minutes;	pc->rel.hour += $2.hour;	pc->rel.day += $2.day;	pc->rel.month += $2.month;	pc->rel.year += $2.year;        pc->rels_seen = true; }  | tZONE tSNUMBER o_colon_minutes      { pc->time_zone = $1 + time_zone_hhmm ($2, $3); }  | tDAYZONE      { pc->time_zone = $1 + 60; }  | tZONE tDST      { pc->time_zone = $1 + 60; }  ;day:    tDAY      {	pc->day_ordinal = 1;	pc->day_number = $1;      }  | tDAY ','      {	pc->day_ordinal = 1;	pc->day_number = $1;      }  | tORDINAL tDAY      {	pc->day_ordinal = $1;	pc->day_number = $2;      }  | tUNUMBER tDAY      {	pc->day_ordinal = $1.value;	pc->day_number = $2;      }  ;date:    tUNUMBER '/' tUNUMBER      {	pc->month = $1.value;	pc->day = $3.value;      }  | tUNUMBER '/' tUNUMBER '/' tUNUMBER      {	/* Interpret as YYYY/MM/DD if the first value has 4 or more digits,	   otherwise as MM/DD/YY.	   The goal in recognizing YYYY/MM/DD is solely to support legacy	   machine-generated dates like those in an RCS log listing.  If	   you want portability, use the ISO 8601 format.  */	if (4 <= $1.digits)	  {	    pc->year = $1;	    pc->month = $3.value;	    pc->day = $5.value;	  }	else	  {	    pc->month = $1.value;	    pc->day = $3.value;	    pc->year = $5;	  }      }  | tUNUMBER tSNUMBER tSNUMBER      {	/* ISO 8601 format.  YYYY-MM-DD.  */	pc->year = $1;	pc->month = -$2.value;	pc->day = -$3.value;      }  | tUNUMBER tMONTH tSNUMBER      {	/* e.g. 17-JUN-1992.  */	pc->day = $1.value;	pc->month = $2;	pc->year.value = -$3.value;	pc->year.digits = $3.digits;      }  | tMONTH tSNUMBER tSNUMBER      {	/* e.g. JUN-17-1992.  */	pc->month = $1;	pc->day = -$2.value;	pc->year.value = -$3.value;	pc->year.digits = $3.digits;      }  | tMONTH tUNUMBER      {	pc->month = $1;	pc->day = $2.value;      }  | tMONTH tUNUMBER ',' tUNUMBER      {	pc->month = $1;	pc->day = $2.value;	pc->year = $4;      }  | tUNUMBER tMONTH      {	pc->day = $1.value;	pc->month = $2;      }  | tUNUMBER tMONTH tUNUMBER      {	pc->day = $1.value;	pc->month = $2;	pc->year = $3;      }  ;rel:    relunit tAGO      {	pc->rel.ns -= $1.ns;	pc->rel.seconds -= $1.seconds;	pc->rel.minutes -= $1.minutes;	pc->rel.hour -= $1.hour;	pc->rel.day -= $1.day;	pc->rel.month -= $1.month;	pc->rel.year -= $1.year;      }  | relunit      {	pc->rel.ns += $1.ns;	pc->rel.seconds += $1.seconds;	pc->rel.minutes += $1.minutes;	pc->rel.hour += $1.hour;	pc->rel.day += $1.day;	pc->rel.month += $1.month;	pc->rel.year += $1.year;      }  ;relunit:    tORDINAL tYEAR_UNIT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -