From e63b2f75607905fedf00cfd9fe644b26af715ffd Mon Sep 17 00:00:00 2001 From: Leo C Date: Mon, 1 Dec 2014 23:25:55 +0100 Subject: switch to avr-libc 1.8.1 time library --- time/strftime.c | 322 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 time/strftime.c (limited to 'time/strftime.c') diff --git a/time/strftime.c b/time/strftime.c new file mode 100644 index 0000000..4dcfd30 --- /dev/null +++ b/time/strftime.c @@ -0,0 +1,322 @@ +/* + * (c)2012 Michael Duane Rice All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials + * provided with the distribution. Neither the name of the copyright holders + * nor the names of contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id: strftime.c 2391 2013-05-03 20:53:06Z swfltek $ */ + +/* + Standard strftime(). This is a memory hungry monster. +*/ + +#include +#include +#include + +extern long __utc_offset; + +#ifdef __MEMX + +const __memx char strfwkdays[] = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday "; +const __memx char strfmonths[] = "January February March April May June July August September October November December "; + +#else + +const char strfwkdays[] = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday "; +const char strfmonths[] = "January February March April May June July August September October November December "; + +#endif + +#ifdef __MEMX + +unsigned char +pgm_copystring(const char __memx * p, unsigned char i, char *b, unsigned char l) +{ + +#else + +unsigned char +pgm_copystring(const char *p, unsigned char i, char *b, unsigned char l) +{ + +#endif + + unsigned char ret, c; + + ret = 0; + while (i) { + c = *p++; + if (c == ' ') + i--; + } + + c = *p++; + while (c != ' ' && l--) { + *b++ = c; + ret++; + c = *p++; + } + *b = 0; + return ret; +} + +size_t +strftime(char *buffer, size_t limit, const char *pattern, const struct tm * timeptr) +{ + unsigned int count, length; + int d, w; + char c; + char _store[26]; + struct week_date wd; + + count = length = 0; + while (count < limit) { + c = *pattern++; + if (c == '%') { + c = *pattern++; + if (c == 'E' || c == 'O') + c = *pattern++; + switch (c) { + case ('%'): + _store[0] = c; + length = 1; + break; + + case ('a'): + length = pgm_copystring(strfwkdays, timeptr->tm_wday, _store, 3); + break; + + case ('A'): + length = pgm_copystring(strfwkdays, timeptr->tm_wday, _store, 255); + break; + + case ('b'): + case ('h'): + length = pgm_copystring(strfmonths, timeptr->tm_mon, _store, 3); + break; + + case ('B'): + length = pgm_copystring(strfmonths, timeptr->tm_mon, _store, 255); + break; + + case ('c'): + asctime_r(timeptr, _store); + length = 0; + while (_store[length]) + length++; + break; + + case ('C'): + d = timeptr->tm_year + 1900; + d /= 100; + length = sprintf(_store, "%.2d", d); + break; + + case ('d'): + length = sprintf(_store, "%.2u", timeptr->tm_mday); + break; + + case ('D'): + length = sprintf(_store, "%.2u/%.2u/%.2u", \ + timeptr->tm_mon + 1, \ + timeptr->tm_mday, \ + timeptr->tm_year % 100 \ + ); + break; + + case ('e'): + length = sprintf(_store, "%2d", timeptr->tm_mday); + break; + + case ('F'): + length = sprintf(_store, "%d-%.2d-%.2d", \ + timeptr->tm_year + 1900, \ + timeptr->tm_mon + 1, \ + timeptr->tm_mday \ + ); + break; + + case ('g'): + case ('G'): + iso_week_date_r(timeptr->tm_year + 1900, timeptr->tm_yday, &wd); + if (c == 'g') { + length = sprintf(_store, "%.2d", wd.year % 100); + } else { + length = sprintf(_store, "%.4d", wd.year); + } + + break; + + case ('H'): + length = sprintf(_store, "%.2u", timeptr->tm_hour); + break; + + case ('I'): + d = timeptr->tm_hour % 12; + if (d == 0) + d = 12; + length = sprintf(_store, "%.2u", d); + break; + + case ('j'): + length = sprintf(_store, "%.3u", timeptr->tm_yday + 1); + break; + + case ('m'): + length = sprintf(_store, "%.2u", timeptr->tm_mon + 1); + break; + + case ('M'): + length = sprintf(_store, "%.2u", timeptr->tm_min); + break; + + case ('n'): + _store[0] = 10; + length = 1; + break; + + case ('p'): + length = 2; + _store[0] = 'A'; + if (timeptr->tm_hour > 11) + _store[0] = 'P'; + _store[1] = 'M'; + _store[2] = 0; + break; + + case ('r'): + d = timeptr->tm_hour % 12; + if (d == 0) + d = 12; + length = sprintf(_store, "%2d:%.2d:%.2d AM", \ + d, \ + timeptr->tm_min, \ + timeptr->tm_sec \ + ); + if (timeptr->tm_hour > 11) + _store[10] = 'P'; + break; + + case ('R'): + length = sprintf(_store, "%.2d:%.2d", timeptr->tm_hour, timeptr->tm_min); + break; + + case ('S'): + length = sprintf(_store, "%.2u", timeptr->tm_sec); + break; + + case ('t'): + length = sprintf(_store, "\t"); + break; + + case ('T'): + length = sprintf(_store, "%.2d:%.2d:%.2d", \ + timeptr->tm_hour, \ + timeptr->tm_min, \ + timeptr->tm_sec \ + ); + break; + + case ('u'): + w = timeptr->tm_wday; + if (w == 0) + w = 7; + length = sprintf(_store, "%d", w); + break; + + case ('U'): + length = sprintf(_store, "%.2u", week_of_year(timeptr, 0)); + break; + + case ('V'): + iso_week_date_r(timeptr->tm_year + 1900, timeptr->tm_yday, &wd); + length = sprintf(_store, "%.2u", wd.week); + break; + + case ('w'): + length = sprintf(_store, "%u", timeptr->tm_wday); + break; + + case ('W'): + w = week_of_year(timeptr, 1); + length = sprintf(_store, "%.2u", w); + break; + + case ('x'): + length = sprintf(_store, "%.2u/%.2u/%.2u", timeptr->tm_mon + 1, timeptr->tm_mday, timeptr->tm_year % 100); + break; + + case ('X'): + length = sprintf(_store, "%.2u:%.2u:%.2u", timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); + break; + + case ('y'): + length = sprintf(_store, "%.2u", timeptr->tm_year % 100); + break; + + case ('Y'): + length = sprintf(_store, "%u", timeptr->tm_year + 1900); + break; + + case ('z'): + d = __utc_offset / 60; + w = timeptr->tm_isdst / 60; + if (w > 0) + d += w; + w = abs(d % 60); + d = d / 60; + length = sprintf(_store, "%+.2d%.2d", d, w); + break; + + default: + length = 1; + _store[0] = '?'; + _store[1] = 0; + break; + } + + if ((length + count) < limit) { + count += length; + for (d = 0; d < (int) length; d++) { + *buffer++ = _store[d]; + } + } else { + *buffer = 0; + return count; + } + + } else { /* copy a literal */ + *buffer = c; + buffer++; + count++; + if (c == 0) + return count; + } + } + + *buffer = 0; + return count; +} -- cgit v1.2.3