summaryrefslogtreecommitdiffstats
path: root/pcp/pcplocale.c
diff options
context:
space:
mode:
authorSam Varshavchik2013-08-19 16:39:41 -0400
committerSam Varshavchik2013-08-25 14:43:51 -0400
commit9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch)
tree7a81a04cb51efb078ee350859a64be2ebc6b8813 /pcp/pcplocale.c
parenta9520698b770168d1f33d6301463bb70a19655ec (diff)
downloadcourier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2
Initial checkin
Imported from subversion report, converted to git. Updated all paths in scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'pcp/pcplocale.c')
-rw-r--r--pcp/pcplocale.c958
1 files changed, 958 insertions, 0 deletions
diff --git a/pcp/pcplocale.c b/pcp/pcplocale.c
new file mode 100644
index 0000000..f41ea73
--- /dev/null
+++ b/pcp/pcplocale.c
@@ -0,0 +1,958 @@
+/*
+** Copyright 2001 Double Precision, Inc. See COPYING for
+** distribution information.
+*/
+
+
+#include "config.h"
+#include "pcp.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "pcp.h"
+
+const char *pcp_am()
+{
+ char *am_buf=0;
+ time_t t;
+ struct tm *tmptr;
+ char tim_buf[40];
+ int n;
+
+ if (am_buf)
+ return (am_buf);
+
+ time(&t);
+ tmptr=localtime(&t);
+ tmptr->tm_hour=6;
+
+ n=strftime(tim_buf, sizeof(tim_buf), "%p", tmptr);
+ tim_buf[n]=0;
+ am_buf=strdup(tim_buf);
+ return (am_buf);
+}
+
+const char *pcp_pm()
+{
+ char *am_buf=0;
+ time_t t;
+ struct tm *tmptr;
+ char tim_buf[40];
+ int n;
+
+ if (am_buf)
+ return (am_buf);
+
+ time(&t);
+ tmptr=localtime(&t);
+ tmptr->tm_hour=18;
+
+ n=strftime(tim_buf, sizeof(tim_buf), "%p", tmptr);
+ tim_buf[n]=0;
+ am_buf=strdup(tim_buf);
+ return (am_buf);
+}
+
+static const char *wday_func(unsigned n, const char *fmt)
+{
+ static char buf[40];
+ time_t t;
+ struct tm *tmptr;
+ int dir=0;
+
+ if (n >= 7)
+ return ("");
+
+ time(&t);
+ tmptr=localtime(&t);
+
+ while (tmptr->tm_wday != n)
+ {
+ if (dir == 0)
+ dir= tmptr->tm_mday > 15 ? -1:1;
+
+ if (dir < 0)
+ {
+ tmptr->tm_mday--;
+ tmptr->tm_wday= (tmptr->tm_wday + 6) % 7;
+ }
+ else
+ {
+ tmptr->tm_mday++;
+ tmptr->tm_wday= (tmptr->tm_wday + 1) % 7;
+ }
+ }
+
+ dir=strftime(buf, sizeof(buf), fmt, tmptr);
+ buf[dir]=0;
+ return (buf);
+}
+
+const char *pcp_wdayname(unsigned n)
+{
+ return (wday_func(n, "%a"));
+}
+
+const char *pcp_wdayname_long(unsigned n)
+{
+ return (wday_func(n, "%A"));
+}
+
+int pcp_wday(const char *p)
+{
+ int i;
+
+ for (i=0; i<7; i++)
+ {
+ const char *q;
+
+ if (strcasecmp(p, pcp_wdayname(i)) == 0)
+ return (i);
+
+ q=pcp_wdayname_long(i);
+
+ if (strncasecmp(p, q, strlen(q)) == 0)
+ return (i);
+ }
+ return (-1);
+}
+
+static const char *month_func(unsigned n, const char *fmt)
+{
+ static char buf[80];
+ time_t t;
+ struct tm *tmptr;
+ int dir=0;
+
+ if (n >= 12)
+ return ("");
+
+ time(&t);
+ tmptr=localtime(&t);
+
+ tmptr->tm_mday=1;
+ tmptr->tm_mon=n;
+ tmptr->tm_hour=12;
+ tmptr->tm_min=0;
+ tmptr->tm_sec=0;
+
+ dir=strftime(buf, sizeof(buf), fmt, tmptr);
+ buf[dir]=0;
+ return (buf);
+}
+
+const char *pcp_monthname(unsigned n)
+{
+ return (month_func(n, "%b"));
+}
+
+const char *pcp_monthname_long(unsigned n)
+{
+ return (month_func(n, "%B"));
+}
+
+int pcp_month(const char *p)
+{
+ int i;
+
+ for (i=0; i<12; i++)
+ {
+ const char *q;
+
+ if (strcasecmp(p, pcp_monthname(i)) == 0)
+ return (i);
+
+ q=pcp_monthname_long(i);
+
+ if (strncasecmp(p, q, strlen(q)) == 0)
+ return (i);
+ }
+ return (-1);
+}
+
+static int is_digit(const char *p)
+{
+ while (*p)
+ {
+ if (!isdigit((int)(unsigned char)*p))
+ return (0);
+ ++p;
+ }
+ return (1);
+}
+
+static int fix_year(int year)
+{
+ time_t now=time(NULL);
+ int nn;
+
+ if (year < 100)
+ {
+ struct tm *tmptr;
+
+ tmptr=localtime(&now);
+
+ nn=tmptr->tm_year + 1900;
+
+ if (year >= (nn % 100))
+ year += (nn / 100 * 100);
+ else
+ year += (nn / 100 * 100) + 100;
+ }
+ return (year);
+}
+
+static int get_year(int mon, int day)
+{
+ time_t t=time(NULL);
+ struct tm *tmptr=localtime(&t);
+ int m=tmptr->tm_mon+1;
+
+ int year=tmptr->tm_year + 1900;
+
+ if (m > mon || (m == mon && tmptr->tm_mday > day))
+ ++year;
+
+ return (year);
+}
+
+static int scan_mdy(int sscan_rc, int *mon, int *day, int *year)
+{
+ time_t t;
+ struct tm *tmptr;
+
+ switch (sscan_rc) {
+ case 0:
+ return (-1);
+ case 1:
+ return (-1);
+ case 2:
+ time(&t);
+ tmptr=localtime(&t);
+
+ *year=tmptr->tm_year + 1900;
+
+ if (*mon < tmptr->tm_mon+1 ||
+ (*mon == tmptr->tm_mon+1 && *day < tmptr->tm_mday))
+ ++ *year;
+ break;
+ case 3:
+ if (*year < 0)
+ return (-1);
+ *year=fix_year(*year);
+ break;
+ }
+ if (*mon <= 0 || *day <= 0)
+ return (-1);
+ return (0);
+}
+
+time_t pcp_parse_datetime(int *argn,
+ int argc,
+ char **argv,
+ struct pcp_parse_datetime_info *info)
+{
+ int mon=-1, day=-1, year=0;
+ int hour=0, min=0, sec=-1;
+ time_t t;
+ struct tm *tmptr, tmsave;
+ const char *today="today";
+ const char *tomorrow="tomorrow";
+ int nn;
+ int i;
+
+ time(&t);
+
+ if (info && info->today_name)
+ today=info->today_name;
+
+ if (info && info->tomorrow_name)
+ tomorrow=info->tomorrow_name;
+
+ while (year == 0 || sec < 0 || day < 0)
+ {
+ const char *p;
+ const char *q;
+
+ if (*argn >= argc)
+ break;
+
+ p=argv[*argn];
+
+ if (strcasecmp(p, today) == 0)
+ {
+ if (year || day >= 0)
+ return (0); /* Already specified */
+
+ tmptr=localtime(&t);
+
+ mon=tmptr->tm_mon+1;
+ day=tmptr->tm_mday;
+ year=tmptr->tm_year + 1900;
+ ++ *argn;
+ continue;
+ }
+
+ if (strcasecmp(p, tomorrow) == 0)
+ {
+ time_t t2;
+
+ if (year || day >= 0)
+ return (0); /* Already specified */
+
+ tmptr=localtime(&t);
+
+ tmptr->tm_hour=12;
+ tmptr->tm_min=0;
+ tmptr->tm_sec=0;
+
+ t2=mktime(tmptr);
+ if (t2 == (time_t)-1)
+ return (0);
+
+ t2 += 24 * 60 * 60;
+
+ tmptr=localtime(&t2);
+
+ mon=tmptr->tm_mon+1;
+ day=tmptr->tm_mday;
+ year=tmptr->tm_year + 1900;
+ ++ *argn;
+ continue;
+ }
+
+ if ((i=pcp_wday(p)) >= 0)
+ {
+ time_t t2;
+
+ if (year || day >= 0)
+ return (0); /* Already specified */
+
+ t2=t;
+
+ do
+ {
+ tmptr=localtime(&t2);
+
+ tmptr->tm_hour=12;
+ tmptr->tm_min=0;
+ tmptr->tm_sec=0;
+
+ t2=mktime(tmptr);
+ if (t2 == (time_t)-1)
+ return (0);
+
+ t2 += 24 * 60 * 60;
+
+ tmptr=localtime(&t2);
+ } while (tmptr->tm_wday != i);
+
+ mon=tmptr->tm_mon+1;
+ day=tmptr->tm_mday;
+ year=tmptr->tm_year + 1900;
+ ++ *argn;
+ continue;
+ }
+
+ if ((i=pcp_month(p)) >= 0)
+ {
+ if (mon >= 0)
+ return (0);
+ mon=i+1;
+
+ if (++*argn >= argc)
+ return (0);
+ day=atoi(argv[*argn]);
+ if (day <= 0)
+ return (0);
+ ++*argn;
+ continue;
+ }
+
+ if (strchr(p, '/'))
+ {
+ if (mon > 0 || day > 0 || year > 0)
+ return (0);
+
+ if (scan_mdy(sscanf(p, "%d/%d/%d", &mon, &day, &year),
+ &mon, &day, &year))
+ return (0);
+ ++*argn;
+ continue;
+ }
+
+ if (strchr(p, '.'))
+ {
+ if (mon > 0 || day > 0 || year > 0)
+ return (0);
+
+ if (scan_mdy(sscanf(p, "%d.%d.%d", &year, &mon, &day),
+ &mon, &day, &year))
+ return (0);
+ ++*argn;
+ continue;
+ }
+
+ if (is_digit(p) && year == 0 &&
+ mon > 0 && day > 0 && sec < 0)
+ {
+ year=atoi(p);
+ year=fix_year(year);
+ ++*argn;
+ continue;
+ }
+
+ nn=atoi(p);
+
+ if (is_digit(p))
+ {
+ ++*argn;
+
+ if (*argn >= argc)
+ return (0);
+
+ p=argv[*argn];
+
+ for (i=0; i<12; i++)
+ if (strcasecmp(p, pcp_monthname(i)) == 0 ||
+ strcasecmp(p, pcp_monthname_long(i)) == 0)
+ break;
+
+ if (i < 12)
+ {
+ if (nn == 0)
+ return (0);
+
+ if (mon >= 0)
+ return (0);
+ mon=i+1;
+ day=nn;
+ ++*argn;
+ continue;
+ }
+
+ if (strcasecmp(p, pcp_am()) == 0)
+ {
+ if (hour >= 0)
+ return (0);
+ hour=nn;
+ min=0;
+ sec=0;
+ ++*argn;
+ if (hour == 12)
+ hour=0;
+
+ continue;
+ }
+
+ if (strcasecmp(p, pcp_pm()) == 0)
+ {
+ if (hour >= 0)
+ return (0);
+ hour=nn+12;
+ min=0;
+ sec=0;
+ ++*argn;
+ if (hour == 24)
+ hour=12;
+ continue;
+ }
+
+ if (hour >= 0)
+ return (0);
+ hour=nn;
+ min=0;
+ sec=0;
+ continue;
+ }
+
+ if (!isdigit((int)(unsigned char)*p))
+ break;
+
+ if (mon > 0 && day > 0 && year == 0)
+ {
+ year=get_year(mon, day);
+ }
+
+
+ switch (sscanf(p, "%d:%d:%d", &hour, &min, &sec)) {
+ case 0:
+ return (0);
+ case 1:
+ if (sec >= 0)
+ return (0);
+
+ min=sec=0;
+ break;
+ case 2:
+ if (sec >= 0)
+ return (0);
+
+ sec=0;
+ break;
+ default:
+ if (sec >= 0)
+ return (0);
+ break;
+ }
+
+ for (q=p; *q; q++)
+ {
+ if (!isdigit((int)(unsigned char)*q) && *q != ':')
+ break;
+ }
+
+ ++*argn;
+
+ if (*q == 0)
+ {
+ q= *argn < argc ? argv[*argn]:"";
+ if (strcasecmp(p, pcp_am()) == 0)
+ {
+ if (hour == 12)
+ hour=0;
+ ++*argn;
+ continue;
+ }
+ if (strcasecmp(p, pcp_pm()) == 0)
+ {
+ hour += 12;
+ if (hour == 24)
+ hour=12;
+ ++*argn;
+ continue;
+ }
+ continue;
+ }
+
+ if (strcasecmp(q, pcp_am()) == 0)
+ {
+ if (hour == 12)
+ hour=0;
+ continue;
+ }
+ if (strcasecmp(q, pcp_pm()) == 0)
+ {
+ hour += 12;
+ if (hour == 24)
+ hour=12;
+ continue;
+ }
+ return (0);
+ }
+
+ if (sec < 0)
+ {
+ hour=min=sec=0;
+ }
+
+ if (day <= 0 && mon < 0 && year <= 0)
+ {
+ tmptr=localtime(&t);
+
+ mon=tmptr->tm_mon+1;
+ day=tmptr->tm_mday;
+ year=tmptr->tm_year + 1900;
+ }
+ if (day < 0)
+ return (0);
+
+ tmptr=localtime(&t);
+ tmptr->tm_mon=mon-1;
+ tmptr->tm_mday=day;
+ tmptr->tm_year=year - 1900;
+ tmptr->tm_hour=hour;
+ tmptr->tm_min=min;
+ tmptr->tm_sec=sec;
+
+ tmsave= *tmptr;
+
+ t=mktime(tmptr);
+ if (t == (time_t)-1)
+ return (0);
+
+ /* Could be different due to altzone change, so we do it again */
+
+ tmptr=localtime(&t);
+ tmptr->tm_mon=tmsave.tm_mon;
+ tmptr->tm_mday=tmsave.tm_mday;
+ tmptr->tm_year=tmsave.tm_year;
+ tmptr->tm_hour=tmsave.tm_hour;
+ tmptr->tm_min=tmsave.tm_min;
+ tmptr->tm_sec=tmsave.tm_sec;
+ t=mktime(tmptr);
+ if (t == (time_t)-1)
+ return (0);
+ return (t);
+}
+
+static time_t add_week(time_t n, unsigned cnt)
+{
+ struct tm *tmptr=localtime(&n);
+ struct tm tmsave= *tmptr;
+
+ if (!tmptr)
+ return (0);
+
+ tmptr->tm_hour=13;
+ tmptr->tm_min=0;
+ tmptr->tm_sec=0;
+
+ n=mktime(tmptr);
+
+ if (n == (time_t)-1)
+ return (0);
+
+ n += cnt * 7 * 24 * 60 * 60;
+
+ tmptr=localtime(&n);
+
+ tmptr->tm_hour=tmsave.tm_hour;
+ tmptr->tm_min=tmsave.tm_min;
+ tmptr->tm_sec=tmsave.tm_sec;
+
+ n=mktime(tmptr);
+ if (n == (time_t)-1)
+ return (0);
+ return (n);
+}
+
+static time_t add_month(time_t n, unsigned cnt)
+{
+ time_t a, b;
+
+ struct tm *tmptr=localtime(&n);
+ int mday, d, m, y, hh, mm, ss;
+ int is_eom=0;
+ int i;
+
+ if (!tmptr)
+ return (0);
+
+ mday=d=tmptr->tm_mday;
+ m=tmptr->tm_mon+1;
+ y=tmptr->tm_year + 1900;
+ hh=tmptr->tm_hour;
+ mm=tmptr->tm_min;
+ ss=tmptr->tm_sec;
+
+ if (pcp_parse_ymd(y, m, d, &a, &b))
+ return (0);
+
+ tmptr=localtime(&b);
+ if (!tmptr)
+ return (0);
+
+ if (tmptr->tm_mday == 1) /* The original date is end of month */
+ is_eom=1;
+
+ /* Go to the next month, then backtrack */
+
+ ++cnt;
+
+ y += (cnt / 12);
+ m += cnt % 12;
+
+ if (m > 12)
+ {
+ m -= 12;
+ ++y;
+ }
+
+ tmptr->tm_mday=1;
+ tmptr->tm_mon=m-1;
+ tmptr->tm_year= y - 1900;
+ tmptr->tm_hour=13;
+ tmptr->tm_min=0;
+ tmptr->tm_sec=0;
+
+ if ((a=mktime(tmptr)) == (time_t)-1)
+ return (0);
+
+ a -= 24 * 60 * 60;
+
+ for (i=0; i<32; i++) /* Stopgap */
+ {
+ tmptr=localtime(&a);
+ if (!tmptr)
+ return (0);
+
+ if (is_eom || tmptr->tm_mday <= mday)
+ break;
+
+ tmptr->tm_hour=13;
+ tmptr->tm_min=0;
+ tmptr->tm_sec=0;
+ if ((a=mktime(tmptr)) == (time_t)-1)
+ return (0);
+
+ a -= 24 * 60 * 60;
+ }
+
+ tmptr->tm_hour=hh;
+ tmptr->tm_min=mm;
+ tmptr->tm_sec=ss;
+
+ if ((a=mktime(tmptr)) == (time_t)-1
+ || (tmptr=localtime(&a)) == NULL)
+ return (0);
+
+ tmptr->tm_hour=hh;
+ tmptr->tm_min=mm;
+ tmptr->tm_sec=ss;
+
+ if ((a=mktime(tmptr)) == (time_t)-1)
+ return (0);
+
+ return (a);
+}
+
+int pcp_parse_datetime_until(time_t start, time_t end,
+ int *argn,
+ int argc,
+ char **argv,
+
+ int recurring_type,
+
+ int (*save_date_time)(time_t, time_t, void *),
+ void *voidfunc)
+{
+ int month=0, day=0, year=0;
+ const char *p;
+ struct tm *tmptr;
+
+ time_t new_start, new_end;
+ unsigned cnt;
+
+ while (month == 0 || day == 0)
+ {
+ if (*argn >= argc)
+ return (-1);
+
+ p=argv[ (*argn)++ ];
+
+ if (month == 0 && day == 0 && year == 0)
+ {
+ if (strchr(p, '/'))
+ {
+ if (scan_mdy(sscanf(p, "%d/%d/%d",
+ &month, &day, &year),
+ &month, &day, &year))
+ return (-1);
+ continue;
+ }
+
+ if (strchr(p, '.'))
+ {
+ if (scan_mdy(sscanf(p, "%d.%d.%d",
+ &year, &month, &day),
+ &month, &day, &year))
+ return (-1);
+ continue;
+ }
+ }
+
+ if (is_digit(p))
+ {
+ if (day > 0)
+ return (-1);
+ day=atoi(p);
+ if (day <= 0)
+ return (-1);
+ continue;
+ }
+
+ if (month > 0)
+ return (-1);
+
+ month=pcp_month(p);
+
+ if (month < 0)
+ return (-1);
+ ++month;
+ }
+
+ if ( year == 0 && *argn < argc && is_digit(argv[*argn]))
+ {
+ year=atoi(argv[*argn++]);
+
+ year=fix_year(year);
+ }
+ else
+ {
+ if (year == 0)
+ year=get_year(month, day);
+ }
+
+ for (cnt=0; cnt < 100; cnt++)
+ {
+ int y, m;
+
+ switch (recurring_type) {
+ case PCP_RECURRING_MONTHLY:
+ new_start=add_month(start, cnt);
+ new_end=add_month(end, cnt);
+ break;
+ case PCP_RECURRING_ANNUALLY:
+ new_start=add_month(start, cnt*12);
+ new_end=add_month(end, cnt*12);
+ break;
+ default:
+ new_start=add_week(start, cnt);
+ new_end=add_week(end, cnt);
+ }
+
+ if (!new_start || !new_end)
+ continue;
+
+ tmptr=localtime(&new_start);
+
+ y=tmptr->tm_year + 1900;
+ m=tmptr->tm_mon + 1;
+
+ if (y > year)
+ break;
+ if (y == year)
+ {
+ if (m > month)
+ break;
+ if (m == month)
+ {
+ if (tmptr->tm_mday > day)
+ break;
+ }
+ }
+
+ y= (*save_date_time)(new_start, new_end, voidfunc);
+ if (y)
+ return (y);
+ }
+ return (0);
+}
+
+int pcp_fmttime(char *ubuf, size_t cnt, time_t t, int flags)
+{
+ struct tm *tmptr=localtime(&t);
+ char datebuf[100];
+ char timebuf[100];
+ char buf[201];
+
+ char *p;
+
+ if (!tmptr)
+ return (-1);
+
+ if (strftime(datebuf, sizeof(datebuf), "%x", tmptr) <= 0)
+ datebuf[0]=0;
+
+ if (strftime(timebuf, sizeof(timebuf), "%X", tmptr) <= 0)
+ timebuf[0]=0;
+
+ if (tmptr->tm_hour == 0 && tmptr->tm_min == 0 && tmptr->tm_sec == 0
+ && (flags & FMTTIME_TIMEDROP))
+ timebuf[0]=0;
+
+ /* Try to drop minutes from timebuf */
+
+ for (p=timebuf; *p; p++)
+ {
+ if (!isdigit((int)(unsigned char)*p) &&
+ p[1] == '0' && p[2] == '0')
+ {
+ char *q;
+
+ for (q=p+3; *q; q++)
+ if (isdigit((int)(unsigned char)*q))
+ break;
+
+ if (!*q)
+ {
+ for (q=p+3; (*p=*q) != 0; p++, q++)
+ ;
+ break;
+ }
+ }
+ }
+
+ buf[0]=0;
+ if (!flags || (flags & FMTTIME_DATE))
+ {
+ strcpy(buf, datebuf);
+ }
+
+ if (!flags || (flags & FMTTIME_TIME))
+ {
+ if (timebuf[0])
+ {
+ if (buf[0])
+ strcat(buf, " ");
+ strcat(buf, timebuf);
+ }
+ }
+
+ if (strlen(buf)+1 > cnt)
+ {
+ errno=ENOSPC;
+ return (-1);
+ }
+
+ strcpy(ubuf, buf);
+ return (0);
+}
+
+int pcp_fmttimerange(char *ubuf, size_t cnt, time_t from, time_t to)
+{
+ char date1[100];
+ char time1[100];
+ char date2[100];
+ char time2[100];
+ char fmtbuf[500];
+
+ if (pcp_fmttime(date1, sizeof(date1), from, FMTTIME_DATE) < 0)
+ date1[0]=0;
+
+ if (pcp_fmttime(time1, sizeof(time1), from,
+ FMTTIME_TIME | FMTTIME_TIMEDROP) < 0)
+ time1[0]=0;
+
+ if (pcp_fmttime(date2, sizeof(date2), to, FMTTIME_DATE) < 0)
+ date2[0]=0;
+ if (pcp_fmttime(time2, sizeof(time2), to,
+ FMTTIME_TIME | FMTTIME_TIMEDROP) < 0)
+ time2[0]=0;
+
+ if (time1[0] == 0 && time2[0] == 0)
+ {
+ sprintf(fmtbuf, strcmp(date1, date2)
+ ? "%s-%s":"%s", date1, date2);
+ }
+ else
+ {
+ if (!time1[0] && pcp_fmttime(time1, sizeof(time1), from,
+ FMTTIME_TIME) < 0)
+ time1[0]=0;
+
+ if (!time2[0] && pcp_fmttime(time2, sizeof(time2), to,
+ FMTTIME_TIME) < 0)
+ time2[0]=0;
+
+ if (strcmp(date1, date2) == 0)
+ sprintf(fmtbuf, "%s %s-%s", date1, time1, time2);
+ else
+ sprintf(fmtbuf, "%s %s-%s %s", date1, time1,
+ date2, time2);
+ }
+
+ if (strlen(fmtbuf)+1 > cnt)
+ {
+ errno=ENOSPC;
+ return (-1);
+ }
+
+ strcpy(ubuf, fmtbuf);
+ return (0);
+}