initial check-in, version 0.5.0

This commit is contained in:
Rich Felker
2011-02-12 00:22:29 -05:00
commit 0b44a0315b
1021 changed files with 45711 additions and 0 deletions

27
src/time/__asctime.c Normal file
View File

@ -0,0 +1,27 @@
#include <time.h>
#include <stdio.h>
#include <langinfo.h>
const char *__langinfo(nl_item);
char *__asctime(const struct tm *tm, char *buf)
{
/* FIXME: change __langinfo to __C_langinfo once we have locales */
if (snprintf(buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
__langinfo(ABDAY_1+tm->tm_wday),
__langinfo(ABMON_1+tm->tm_mon),
tm->tm_mday, tm->tm_hour,
tm->tm_min, tm->tm_sec,
1900 + tm->tm_year) >= 26)
{
/* ISO C requires us to use the above format string,
* even if it will not fit in the buffer. Thus asctime_r
* is _supposed_ to crash if the fields in tm are too large.
* We follow this behavior and crash "gracefully" to warn
* application developers that they may not be so lucky
* on other implementations (e.g. stack smashing..).
*/
*(int*)0 = 0;
}
return buf;
}

9
src/time/__time.h Normal file
View File

@ -0,0 +1,9 @@
time_t __tm_to_time(struct tm *);
struct tm *__time_to_tm(time_t, struct tm *);
void __tzset(void);
struct tm *__dst_adjust(struct tm *tm);
extern long __timezone;
extern int __daylight;
extern int __dst_offset;
extern char *__tzname[2];

81
src/time/__time_to_tm.c Normal file
View File

@ -0,0 +1,81 @@
#include <time.h>
/* C defines the rounding for division in a nonsensical way */
#define Q(a,b) ((a)>0 ? (a)/(b) : -(((b)-(a)-1)/(b)))
#define DAYS_PER_400Y (365*400 + 97)
#define DAYS_PER_100Y (365*100 + 24)
#define DAYS_PER_4Y (365*4 + 1)
/* FIXME: use lldiv once it's fixed to compute quot,rem together */
struct tm *__time_to_tm(time_t t, struct tm *tm)
{
/* months are march-based */
static const int days_thru_month[] = {31,61,92,122,153,184,214,245,275,306,337,366};
long long bigday;
unsigned int day, year4, year100;
int year, year400;
int month;
int leap;
int hour, min, sec;
int wday, mday, yday;
/* start from 2000-03-01 (multiple of 400 years) */
t += -946684800 - 86400*(31+29);
bigday = Q(t, 86400);
sec = t-bigday*86400;
hour = sec/3600;
sec -= hour*3600;
min = sec/60;
sec -= min*60;
/* 2000-03-01 was a wednesday */
wday = (3+bigday)%7;
if (wday < 0) wday += 7;
t = -946684800LL - 86400*(31+29) + 9000000;
year400 = Q(bigday, DAYS_PER_400Y);
day = bigday-year400*DAYS_PER_400Y;
year100 = day/DAYS_PER_100Y;
if (year100 == 4) year100--;
day -= year100*DAYS_PER_100Y;
year4 = day/DAYS_PER_4Y;
if (year4 == 25) year4--;
day -= year4*DAYS_PER_4Y;
year = day/365;
if (year == 4) year--;
day -= year*365;
leap = !year && (year4 || !year100);
yday = day + 31+28 + leap;
if (yday >= 365+leap) yday -= 365+leap;
year += 4*year4 + 100*year100 + 400*year400 + 2000-1900;
for (month=0; days_thru_month[month] <= day; month++);
if (month) day -= days_thru_month[month-1];
month += 2;
if (month >= 12) {
month -= 12;
year++;
}
mday = day+1;
tm->tm_sec = sec;
tm->tm_min = min;
tm->tm_hour= hour;
tm->tm_mday= mday;
tm->tm_mon = month;
tm->tm_year= year;
tm->tm_wday= wday;
tm->tm_yday= yday;
return tm;
}

33
src/time/__tm_to_time.c Normal file
View File

@ -0,0 +1,33 @@
#include <time.h>
/* C defines the rounding for division in a nonsensical way */
#define Q(a,b) ((a)>0 ? (a)/(b) : -(((b)-(a)-1)/(b)))
time_t __tm_to_time(struct tm *tm)
{
time_t year = tm->tm_year + -100;
int month = tm->tm_mon;
int day = tm->tm_mday;
int z4, z100, z400;
/* normalize month */
if (month >= 12) {
year += month/12;
month %= 12;
} else if (month < 0) {
year += month/12;
month %= 12;
if (month) {
month += 12;
year--;
}
}
z4 = Q(year - (month < 2), 4);
z100 = Q(z4, 25);
z400 = Q(z100, 4);
day += year*365 + z4 - z100 + z400 +
month[(int []){0,31,59,90,120,151,181,212,243,273,304,335}];
return (long long)day*86400
+ tm->tm_hour*3600 + tm->tm_min*60 + tm->tm_sec
- -946684800; /* the dawn of time :) */
}

9
src/time/asctime.c Normal file
View File

@ -0,0 +1,9 @@
#include <time.h>
char *__asctime(const struct tm *, char *);
char *asctime(const struct tm *tm)
{
static char buf[26];
return __asctime(tm, buf);
}

8
src/time/asctime_r.c Normal file
View File

@ -0,0 +1,8 @@
#include <time.h>
char *__asctime(const struct tm *, char *);
char *asctime_r(const struct tm *tm, char *buf)
{
return __asctime(tm, buf);
}

9
src/time/clock.c Normal file
View File

@ -0,0 +1,9 @@
#include <time.h>
#include <sys/times.h>
/* this function assumes 100 hz linux and corrects for it */
clock_t clock()
{
struct tms tms;
return (unsigned long)times(&tms)*10000;
}

7
src/time/clock_gettime.c Normal file
View File

@ -0,0 +1,7 @@
#include <time.h>
#include "syscall.h"
int clock_gettime(clockid_t clk, struct timespec *ts)
{
return syscall2(__NR_clock_gettime, clk, (long)ts);
}

6
src/time/ctime.c Normal file
View File

@ -0,0 +1,6 @@
#include <time.h>
char *ctime(const time_t *t)
{
return asctime(localtime(t));
}

8
src/time/ctime_r.c Normal file
View File

@ -0,0 +1,8 @@
#include <time.h>
char *ctime_r(const time_t *t, char *buf)
{
struct tm tm;
localtime_r(t, &tm);
return asctime_r(&tm, buf);
}

6
src/time/difftime.c Normal file
View File

@ -0,0 +1,6 @@
#include <time.h>
double difftime(time_t t1, time_t t0)
{
return t1-t0;
}

9
src/time/gettimeofday.c Normal file
View File

@ -0,0 +1,9 @@
#define SYSCALL_RETURN_ERRNO
#include <sys/time.h>
#include "syscall.h"
int gettimeofday(struct timeval *tv, void *tz)
{
syscall2(__NR_gettimeofday, (long)tv, 0);
return 0;
}

11
src/time/gmtime.c Normal file
View File

@ -0,0 +1,11 @@
#include <time.h>
#include "__time.h"
struct tm *gmtime(const time_t *t)
{
static struct tm tm;
__time_to_tm(*t, &tm);
tm.tm_isdst = 0;
return &tm;
}

10
src/time/gmtime_r.c Normal file
View File

@ -0,0 +1,10 @@
#include <time.h>
#include "__time.h"
struct tm *gmtime_r(const time_t *t, struct tm *result)
{
__time_to_tm(*t, result);
result->tm_isdst = 0;
return result;
}

12
src/time/localtime.c Normal file
View File

@ -0,0 +1,12 @@
#include <time.h>
#include "__time.h"
struct tm *localtime(const time_t *t)
{
static struct tm tm;
__tzset();
__time_to_tm(*t - __timezone, &tm);
tm.tm_isdst = -1;
return __dst_adjust(&tm);
}

11
src/time/localtime_r.c Normal file
View File

@ -0,0 +1,11 @@
#include <time.h>
#include "__time.h"
struct tm *localtime_r(const time_t *t, struct tm *result)
{
__tzset();
__time_to_tm(*t - __timezone, result);
result->tm_isdst = -1;
return __dst_adjust(result);
}

24
src/time/mktime.c Normal file
View File

@ -0,0 +1,24 @@
#include <time.h>
#include "__time.h"
time_t mktime(struct tm *tm)
{
int isdst = tm->tm_isdst;
time_t t, lt;
__tzset();
tm->tm_sec += __timezone;
if (isdst > 0) tm->tm_sec += __dst_offset;
t = __tm_to_time(tm);
lt = t - __timezone;
if (isdst > 0) lt -= __dst_offset;
__time_to_tm(lt, tm);
__dst_adjust(tm);
return t;
}

13
src/time/nanosleep.c Normal file
View File

@ -0,0 +1,13 @@
#include <unistd.h>
#include <time.h>
#include "syscall.h"
#include "libc.h"
int nanosleep(const struct timespec *req, struct timespec *rem)
{
int ret;
CANCELPT_BEGIN;
ret = syscall2(__NR_nanosleep, (long)req, (long)rem);
CANCELPT_END;
return ret;
}

172
src/time/strftime.c Normal file
View File

@ -0,0 +1,172 @@
#include <stdio.h>
#include <stdlib.h>
#include <langinfo.h>
#include <time.h>
#include "__time.h"
// FIXME: integer overflows
const char *__langinfo(nl_item);
size_t strftime(char *s, size_t n, const char *f, const struct tm *tm)
{
nl_item item;
int val;
const char *fmt;
size_t l;
for (l=0; *f && l<n; f++) {
if (*f == '%') {
do_fmt:
switch (*++f) {
case '%':
goto literal;
case 'E':
case 'O':
goto do_fmt;
case 'a':
item = ABDAY_1 + tm->tm_wday;
goto nl_strcat;
case 'A':
item = DAY_1 + tm->tm_wday;
goto nl_strcat;
case 'h':
case 'b':
item = ABMON_1 + tm->tm_mon;
goto nl_strcat;
case 'B':
item = MON_1 + tm->tm_mon;
goto nl_strcat;
case 'c':
item = D_T_FMT;
goto nl_strftime;
case 'C':
val = (1900+tm->tm_year) / 100;
fmt = "%02d";
goto number;
case 'd':
val = tm->tm_mday;
fmt = "%02d";
goto number;
case 'D':
fmt = "%m/%d/%y";
goto recu_strftime;
case 'e':
val = tm->tm_mday;
fmt = "%2d";
goto number;
case 'F':
fmt = "%Y-%m-%d";
goto recu_strftime;
case 'g':
// FIXME
val = 0; //week_based_year(tm)%100;
fmt = "%02d";
goto number;
case 'G':
// FIXME
val = 0; //week_based_year(tm);
fmt = "%04d";
goto number;
case 'H':
val = tm->tm_hour;
fmt = "%02d";
goto number;
case 'I':
val = tm->tm_hour;
if (!val) val = 12;
else if (val > 12) val -= 12;
fmt = "%02d";
goto number;
case 'j':
val = tm->tm_yday+1;
fmt = "%03d";
goto number;
case 'm':
val = tm->tm_mon+1;
fmt = "%02d";
goto number;
case 'M':
val = tm->tm_min;
fmt = "%02d";
goto number;
case 'n':
s[l++] = '\n';
continue;
case 'p':
item = tm->tm_hour >= 12 ? PM_STR : AM_STR;
goto nl_strcat;
case 'r':
item = T_FMT_AMPM;
goto nl_strftime;
case 'R':
fmt = "%H:%M";
goto recu_strftime;
case 'S':
val = tm->tm_sec;
fmt = "%02d";
goto number;
case 't':
s[l++] = '\t';
continue;
case 'T':
fmt = "%H:%M:%S";
goto recu_strftime;
case 'u':
val = tm->tm_wday ? tm->tm_wday : 7;
fmt = "%d";
goto number;
case 'U':
case 'V':
case 'W':
// FIXME: week number mess..
continue;
case 'w':
val = tm->tm_wday;
fmt = "%d";
goto number;
case 'x':
item = D_FMT;
goto nl_strftime;
case 'X':
item = T_FMT;
goto nl_strftime;
case 'y':
val = tm->tm_year % 100;
fmt = "%02d";
goto number;
case 'Y':
val = tm->tm_year + 1900;
fmt = "%04d";
goto number;
case 'z':
if (tm->tm_isdst < 0) continue;
val = -__timezone - (tm->tm_isdst ? __dst_offset : 0);
l += snprintf(s+l, n-l, "%+.2d%.2d", val/3600, abs(val%3600)/60);
continue;
case 'Z':
if (tm->tm_isdst < 0 || !__tzname[0] || !__tzname[0][0])
continue;
l += snprintf(s+l, n-l, "%s", __tzname[!!tm->tm_isdst]);
continue;
default:
return 0;
}
}
literal:
s[l++] = *f;
continue;
number:
l += snprintf(s+l, n-l, fmt, val);
continue;
nl_strcat:
l += snprintf(s+l, n-l, "%s", __langinfo(item));
continue;
nl_strftime:
fmt = __langinfo(item);
recu_strftime:
l += strftime(s+l, n-l, fmt, tm);
}
if (l >= n) return 0;
s[l] = 0;
return l;
}

178
src/time/strptime.c Normal file
View File

@ -0,0 +1,178 @@
#include <stdio.h>
#include <stdlib.h>
#include <langinfo.h>
#include <time.h>
const char *__langinfo(nl_item);
char *strptime(const char *s, const char *f, struct tm *tm)
{
return NULL;
}
#if 0
char *strptime(const char *s, const char *f, struct tm *tm)
{
nl_item item;
int *dest;
const char *fmt;
for (; *f; f++) {
if (isspace(*f)) goto whitespace;
if (*f == '%') {
do_fmt:
switch (*++f) {
case '%':
goto literal;
case 'E':
case 'O':
goto do_fmt;
case 'a':
item = ABDAY_1 + tm->tm_wday;
goto nl_strcat;
case 'A':
item = DAY_1 + tm->tm_wday;
goto nl_strcat;
case 'h':
case 'b':
item = ABMON_1 + tm->tm_mon;
goto nl_strcat;
case 'B':
item = MON_1 + tm->tm_mon;
goto nl_strcat;
case 'c':
item = D_T_FMT;
goto nl_strftime;
case 'C':
val = (1900+tm->tm_year) / 100;
fmt = "%02d";
goto number;
case 'd':
val = tm->tm_mday;
fmt = "%02d";
goto number;
case 'D':
fmt = "%m/%d/%y";
goto recu_strftime;
case 'e':
val = tm->tm_mday;
fmt = "%2d";
goto number;
case 'F':
fmt = "%Y-%m-%d";
goto recu_strftime;
case 'g':
// FIXME
val = 0; //week_based_year(tm)%100;
fmt = "%02d";
goto number;
case 'G':
// FIXME
val = 0; //week_based_year(tm);
fmt = "%04d";
goto number;
case 'H':
val = tm->tm_hour;
fmt = "%02d";
goto number;
case 'I':
val = tm->tm_hour;
if (!val) val = 12;
else if (val > 12) val -= 12;
fmt = "%02d";
goto number;
case 'j':
val = tm->tm_yday+1;
fmt = "%03d";
goto number;
case 'm':
val = tm->tm_mon+1;
fmt = "%02d";
goto number;
case 'M':
val = tm->tm_min;
fmt = "%02d";
goto number;
case 'n':
case 't':
goto whitespace;
case 'p':
item = tm->tm_hour >= 12 ? PM_STR : AM_STR;
goto nl_strcat;
case 'r':
item = T_FMT_AMPM;
goto nl_strftime;
case 'R':
fmt = "%H:%M";
goto recu_strftime;
case 'S':
val = tm->tm_sec;
fmt = "%02d";
goto number;
case 'T':
fmt = "%H:%M:%S";
goto recu_strftime;
case 'u':
val = tm->tm_wday ? tm->tm_wday : 7;
fmt = "%d";
goto number;
case 'U':
case 'V':
case 'W':
// FIXME: week number mess..
continue;
case 'w':
val = tm->tm_wday;
fmt = "%d";
goto number;
case 'x':
item = D_FMT;
goto nl_strftime;
case 'X':
item = T_FMT;
goto nl_strftime;
case 'y':
val = tm->tm_year % 100;
fmt = "%02d";
goto number;
case 'Y':
val = tm->tm_year + 1900;
fmt = "%04d";
goto number;
case 'z':
if (tm->tm_isdst < 0) continue;
val = timezone + (tm->tm_isdst) ? __dst_offset : 0;
l += snprintf(s+l, n-l, "%+02d%02d", val/60, abs(val%60));
continue;
case 'Z':
if (tm->tm_isdst < 0 || !tzname[0] || !tzname[0][0])
continue;
l += snprintf(s+l, n-l, "%s", tzname[!!tm->tm_isdst]);
continue;
}
default:
return NULL;
}
literal:
if (*s++ != *f) return NULL;
continue;
whitespace:
while(isspace(*s)) s++;
continue;
number:
l += snprintf(s+l, n-l, fmt, val);
continue;
nl_strcat:
l += snprintf(s+l, n-l, "%s", __langinfo(item));
continue;
nl_strftime:
fmt = __langinfo(item);
recu_strftime:
l += strftime(s+l, n-l, fmt, tm);
}
if (l >= n) return 0;
s[l] = 0;
return l;
}
#endif

12
src/time/time.c Normal file
View File

@ -0,0 +1,12 @@
#define SYSCALL_RETURN_ERRNO
#include <time.h>
#include <sys/time.h>
#include "syscall.h"
time_t time(time_t *t)
{
struct timeval tv;
syscall2(__NR_gettimeofday, (long)&tv, 0);
if (t) *t = tv.tv_sec;
return tv.tv_sec;
}

7
src/time/times.c Normal file
View File

@ -0,0 +1,7 @@
#include <sys/times.h>
#include "syscall.h"
clock_t times(struct tms *tms)
{
return syscall1(__NR_times, (long)&tms);
}

27
src/time/timezone.s Normal file
View File

@ -0,0 +1,27 @@
.data
.global timezone
.global __timezone
.global daylight
.global __daylight
.global tzname
.global __tzname
__timezone:
timezone:
.long 0
.size timezone,.-timezone
.size __timezone,.-__timezone
__daylight:
daylight:
.long 0
.size daylight,.-daylight
.size __daylight,.-__daylight
__tzname:
tzname:
.long 0
.long 0
.size tzname,.-tzname
.size __tzname,.-__tzname

173
src/time/tzset.c Normal file
View File

@ -0,0 +1,173 @@
#include <time.h>
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "libc.h"
#include "__time.h"
long __timezone = 0;
int __daylight = 0;
char *__tzname[2] = { 0, 0 };
int __dst_offset = 0;
weak_alias(__timezone, timezone);
weak_alias(__daylight, daylight);
weak_alias(__tzname, tzname);
weak_alias(__dst_offset, dst_offset);
static char std_name[TZNAME_MAX+1];
static char dst_name[TZNAME_MAX+1];
/* all elements are zero-based */
static struct rule {
char month;
char week;
short day;
int time;
} __dst_start, __dst_end;
static void zname(char *d, char **s)
{
int i;
for (i=0; i<TZNAME_MAX && isalpha(d[i]=**s); i++, (*s)++);
d[i] = 0;
}
static int hhmmss(char **s)
{
int ofs = strtol(*s, s, 10)*3600;
if (ofs >= 0) {
if (**s == ':') ofs += strtol(*s+1, s, 10)*60;
if (**s == ':') ofs += strtol(*s+1, s, 10);
} else {
if (**s == ':') ofs -= strtol(*s+1, s, 10)*60;
if (**s == ':') ofs -= strtol(*s+1, s, 10);
}
return ofs;
}
static int dstrule(struct rule *rule, char **s)
{
if (**s != ',') return -1;
switch (*++*s) {
case 'J':
rule->month = 'J';
rule->day = strtol(*s+1, s, 10)-1;
break;
case 'M':
rule->month = strtol(*s+1, s, 10)-1;
if (**s != '.' || rule->month < 0 || rule->month > 11)
return -1;
rule->week = strtol(*s+1, s, 10)-1;
if (**s != '.' || rule->week < 0 || rule->week > 4)
return -1;
rule->day = strtol(*s+1, s, 10);
if (rule->day < 0 || rule->day > 6)
return -1;
break;
default:
rule->month = 'L';
rule->day = strtol(*s+1, s, 10);
break;
}
if (**s == '/') {
(*s)++;
rule->time = hhmmss(s);
} else rule->time = 7200;
return 0;
}
void tzset(void)
{
char *z, *a;
strcpy(std_name, "GMT");
strcpy(dst_name, "GMT");
__tzname[0] = std_name;
__tzname[1] = dst_name;
__timezone = 0;
__daylight = 0;
if (!(z = getenv("TZ")) || !isalpha(*z)) return;
zname(std_name, &z);
__timezone = hhmmss(&z);
zname(dst_name, &z);
if (dst_name[0]) __daylight=1;
a = z;
__dst_offset = hhmmss(&z) - __timezone;
if (z==a) __dst_offset = -3600;
if (dstrule(&__dst_start, &z) || dstrule(&__dst_end, &z))
__daylight = 0;
}
void __tzset(void)
{
static int lock, init;
if (init) return;
LOCK(&lock);
if (!init) tzset();
init=1;
UNLOCK(&lock);
}
static int is_leap(int year)
{
year -= 100;
return !(year&3) && ((year%100) || !(year%400));
}
static int cutoff_yday(struct tm *tm, struct rule *rule)
{
static const char days_in_month[] = {31,28,31,30,31,30,31,31,30,31,30,31};
static const int first_day[] = {0,31,59,90,120,151,181,212,243,273,304,335};
int yday, mday, leap;
switch (rule->month) {
case 'J':
return rule->day + (tm->tm_mon > 1 && is_leap(tm->tm_year));
case 'L':
return rule->day;
default:
yday = first_day[rule->month];
leap = is_leap(tm->tm_year);
if (rule->month > 1 && leap) yday++;
mday = (rule->day - (yday + tm->tm_wday - tm->tm_yday) + 1400)%7 + 7*rule->week;
if (mday >= days_in_month[rule->month] + (leap && rule->month == 1))
mday -= 7;
return mday + yday;
}
}
struct tm *__dst_adjust(struct tm *tm)
{
time_t t;
int start, end, secs;
int after_start, before_end;
if (tm->tm_isdst >= 0) return tm;
if (!__daylight) {
tm->tm_isdst = 0;
return tm;
}
secs = tm->tm_hour*3600 + tm->tm_min*60 + tm->tm_sec;
start = cutoff_yday(tm, &__dst_start);
end = cutoff_yday(tm, &__dst_end);
after_start = (tm->tm_yday > start || (tm->tm_yday == start && secs >= __dst_start.time));
before_end = (tm->tm_yday < end || (tm->tm_yday == end && secs < __dst_end.time));
if ((after_start && before_end) || ((end < start) && (after_start || before_end))) {
tm->tm_sec -= __dst_offset;
tm->tm_isdst = 1;
t = __tm_to_time(tm);
return __time_to_tm(t, tm);
} else tm->tm_isdst = 0;
return tm;
}

12
src/time/utime.c Normal file
View File

@ -0,0 +1,12 @@
#include <utime.h>
#include "syscall.h"
int utime(const char *path, const struct utimbuf *times)
{
long ktimes[2];
if (times) {
ktimes[0] = times->actime;
ktimes[1] = times->modtime;
}
return syscall2(__NR_utime, (long)path, times ? (long)ktimes : 0);
}