From 0f4ebd49c8b6997ac46d89dd2c90cbc1011da54c Mon Sep 17 00:00:00 2001 From: June McEnroe Date: Mon, 15 Aug 2022 20:29:44 -0400 Subject: Add named dates to when --- bin/man1/when.1 | 7 ++++++- bin/when.y | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 4 deletions(-) (limited to 'bin') diff --git a/bin/man1/when.1 b/bin/man1/when.1 index 0b473573..f955daf4 100644 --- a/bin/man1/when.1 +++ b/bin/man1/when.1 @@ -1,4 +1,4 @@ -.Dd July 24, 2019 +.Dd August 15, 2022 .Dt WHEN 1 .Os . @@ -24,6 +24,11 @@ The grammar is as follows: .Bl -tag -width Ds .It Sy \&. Today's date. +The empty expression is equivalent. +. +.It Ar name Op Sy = Ar date +A named date. +Names are alphanumeric including underscores. . .It Ar month Ar date Op Ar year A full date, diff --git a/bin/when.y b/bin/when.y index 64859da7..095493d7 100644 --- a/bin/when.y +++ b/bin/when.y @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 June McEnroe +/* Copyright (C) 2019, 2022 June McEnroe * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -130,6 +130,37 @@ static struct tm dateDiff(struct tm a, struct tm b) { return diff; } +static struct { + size_t cap, len; + struct tm *ptr; +} dates; + +static struct tm getDate(const char *name) { + for (size_t i = 0; i < dates.len; ++i) { + if (!strcmp(dates.ptr[i].tm_zone, name)) return dates.ptr[i]; + } + return (struct tm) {0}; +} + +static void setDate(const char *name, struct tm date) { + for (size_t i = 0; i < dates.len; ++i) { + if (strcmp(dates.ptr[i].tm_zone, name)) continue; + char *tm_zone = dates.ptr[i].tm_zone; + dates.ptr[i] = date; + dates.ptr[i].tm_zone = tm_zone; + return; + } + if (dates.len == dates.cap) { + dates.cap = (dates.cap ? dates.cap * 2 : 8); + dates.ptr = realloc(dates.ptr, sizeof(*dates.ptr) * dates.cap); + if (!dates.ptr) err(EX_OSERR, "realloc"); + } + dates.ptr[dates.len] = date; + dates.ptr[dates.len].tm_zone = strdup(name); + if (!dates.ptr[dates.len].tm_zone) err(EX_OSERR, "strdup"); + dates.len++; +} + static void printDate(struct tm date) { printf( "%s %s %d %d\n", @@ -161,9 +192,9 @@ static void printScalar(struct tm scalar) { %} -%token Number Month Day +%token Name Number Month Day %left '+' '-' -%right '<' '>' +%right '=' '<' '>' %% @@ -174,6 +205,8 @@ expr: date: dateLit + | Name { $$ = getDate($1.tm_zone); free($1.tm_zone); } + | Name '=' date { setDate($1.tm_zone, $3); free($1.tm_zone); $$ = $3; } | '(' date ')' { $$ = $2; } | '<' date { $$ = dateSub($2, Week); } | '>' date { $$ = dateAdd($2, Week); } @@ -237,6 +270,15 @@ static int yylex(void) { return Month; } + size_t len; + for (len = 0; isalnum(input[len]) || input[len] == '_'; ++len); + if (len && (len != 1 || !strchr("dwmy", *input))) { + yylval.tm_zone = strndup(input, len); + if (!yylval.tm_zone) err(EX_OSERR, "strndup"); + input += len; + return Name; + } + return *input++; } -- cgit 1.4.1