mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-17 23:08:40 +02:00
Add DATETIME type.
This commit is contained in:
104
src/expr.c
104
src/expr.c
@@ -11,7 +11,7 @@
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
static char const RCSID[] = "$Id: expr.c,v 1.10 2005-09-30 03:29:32 dfs Exp $";
|
static char const RCSID[] = "$Id: expr.c,v 1.11 2007-06-28 03:04:44 dfs Exp $";
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -44,7 +44,7 @@ static int Multiply(void), Divide(void), Mod(void), Add(void),
|
|||||||
Compare(int);
|
Compare(int);
|
||||||
|
|
||||||
static int MakeValue (char *s, Value *v, Var *locals);
|
static int MakeValue (char *s, Value *v, Var *locals);
|
||||||
static int ParseLiteralDate (char **s, int *jul);
|
static int ParseLiteralDate (char **s, int *jul, int *tim);
|
||||||
|
|
||||||
/* Binary operators - all left-associative */
|
/* Binary operators - all left-associative */
|
||||||
|
|
||||||
@@ -468,10 +468,15 @@ static int MakeValue(char *s, Value *v, Var *locals)
|
|||||||
return OK;
|
return OK;
|
||||||
} else if (*s == '\'') { /* It's a literal date */
|
} else if (*s == '\'') { /* It's a literal date */
|
||||||
s++;
|
s++;
|
||||||
if ((r=ParseLiteralDate(&s, &h))) return r;
|
if ((r=ParseLiteralDate(&s, &h, &m))) return r;
|
||||||
if (*s != '\'') return E_BAD_DATE;
|
if (*s != '\'') return E_BAD_DATE;
|
||||||
v->type = DATE_TYPE;
|
if (m == NO_TIME) {
|
||||||
v->v.val = h;
|
v->type = DATE_TYPE;
|
||||||
|
v->v.val = h;
|
||||||
|
} else {
|
||||||
|
v->type = DATETIME_TYPE;
|
||||||
|
v->v.val = (h * 1440) + m;
|
||||||
|
}
|
||||||
return OK;
|
return OK;
|
||||||
} else if (isdigit(*s)) { /* It's a number - use len to hold it.*/
|
} else if (isdigit(*s)) { /* It's a number - use len to hold it.*/
|
||||||
len = 0;
|
len = 0;
|
||||||
@@ -529,13 +534,34 @@ static int MakeValue(char *s, Value *v, Var *locals)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int DoCoerce(char type, Value *v)
|
int DoCoerce(char type, Value *v)
|
||||||
{
|
{
|
||||||
int h, d, m, y, i;
|
int h, d, m, y, i, k;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
/* Do nothing if value is already the right type */
|
/* Do nothing if value is already the right type */
|
||||||
if (type == v->type) return OK;
|
if (type == v->type) return OK;
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
case DATETIME_TYPE:
|
||||||
|
switch(v->type) {
|
||||||
|
case INT_TYPE:
|
||||||
|
v->type = DATETIME_TYPE;
|
||||||
|
return OK;
|
||||||
|
case DATE_TYPE:
|
||||||
|
v->type = DATETIME_TYPE;
|
||||||
|
v->v.val *= 1440;
|
||||||
|
return OK;
|
||||||
|
case STR_TYPE:
|
||||||
|
s = v->v.str;
|
||||||
|
if (ParseLiteralDate(&s, &i, &m)) return E_CANT_COERCE;
|
||||||
|
if (*s) return E_CANT_COERCE;
|
||||||
|
v->type = DATETIME_TYPE;
|
||||||
|
free(v->v.str);
|
||||||
|
if (m == NO_TIME) m = 0;
|
||||||
|
v->v.val = i * 1440 + m;
|
||||||
|
return OK;
|
||||||
|
default:
|
||||||
|
return E_CANT_COERCE;
|
||||||
|
}
|
||||||
case STR_TYPE:
|
case STR_TYPE:
|
||||||
switch(v->type) {
|
switch(v->type) {
|
||||||
case INT_TYPE: sprintf(CoerceBuf, "%d", v->v.val); break;
|
case INT_TYPE: sprintf(CoerceBuf, "%d", v->v.val); break;
|
||||||
@@ -546,6 +572,15 @@ int DoCoerce(char type, Value *v)
|
|||||||
sprintf(CoerceBuf, "%04d%c%02d%c%02d",
|
sprintf(CoerceBuf, "%04d%c%02d%c%02d",
|
||||||
y, DATESEP, m+1, DATESEP, d);
|
y, DATESEP, m+1, DATESEP, d);
|
||||||
break;
|
break;
|
||||||
|
case DATETIME_TYPE:
|
||||||
|
i = v->v.val / 1440;
|
||||||
|
FromJulian(i, &y, &m, &d);
|
||||||
|
k = v->v.val % 1440;
|
||||||
|
h = k / 60;
|
||||||
|
i = k % 60;
|
||||||
|
sprintf(CoerceBuf, "%04d%c%02d%c%02d %02d%c%02d",
|
||||||
|
y, DATESEP, m+1, DATESEP, d, h, TIMESEP, i);
|
||||||
|
break;
|
||||||
default: return E_CANT_COERCE;
|
default: return E_CANT_COERCE;
|
||||||
}
|
}
|
||||||
v->type = STR_TYPE;
|
v->type = STR_TYPE;
|
||||||
@@ -582,6 +617,7 @@ int DoCoerce(char type, Value *v)
|
|||||||
|
|
||||||
case DATE_TYPE:
|
case DATE_TYPE:
|
||||||
case TIM_TYPE:
|
case TIM_TYPE:
|
||||||
|
case DATETIME_TYPE:
|
||||||
v->type = INT_TYPE;
|
v->type = INT_TYPE;
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
@@ -598,19 +634,25 @@ int DoCoerce(char type, Value *v)
|
|||||||
|
|
||||||
case STR_TYPE:
|
case STR_TYPE:
|
||||||
s = v->v.str;
|
s = v->v.str;
|
||||||
if (ParseLiteralDate(&s, &i)) return E_CANT_COERCE;
|
if (ParseLiteralDate(&s, &i, &m)) return E_CANT_COERCE;
|
||||||
if (*s) return E_CANT_COERCE;
|
if (*s) return E_CANT_COERCE;
|
||||||
v->type = DATE_TYPE;
|
v->type = DATE_TYPE;
|
||||||
free(v->v.str);
|
free(v->v.str);
|
||||||
v->v.val = i;
|
v->v.val = i;
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
|
case DATETIME_TYPE:
|
||||||
|
v->type = DATE_TYPE;
|
||||||
|
v->v.val /= 1440;
|
||||||
|
return OK;
|
||||||
|
|
||||||
default: return E_CANT_COERCE;
|
default: return E_CANT_COERCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TIM_TYPE:
|
case TIM_TYPE:
|
||||||
switch(v->type) {
|
switch(v->type) {
|
||||||
case INT_TYPE:
|
case INT_TYPE:
|
||||||
|
case DATETIME_TYPE:
|
||||||
v->type = TIM_TYPE;
|
v->type = TIM_TYPE;
|
||||||
v->v.val %= 1440;
|
v->v.val %= 1440;
|
||||||
if (v->v.val < 0) v->v.val += 1440;
|
if (v->v.val < 0) v->v.val += 1440;
|
||||||
@@ -680,6 +722,16 @@ static int Add(void)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If it's a datetime plus an int, add 'em */
|
||||||
|
if ((v1.type == DATETIME_TYPE && v2.type == INT_TYPE) ||
|
||||||
|
(v1.type == INT_TYPE && v2.type == DATETIME_TYPE)) {
|
||||||
|
v1.v.val += v2.v.val;
|
||||||
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
|
v1.type = DATETIME_TYPE;
|
||||||
|
PushValStack(v1);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* If it's a time plus an int, add 'em mod 1440 */
|
/* If it's a time plus an int, add 'em mod 1440 */
|
||||||
if ((v1.type == TIM_TYPE && v2.type == INT_TYPE) ||
|
if ((v1.type == TIM_TYPE && v2.type == INT_TYPE) ||
|
||||||
(v1.type == INT_TYPE && v2.type == TIM_TYPE)) {
|
(v1.type == INT_TYPE && v2.type == TIM_TYPE)) {
|
||||||
@@ -750,6 +802,14 @@ static int Subtract(void)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If it's a datetime minus an int, do subtraction, checking for underflow */
|
||||||
|
if (v1.type == DATETIME_TYPE && v2.type == INT_TYPE) {
|
||||||
|
v1.v.val -= v2.v.val;
|
||||||
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
|
PushValStack(v1);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* If it's a time minus an int, do subtraction mod 1440 */
|
/* If it's a time minus an int, do subtraction mod 1440 */
|
||||||
if (v1.type == TIM_TYPE && v2.type == INT_TYPE) {
|
if (v1.type == TIM_TYPE && v2.type == INT_TYPE) {
|
||||||
v1.v.val = (v1.v.val - v2.v.val) % 1440;
|
v1.v.val = (v1.v.val - v2.v.val) % 1440;
|
||||||
@@ -1059,6 +1119,11 @@ void PrintValue (Value *v, FILE *fp)
|
|||||||
FromJulian(v->v.val, &y, &m, &d);
|
FromJulian(v->v.val, &y, &m, &d);
|
||||||
fprintf(fp, "%04d%c%02d%c%02d", y, DATESEP, m+1, DATESEP, d);
|
fprintf(fp, "%04d%c%02d%c%02d", y, DATESEP, m+1, DATESEP, d);
|
||||||
}
|
}
|
||||||
|
else if (v->type == DATETIME_TYPE) {
|
||||||
|
FromJulian(v->v.val / 1440, &y, &m, &d);
|
||||||
|
fprintf(fp, "%04d%c%02d%c%02d %02d%c%02d", y, DATESEP, m+1, DATESEP, d,
|
||||||
|
(v->v.val % 1440) / 60, TIMESEP, (v->v.val % 1440) % 60);
|
||||||
|
}
|
||||||
else fprintf(fp, "ERR");
|
else fprintf(fp, "ERR");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1086,15 +1151,19 @@ int CopyValue(Value *dest, const Value *src)
|
|||||||
/* */
|
/* */
|
||||||
/* ParseLiteralDate */
|
/* ParseLiteralDate */
|
||||||
/* */
|
/* */
|
||||||
/* Parse a literal date. Return result in jul, update s. */
|
/* Parse a literal date or datetime. Return result in jul */
|
||||||
|
/* and tim; update s. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int ParseLiteralDate(char **s, int *jul)
|
static int ParseLiteralDate(char **s, int *jul, int *tim)
|
||||||
{
|
{
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
|
int hour, min;
|
||||||
|
|
||||||
y=0; m=0; d=0;
|
y=0; m=0; d=0;
|
||||||
|
hour=0; min=0;
|
||||||
|
|
||||||
|
*tim = NO_TIME;
|
||||||
if (!isdigit(**s)) return E_BAD_DATE;
|
if (!isdigit(**s)) return E_BAD_DATE;
|
||||||
while (isdigit(**s)) {
|
while (isdigit(**s)) {
|
||||||
y *= 10;
|
y *= 10;
|
||||||
@@ -1119,6 +1188,23 @@ static int ParseLiteralDate(char **s, int *jul)
|
|||||||
|
|
||||||
*jul = Julian(y, m, d);
|
*jul = Julian(y, m, d);
|
||||||
|
|
||||||
|
/* Do we have a time part as well? */
|
||||||
|
if (**s == ' ') {
|
||||||
|
(*s)++;
|
||||||
|
while(isdigit(**s)) {
|
||||||
|
hour *= 10;
|
||||||
|
hour += *(*s)++ - '0';
|
||||||
|
}
|
||||||
|
if (**s != ':' && **s != '.' && **s != TIMESEP) return E_BAD_TIME;
|
||||||
|
(*s)++;
|
||||||
|
while(isdigit(**s)) {
|
||||||
|
min *= 10;
|
||||||
|
min += *(*s)++ - '0';
|
||||||
|
}
|
||||||
|
if (hour > 23 || min > 59) return E_BAD_TIME;
|
||||||
|
*tim = hour * 60 + min;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
src/expr.h
13
src/expr.h
@@ -10,14 +10,15 @@
|
|||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
/* $Id: expr.h,v 1.4 2000-02-18 03:45:53 dfs Exp $ */
|
/* $Id: expr.h,v 1.5 2007-06-28 03:04:44 dfs Exp $ */
|
||||||
|
|
||||||
/* Define the types of values */
|
/* Define the types of values */
|
||||||
#define ERR_TYPE 0
|
#define ERR_TYPE 0
|
||||||
#define INT_TYPE 1
|
#define INT_TYPE 1
|
||||||
#define TIM_TYPE 2
|
#define TIM_TYPE 2
|
||||||
#define DATE_TYPE 3
|
#define DATE_TYPE 3
|
||||||
#define STR_TYPE 4
|
#define STR_TYPE 4
|
||||||
|
#define DATETIME_TYPE 5
|
||||||
|
|
||||||
/* Define stuff for parsing expressions */
|
/* Define stuff for parsing expressions */
|
||||||
#define BEG_OF_EXPR '['
|
#define BEG_OF_EXPR '['
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
static char const RCSID[] = "$Id: funcs.c,v 1.10 2005-09-30 03:29:32 dfs Exp $";
|
static char const RCSID[] = "$Id: funcs.c,v 1.11 2007-06-28 03:04:44 dfs Exp $";
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -415,6 +415,7 @@ static int FCoerce(void)
|
|||||||
else if (! StrCmpi(s, "date")) return DoCoerce(DATE_TYPE, &RetVal);
|
else if (! StrCmpi(s, "date")) return DoCoerce(DATE_TYPE, &RetVal);
|
||||||
else if (! StrCmpi(s, "time")) return DoCoerce(TIM_TYPE, &RetVal);
|
else if (! StrCmpi(s, "time")) return DoCoerce(TIM_TYPE, &RetVal);
|
||||||
else if (! StrCmpi(s, "string")) return DoCoerce(STR_TYPE, &RetVal);
|
else if (! StrCmpi(s, "string")) return DoCoerce(STR_TYPE, &RetVal);
|
||||||
|
else if (! StrCmpi(s, "datetime")) return DoCoerce(DATETIME_TYPE, &RetVal);
|
||||||
else return E_CANT_COERCE;
|
else return E_CANT_COERCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user