]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
cal: allow to specify month by name
authorKarel Zak <kzak@redhat.com>
Tue, 31 May 2016 11:53:58 +0000 (13:53 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 31 May 2016 11:53:58 +0000 (13:53 +0200)
For example:

$ cal August 2016

Signed-off-by: Karel Zak <kzak@redhat.com>
misc-utils/cal.1
misc-utils/cal.c

index 031e0159b491c3e0fea5a850da239ae19db1048c..683e67d19d08a3bcf1fabd57713e82d1fd6637f1 100644 (file)
@@ -45,6 +45,9 @@ cal \- display a calendar
 .B cal
 displays a simple calendar.  If no arguments are specified, the current
 month is displayed.
+.sp
+The \fImonth\fR may be specified as a number (1-12) or as a month name according
+to the current locales.
 .SH OPTIONS
 .TP
 \fB\-1\fR, \fB\-\-one\fR
index 3e20530253141e78cee054e55ac4036578df9e51..c48de69f525a398522e6e4aad45ca5dc689814d3 100644 (file)
@@ -219,6 +219,7 @@ struct cal_month {
 
 /* function prototypes */
 static int leap_year(int32_t year);
+static int monthname_to_number(struct cal_control *ctl, const char *name);
 static void headers_init(struct cal_control *ctl);
 static void cal_fill_month(struct cal_month *month, const struct cal_control *ctl);
 static void cal_output_header(struct cal_month *month, const struct cal_control *ctl);
@@ -411,7 +412,10 @@ int main(int argc, char **argv)
                        errx(EXIT_FAILURE, _("illegal day value: use 1-%d"), DAYS_IN_MONTH);
                /* FALLTHROUGH */
        case 2:
-               ctl.req.month = strtos32_or_err(*argv++, _("illegal month value: use 1-12"));
+               if (isdigit(**argv))
+                       ctl.req.month = strtos32_or_err(*argv++, _("illegal month value: use 1-12"));
+               else
+                       ctl.req.month = monthname_to_number(&ctl, *argv++);
                if (ctl.req.month < 1 || MONTHS_IN_YEAR < ctl.req.month)
                        errx(EXIT_FAILURE, _("illegal month value: use 1-12"));
                /* FALLTHROUGH */
@@ -509,6 +513,30 @@ static int leap_year(int32_t year)
                return ( !(year % 4) && (year % 100) ) || !(year % 400);
 }
 
+static void init_monthnames(struct cal_control *ctl)
+{
+       size_t i;
+
+       if (ctl->full_month[0] != '\0')
+               return;         /* already initialized */
+
+       for (i = 0; i < MONTHS_IN_YEAR; i++)
+               ctl->full_month[i] = nl_langinfo(MON_1 + i);
+}
+
+static int monthname_to_number(struct cal_control *ctl, const char *name)
+{
+       size_t i;
+
+       init_monthnames(ctl);
+
+       for (i = 0; i < MONTHS_IN_YEAR; i++)
+               if (strcasecmp(ctl->full_month[i], name) == 0)
+                       return i + 1;
+
+       errx(EXIT_FAILURE, _("unknown month name: %s"), name);
+}
+
 static void headers_init(struct cal_control *ctl)
 {
        size_t i, wd;
@@ -537,8 +565,9 @@ static void headers_init(struct cal_control *ctl)
                                     space_left, ctl->day_width - 1);
        }
 
+       init_monthnames(ctl);
+
        for (i = 0; i < MONTHS_IN_YEAR; i++) {
-               ctl->full_month[i] = nl_langinfo(MON_1 + i);
                /* The +1 after year_len is space in between month and year. */
                if (ctl->week_width < strlen(ctl->full_month[i]) + year_len + 1)
                        ctl->header_hint = 1;