Initial release of Maemo 5 port of gnuplot
[gnuplot] / src / strftime.c
diff --git a/src/strftime.c b/src/strftime.c
new file mode 100644 (file)
index 0000000..42ee196
--- /dev/null
@@ -0,0 +1,252 @@
+#ifndef lint
+static char *RCSid() { return RCSid("$Id: strftime.c,v 1.7 2004/07/01 17:10:08 broeker Exp $"); }
+#endif
+
+/* GNUPLOT - strftime.c */
+
+/*[
+ * Copyright 1986 - 1993, 1998, 2004   Thomas Williams, Colin Kelley
+ *
+ * Permission to use, copy, and distribute this software and its
+ * documentation for any purpose with or without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.
+ *
+ * Permission to modify the software is granted, but not the right to
+ * distribute the complete modified source code.  Modifications are to
+ * be distributed as patches to the released version.  Permission to
+ * distribute binaries produced by compiling modified sources is granted,
+ * provided you
+ *   1. distribute the corresponding source modifications from the
+ *    released version in the form of a patch file along with the binaries,
+ *   2. add special version identification to distinguish your version
+ *    in addition to the base release version number,
+ *   3. provide your name and address as the primary contact for the
+ *    support of your modified version, and
+ *   4. retain our contact information in regard to use of the base
+ *    software.
+ * Permission to distribute the released version of the source code along
+ * with corresponding source modifications in the form of a patch file is
+ * granted with same provisions 2 through 4 for binary distributions.
+ *
+ * This software is provided "as is" without express or implied warranty
+ * to the extent permitted by applicable law.
+]*/
+
+/*
+ * Implementation of strftime for systems missing this (e.g. vaxctrl)
+ *
+ * This code was written based on the NeXT strftime man-page, sample output of
+ * the function and an ANSI-C quickreference chart. This code does not use
+ * parts of any existing strftime implementation.
+ *
+ * Apparently not all format chars are implemented, but this was all I had in
+ * my documentation.
+ *
+ * (written by Alexander Lehmann)
+ */
+
+#define NOTIMEZONE
+
+#include "syscfg.h"            /* for MAX_LINE_LEN */
+#include "stdfn.h"             /* for safe_strncpy */
+
+#ifdef TEST_STRFTIME           /* test case; link with stdfn */
+#define strftime _strftime
+
+
+#include "national.h"          /* language info for the following, */
+                       /* extracted from set.c */
+
+char full_month_names[12][32] =
+{FMON01, FMON02, FMON03, FMON04, FMON05,
+ FMON06, FMON07, FMON08, FMON09, FMON10, FMON11, FMON12};
+char abbrev_month_names[12][8] =
+{AMON01, AMON02, AMON03, AMON04, AMON05,
+ AMON06, AMON07, AMON08, AMON09, AMON10, AMON11, AMON12};
+
+char full_day_names[7][32] =
+{FDAY0, FDAY1, FDAY2, FDAY3, FDAY4, FDAY5, FDAY6};
+char abbrev_day_names[7][8] =
+{ADAY0, ADAY1, ADAY2, ADAY3, ADAY4, ADAY5, ADAY6};
+
+#endif /* TEST_STRFTIME */
+
+static void fill __PROTO((char *from, char **pto, size_t *pmaxsize));
+static void number __PROTO((int num, int pad, char **pto, size_t *pmaxsize));
+
+static void
+fill(char *from, char **pto, size_t *pmaxsize)
+{
+    safe_strncpy(*pto, from, *pmaxsize);
+    if (*pmaxsize < strlen(from)) {
+       (*pto) += *pmaxsize;
+       *pmaxsize = 0;
+    } else {
+       (*pto) += strlen(from);
+       (*pmaxsize) -= strlen(from);
+    }
+}
+
+static void
+number(int num, int pad, char **pto, size_t *pmaxsize)
+{
+    char str[100];
+
+    sprintf(str, "%0*d", pad, num);
+    fill(str, pto, pmaxsize);
+}
+
+size_t
+strftime(char *s, size_t max, const char *format, const struct tm *tp)
+{
+    char *start = s;
+    size_t maxsize = max;
+
+    if (max > 0) {
+       while (*format && max > 0) {
+           if (*format != '%') {
+               *s++ = *format++;
+               max--;
+           } else {
+               format++;
+               switch (*format++) {
+               case 'a':       /* abbreviated weekday name */
+                   if (tp->tm_wday >= 0 && tp->tm_wday <= 6)
+                       fill(abbrev_day_names[tp->tm_wday], &s, &max);
+                   break;
+               case 'A':       /* full name of the weekday */
+                   if (tp->tm_wday >= 0 && tp->tm_wday <= 6)
+                       fill(full_day_names[tp->tm_wday], &s, &max);
+                   break;
+               case 'b':       /* abbreviated month name */
+                   if (tp->tm_mon >= 0 && tp->tm_mon <= 11)
+                       fill(abbrev_month_names[tp->tm_mon], &s, &max);
+                   break;
+               case 'B':       /* full name of month */
+                   if (tp->tm_mon >= 0 && tp->tm_mon <= 11)
+                       fill(full_month_names[tp->tm_mon], &s, &max);
+                   break;
+               case 'c':       /* locale's date and time reprensentation */
+                   strftime(s, max, "%a %b %X %Y", tp);
+                   max -= strlen(s);
+                   s += strlen(s);
+                   break;
+               case 'd':       /* day of the month (01-31) */
+                   number(tp->tm_mday, 2, &s, &max);
+                   break;
+               case 'H':       /* hour of the day (00-23) */
+                   number(tp->tm_hour, 2, &s, &max);
+                   break;
+               case 'I':       /* hour of the day (01-12) */
+                   number((tp->tm_hour + 11) % 12 + 1, 2, &s, &max);
+                   break;
+               case 'j':       /* day of the year (001-366) */
+                   number(tp->tm_yday + 1, 3, &s, &max);
+                   break;
+               case 'm':       /* month of the year (01-12) */
+                   number(tp->tm_mon + 1, 2, &s, &max);
+                   break;
+               case 'M':       /* minute (00-59) */
+                   number(tp->tm_min, 2, &s, &max);
+                   break;
+               case 'p':       /* locale's version of AM or PM */
+                   fill(tp->tm_hour >= 6 ? "PM" : "AM", &s, &max);
+                   break;
+               case 'S':       /* seconds (00-59) */
+                   number(tp->tm_sec, 2, &s, &max);
+                   break;
+               case 'U':       /* week number of the year (00-53) with Sunday as the first day of the week */
+                   number((tp->tm_yday - (tp->tm_yday - tp->tm_wday + 7) % 7 + 7) / 7, 1, &s, &max);
+                   break;
+               case 'w':       /* weekday (Sunday = 0 to Saturday = 6) */
+                   number(tp->tm_wday, 1, &s, &max);
+                   break;
+               case 'W':       /* week number of the year (00-53) with Monday as the first day of the week */
+                   number((tp->tm_yday - (tp->tm_yday - tp->tm_wday + 8) % 7 + 7) / 7, 2, &s, &max);
+                   break;
+               case 'x':       /* locale's date representation */
+                   strftime(s, max, "%a %b %d %Y", tp);
+                   max -= strlen(s);
+                   s += strlen(s);
+                   break;
+               case 'X':       /* locale's time representation */
+#ifndef NOTIMEZONE
+                   strftime(s, max, "%H:%M:%S %Z", tp);
+#else
+                   strftime(s, max, "%H:%M:%S", tp);
+#endif
+                   max -= strlen(s);
+                   s += strlen(s);
+                   break;
+               case 'y':       /* two-digit year representation (00-99) */
+                   number(tp->tm_year % 100, 2, &s, &max);
+                   break;
+               case 'Y':       /* four-digit year representation */
+                   number(tp->tm_year + 1900, 2, &s, &max);
+                   break;
+#ifndef NOTIMEZONE
+               case 'Z':       /* time zone name */
+                   fill(tp->tm_zone, &s, &max);
+                   break;
+#endif
+               case '%':       /* percent sign */
+               default:
+                   *s++ = *(format - 1);
+                   max--;
+                   break;
+               }
+           }
+       }
+       if (s - start < maxsize) {
+           *s++ = '\0';
+       } else {
+           *(s - 1) = '\0';
+       }
+    }
+    return s - start;
+}
+
+#ifdef TEST_STRFTIME
+
+#undef strftime
+#define test(s)                                \
+       printf("%s -> ",s );            \
+       _strftime(str, 100, s, ts);     \
+       printf("%s - ", str);           \
+       strftime(str, 100, s, ts);      \
+       printf("%s\n", str)
+
+int
+main()
+{
+    char str[100];
+    struct tm *ts;
+    time_t t;
+    int i;
+
+    t = time(NULL);
+
+    ts = localtime(&t);
+
+    test("%c");
+    test("test%%test");
+    test("%a %b %d %X %Y");
+    test("%x %X");
+    test("%A %B %U");
+    test("%I:%M %p %j %w");
+
+    t -= 245 * 24 * 60 * 60;
+
+    for (i = 0; i < 366; i++) {
+       ts = localtime(&t);
+       printf("%03d: ", i);
+       test("%a %d %m %W");
+       t += 24 * 60 * 60;
+    }
+
+    return 0;
+}
+
+#endif