- new constants
- functions for month's labels
- OnCalendar=minutely case
- minor fixes

HTH

From 750176cf1cc325f7668b12856b84bf084622f754 Mon Sep 17 00:00:00 2001
From: Daniele Medri <dme...@gmail.com>
Date: Sun, 26 Oct 2014 07:16:04 +0100
Subject: [PATCH 1/7] calendar: add constant values

---
 src/shared/calendarspec.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
index 64d0dec..73f87c6 100644
--- a/src/shared/calendarspec.c
+++ b/src/shared/calendarspec.c
@@ -24,6 +24,12 @@
 
 #include "calendarspec.h"
 
+#define CENTURY_ONE 1900
+#define CENTURY_TWO 2000
+#define CENTURY_GAP 70
+#define BITS_WEEKDAYS	127
+#define BITS_MONTHS	127
+
 static void free_chain(CalendarComponent *c) {
         CalendarComponent *n;
 
@@ -107,11 +113,11 @@ static void fix_year(CalendarComponent *c) {
         while(c) {
                 CalendarComponent *n = c->next;
 
-                if (c->value >= 0 && c->value < 70)
-                        c->value += 2000;
+                if (c->value >= 0 && c->value < CENTURY_GAP)
+                        c->value += CENTURY_TWO;
 
-                if (c->value >= 70 && c->value < 100)
-                        c->value += 1900;
+                if (c->value >= CENTURY_GAP && c->value < 100)
+                        c->value += CENTURY_ONE;
 
                 c = n;
         }
@@ -157,7 +163,9 @@ _pure_ bool calendar_spec_valid(CalendarSpec *c) {
         if (c->weekdays_bits > 127)
                 return false;
 
-        if (!chain_valid(c->year, 1970, 2199))
+        if (!chain_valid(c->year,
+			(CENTURY_ONE + CENTURY_GAP),
+			(CENTURY_TWO + CENTURY_GAP)))
                 return false;
 
         if (!chain_valid(c->month, 1, 12))
@@ -847,9 +855,9 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                 mktime(&c);
                 c.tm_isdst = -1;
 
-                c.tm_year += 1900;
+                c.tm_year += CENTURY_ONE;
                 r = find_matching_component(spec->year, &c.tm_year);
-                c.tm_year -= 1900;
+                c.tm_year -= CENTURY_ONE;
 
                 if (r > 0) {
                         c.tm_mon = 0;
-- 
1.9.3

From a7b1f3434576c50a9c4b2748941c63b400874443 Mon Sep 17 00:00:00 2001
From: Daniele Medri <dme...@gmail.com>
Date: Sun, 26 Oct 2014 07:19:59 +0100
Subject: [PATCH 2/7] calendar: constant value for weekdays

---
 src/shared/calendarspec.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
index 73f87c6..67fd76a 100644
--- a/src/shared/calendarspec.c
+++ b/src/shared/calendarspec.c
@@ -126,7 +126,7 @@ static void fix_year(CalendarComponent *c) {
 int calendar_spec_normalize(CalendarSpec *c) {
         assert(c);
 
-        if (c->weekdays_bits <= 0 || c->weekdays_bits >= 127)
+        if (c->weekdays_bits <= 0 || c->weekdays_bits >= BITS_WEEKDAYS)
                 c->weekdays_bits = -1;
 
         fix_year(c->year);
@@ -160,7 +160,7 @@ _pure_ static bool chain_valid(CalendarComponent *c, int from, int to) {
 _pure_ bool calendar_spec_valid(CalendarSpec *c) {
         assert(c);
 
-        if (c->weekdays_bits > 127)
+        if (c->weekdays_bits > BITS_WEEKDAYS)
                 return false;
 
         if (!chain_valid(c->year,
@@ -202,7 +202,7 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) {
 
         assert(f);
         assert(c);
-        assert(c->weekdays_bits > 0 && c->weekdays_bits <= 127);
+        assert(c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS);
 
         for (x = 0, l = -1; x < (int) ELEMENTSOF(days); x++) {
 
@@ -267,7 +267,7 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
         if (!f)
                 return -ENOMEM;
 
-        if (c->weekdays_bits > 0 && c->weekdays_bits <= 127) {
+        if (c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS) {
                 format_weekdays(f, c);
                 fputc(' ', f);
         }
@@ -830,7 +830,7 @@ static bool matches_weekday(int weekdays_bits, const struct tm *tm) {
         struct tm t;
         int k;
 
-        if (weekdays_bits < 0 || weekdays_bits >= 127)
+        if (weekdays_bits < 0 || weekdays_bits >= BITS_WEEKDAYS)
                 return true;
 
         t = *tm;
-- 
1.9.3

From 68778e1c730d25de33d449cc045f25e3bb2fc6c1 Mon Sep 17 00:00:00 2001
From: Daniele Medri <dme...@gmail.com>
Date: Sun, 26 Oct 2014 07:39:53 +0100
Subject: [PATCH 3/7] calendar: functions and callings to handle the months's
 labels

---
 src/shared/calendarspec.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++
 src/shared/calendarspec.h |   1 +
 2 files changed, 199 insertions(+)

diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
index 67fd76a..196a330 100644
--- a/src/shared/calendarspec.c
+++ b/src/shared/calendarspec.c
@@ -129,6 +129,9 @@ int calendar_spec_normalize(CalendarSpec *c) {
         if (c->weekdays_bits <= 0 || c->weekdays_bits >= BITS_WEEKDAYS)
                 c->weekdays_bits = -1;
 
+        if (c->months_bits <= 0 || c->months_bits >= BITS_MONTHS)
+                c->months_bits = -1;
+
         fix_year(c->year);
 
         sort_chain(&c->year);
@@ -163,6 +166,9 @@ _pure_ bool calendar_spec_valid(CalendarSpec *c) {
         if (c->weekdays_bits > BITS_WEEKDAYS)
                 return false;
 
+        if (c->months_bits > BITS_MONTHS)
+                return false;
+
         if (!chain_valid(c->year,
 			(CENTURY_ONE + CENTURY_GAP),
 			(CENTURY_TWO + CENTURY_GAP)))
@@ -235,6 +241,60 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) {
         }
 }
 
+static void format_months(FILE *f, const CalendarSpec *c) {
+        static const char *const months[] = {
+                "Jan",
+                "Feb",
+                "Mar",
+                "Apr",
+                "May",
+                "Jun",
+                "Jul",
+                "Aug",
+                "Sep",
+                "Oct",
+                "Nov",
+                "Dec"
+        };
+
+        int l, x;
+        bool need_colon = false;
+
+        assert(f);
+        assert(c);
+        assert(c->months_bits > 0 && c->months_bits <= BITS_MONTHS);
+
+        for (x = 0, l = -1; x < (int) ELEMENTSOF(months); x++) {
+
+                if (c->months_bits & (1 << x)) {
+
+                        if (l < 0) {
+                                if (need_colon)
+                                        fputc(',', f);
+                                else
+                                        need_colon = true;
+
+                                fputs(months[x], f);
+                                l = x;
+                        }
+
+                } else if (l >= 0) {
+
+                        if (x > l + 1) {
+                                fputc(x > l + 2 ? '-' : ',', f);
+                                fputs(months[x-1], f);
+                        }
+
+                        l = -1;
+                }
+        }
+
+        if (l >= 0 && x > l + 1) {
+                fputc(x > l + 2 ? '-' : ',', f);
+                fputs(months[x-1], f);
+        }
+}
+
 static void format_chain(FILE *f, int space, const CalendarComponent *c) {
         assert(f);
 
@@ -272,6 +332,11 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
                 fputc(' ', f);
         }
 
+        if (c->months_bits > 0 && c->months_bits <= BITS_MONTHS) {
+                format_months(f, c);
+                fputc(' ', f);
+        }
+
         format_chain(f, 4, c->year);
         fputc('-', f);
         format_chain(f, 2, c->month);
@@ -391,6 +456,108 @@ static int parse_weekdays(const char **p, CalendarSpec *c) {
         }
 }
 
+static int parse_months(const char **p, CalendarSpec *c) {
+        static const struct {
+                const char *name;
+                const int nr;
+        } month_nr[] = {
+                { "January",	0 },
+                { "Jan",	0 },
+                { "February",	1 },
+                { "Feb",	1 },
+                { "March",	2 },
+                { "Mar",	2 },
+                { "April",	3 },
+                { "Apr",	3 },
+                { "May",	4 },
+                { "June",	5 },
+                { "Jun",	5 },
+                { "July",	6 },
+                { "Jul",	6 },
+                { "August",	7 },
+                { "Aug",	7 },
+                { "September",	8 },
+                { "Sep",	8 },
+                { "October",	9 },
+                { "Oct",	9 },
+                { "November",	10 },
+                { "Nov",	10 },
+                { "December",	11 },
+                { "Dec",	11 }
+        };
+
+        int l = -1;
+        bool first = true;
+
+        assert(p);
+        assert(*p);
+        assert(c);
+
+        for (;;) {
+                unsigned i;
+
+                if (!first && **p == ' ')
+                        return 0;
+
+                for (i = 0; i < ELEMENTSOF(month_nr); i++) {
+                        size_t skip;
+
+                        if (!startswith_no_case(*p, month_nr[i].name))
+                                continue;
+
+                        skip = strlen(month_nr[i].name);
+
+                        if ((*p)[skip] != '-' &&
+                            (*p)[skip] != ',' &&
+                            (*p)[skip] != ' ' &&
+                            (*p)[skip] != 0)
+                                return -EINVAL;
+
+                        c->months_bits |= 1 << month_nr[i].nr;
+
+                        if (l >= 0) {
+                                int j;
+
+                                if (l > month_nr[i].nr)
+                                        return -EINVAL;
+
+                                for (j = l + 1; j < month_nr[i].nr; j++)
+                                        c->months_bits |= 1 << j;
+                        }
+
+                        *p += skip;
+                        break;
+                }
+
+                /* Couldn't find this prefix, so let's assume the
+                   weekday was not specified and let's continue with
+                   the date */
+                if (i >= ELEMENTSOF(month_nr))
+                        return first ? 0 : -EINVAL;
+
+                /* We reached the end of the string */
+                if (**p == 0)
+                        return 0;
+
+                /* We reached the end of the month spec part */
+                if (**p == ' ') {
+                        *p += strspn(*p, " ");
+                        return 0;
+                }
+
+                if (**p == '-') {
+                        if (l >= 0)
+                                return -EINVAL;
+
+                        l = month_nr[i].nr;
+                } else
+                        l = -1;
+
+                *p += 1;
+                first = false;
+        }
+}
+
 static int prepend_component(const char **p, CalendarComponent **c) {
         unsigned long value, repeat = 0;
         char *e = NULL, *ee = NULL;
@@ -579,6 +746,9 @@ static int parse_time(const char **p, CalendarSpec *c) {
                 if (c->day || c->weekdays_bits > 0)
                         goto null_hour;
 
+                if (c->month || c->months_bits > 0)
+                        goto null_hour;
+
                 goto finish;
         }
 
@@ -841,6 +1011,21 @@ static bool matches_weekday(int weekdays_bits, const struct tm *tm) {
         return (weekdays_bits & (1 << k));
 }
 
+static bool matches_month(int months_bits, const struct tm *tm) {
+        struct tm t;
+        int k;
+
+        if (months_bits < 0 || months_bits >= BITS_MONTHS)
+                return true;
+
+        t = *tm;
+        if (mktime(&t) == (time_t) -1)
+                return false;
+
+        k = t.tm_mon == 0 ? 11 : t.tm_mon - 1;
+        return (months_bits & (1 << k));
+}
+
 static int find_next(const CalendarSpec *spec, struct tm *tm) {
         struct tm c;
         int r;
@@ -855,6 +1040,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                 mktime(&c);
                 c.tm_isdst = -1;
 
+		/* years */
                 c.tm_year += CENTURY_ONE;
                 r = find_matching_component(spec->year, &c.tm_year);
                 c.tm_year -= CENTURY_ONE;
@@ -867,6 +1053,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                 if (r < 0 || tm_out_of_bounds(&c))
                         return r;
 
+		/* months */
                 c.tm_mon += 1;
                 r = find_matching_component(spec->month, &c.tm_mon);
                 c.tm_mon -= 1;
@@ -883,6 +1070,14 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                         continue;
                 }
 
+                if (!matches_month(spec->months_bits, &c)) {
+		 	 c.tm_mon ++;                        
+			 c.tm_mday = 1;
+                        c.tm_hour = c.tm_min = c.tm_sec = 0;
+                        continue;
+                }
+
+		/* weekdays */
                 r = find_matching_component(spec->day, &c.tm_mday);
                 if (r > 0)
                         c.tm_hour = c.tm_min = c.tm_sec = 0;
@@ -899,6 +1094,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                         continue;
                 }
 
+		/* hours */
                 r = find_matching_component(spec->hour, &c.tm_hour);
                 if (r > 0)
                         c.tm_min = c.tm_sec = 0;
@@ -908,6 +1104,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                         continue;
                 }
 
+		/* minutes */
                 r = find_matching_component(spec->minute, &c.tm_min);
                 if (r > 0)
                         c.tm_sec = 0;
@@ -917,6 +1114,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                         continue;
                 }
 
+		/* seconds */
                 r = find_matching_component(spec->second, &c.tm_sec);
                 if (r < 0 || tm_out_of_bounds(&c)) {
                         c.tm_min ++;
diff --git a/src/shared/calendarspec.h b/src/shared/calendarspec.h
index 7baf318..462bacc 100644
--- a/src/shared/calendarspec.h
+++ b/src/shared/calendarspec.h
@@ -36,6 +36,7 @@ typedef struct CalendarComponent {
 
 typedef struct CalendarSpec {
         int weekdays_bits;
+	 int months_bits;
 
         CalendarComponent *year;
         CalendarComponent *month;
-- 
1.9.3

From d89ef0cfe5103c0b94f700e883835b16a816ce3c Mon Sep 17 00:00:00 2001
From: Daniele Medri <dme...@gmail.com>
Date: Sun, 26 Oct 2014 07:55:34 +0100
Subject: [PATCH 4/7] calendar: new case 'minutely'

---
 src/shared/calendarspec.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
index 196a330..6186301 100644
--- a/src/shared/calendarspec.c
+++ b/src/shared/calendarspec.c
@@ -833,7 +833,12 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
         if (!c)
                 return -ENOMEM;
 
-        if (strcaseeq(p, "hourly")) {
+        if (strcaseeq(p, "minutely")) {
+                r = const_chain(0, &c->second);
+                if (r < 0)
+                        goto fail;
+
+        } else if (strcaseeq(p, "hourly")) {
                 r = const_chain(0, &c->minute);
                 if (r < 0)
                         goto fail;
-- 
1.9.3

From 0180fdc1271d6674438fa8427a74b24650639751 Mon Sep 17 00:00:00 2001
From: Daniele Medri <dme...@gmail.com>
Date: Sun, 26 Oct 2014 07:57:03 +0100
Subject: [PATCH 5/7] calendar: re-ordering 'weekly'

---
 src/shared/calendarspec.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
index 6186301..fae7dfd 100644
--- a/src/shared/calendarspec.c
+++ b/src/shared/calendarspec.c
@@ -857,10 +857,10 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 if (r < 0)
                         goto fail;
 
-        } else if (strcaseeq(p, "monthly")) {
-                r = const_chain(1, &c->day);
-                if (r < 0)
-                        goto fail;
+        } else if (strcaseeq(p, "weekly")) {
+
+                c->weekdays_bits = 1;
+
                 r = const_chain(0, &c->hour);
                 if (r < 0)
                         goto fail;
@@ -871,11 +871,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 if (r < 0)
                         goto fail;
 
-        } else if (strcaseeq(p, "annually") || strcaseeq(p, "yearly")
-                   || strcaseeq(p, "anually") /* backwards compatibility */ ) {
-                r = const_chain(1, &c->month);
-                if (r < 0)
-                        goto fail;
+        } else if (strcaseeq(p, "monthly")) {
                 r = const_chain(1, &c->day);
                 if (r < 0)
                         goto fail;
@@ -889,10 +885,14 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 if (r < 0)
                         goto fail;
 
-        } else if (strcaseeq(p, "weekly")) {
-
-                c->weekdays_bits = 1;
-
+        } else if (strcaseeq(p, "annually") || strcaseeq(p, "yearly")
+                   || strcaseeq(p, "anually") /* backwards compatibility */ ) {
+                r = const_chain(1, &c->month);
+                if (r < 0)
+                        goto fail;
+                r = const_chain(1, &c->day);
+                if (r < 0)
+                        goto fail;
                 r = const_chain(0, &c->hour);
                 if (r < 0)
                         goto fail;
-- 
1.9.3

From b16c7840eeedfe656a38781fe8eba1a866601d1d Mon Sep 17 00:00:00 2001
From: Daniele Medri <dme...@gmail.com>
Date: Sun, 26 Oct 2014 07:58:48 +0100
Subject: [PATCH 6/7] calendar: no backward compatibility for erroneous label

---
 src/shared/calendarspec.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
index fae7dfd..8e6c871 100644
--- a/src/shared/calendarspec.c
+++ b/src/shared/calendarspec.c
@@ -885,8 +885,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 if (r < 0)
                         goto fail;
 
-        } else if (strcaseeq(p, "annually") || strcaseeq(p, "yearly")
-                   || strcaseeq(p, "anually") /* backwards compatibility */ ) {
+        } else if (strcaseeq(p, "annually") || strcaseeq(p, "yearly")) {
                 r = const_chain(1, &c->month);
                 if (r < 0)
                         goto fail;
-- 
1.9.3

From ec9f8add7663d22bfcc7be67b874dff69e486e93 Mon Sep 17 00:00:00 2001
From: Daniele Medri <dme...@gmail.com>
Date: Sun, 26 Oct 2014 08:00:21 +0100
Subject: [PATCH 7/7] calendar: parse months

---
 src/shared/calendarspec.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
index 8e6c871..ec84d65 100644
--- a/src/shared/calendarspec.c
+++ b/src/shared/calendarspec.c
@@ -907,6 +907,10 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 if (r < 0)
                         goto fail;
 
+                r = parse_months(&p, c);
+                if (r < 0)
+                        goto fail;
+
                 r = parse_date(&p, c);
                 if (r < 0)
                         goto fail;
-- 
1.9.3

_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to