diff options
| -rw-r--r-- | src/time/strftime.c | 312 | 
1 files changed, 161 insertions, 151 deletions
| diff --git a/src/time/strftime.c b/src/time/strftime.c index 3f0ec3e3..87e87d50 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -44,168 +44,178 @@ static int week_num(const struct tm *tm)  	return val;  } -size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm, locale_t loc) +size_t __strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t); + +int __strftime_fmt_1(char *s, size_t n, int f, const struct tm *tm, locale_t loc)  {  	nl_item item;  	int val;  	const char *fmt;  	size_t l; -	for (l=0; *f && l<n; f++) { -		if (*f != '%') { -literal: -			s[l++] = *f; -			continue; -		} -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': -		case 'G': -			fmt = "%04d"; -			val = tm->tm_year + 1900; -			if (tm->tm_yday < 3 && week_num(tm) != 1) val--; -			else if (tm->tm_yday > 360 && week_num(tm) == 1) val++; -			if (*f=='g') { -				fmt = "%02d"; -				val %= 100; -			} -			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': -			val = (tm->tm_yday + 7 - tm->tm_wday) / 7; -			fmt = "%02d"; -			goto number; -		case 'W': -			val = (tm->tm_yday + 7 - (tm->tm_wday+6)%7) / 7; -			fmt = "%02d"; -			goto number; -		case 'V': -			val = week_num(tm); -			fmt = "%02d"; -			goto number; -		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; + +	if (n<2) return 0; + +	switch (f) { +	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': +	case 'G': +		fmt = "%04d"; +		val = tm->tm_year + 1900; +		if (tm->tm_yday < 3 && week_num(tm) != 1) val--; +		else if (tm->tm_yday > 360 && week_num(tm) == 1) val++; +		if (f=='g') {  			fmt = "%02d"; -			goto number; -		case 'Y': -			val = tm->tm_year + 1900; -			fmt = "%04d"; -			goto number; -		case 'z': -			val = -tm->__tm_gmtoff; -			l += snprintf(s+l, n-l, "%+.2d%.2d", val/3600, abs(val%3600)/60); -			continue; -		case 'Z': -			l += snprintf(s+l, n-l, "%s", tm->__tm_zone); -			continue; -		default: -			return 0; +			val %= 100;  		} +		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[0] = '\n'; +		s[1] = 0; +		return 1; +	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[0] = '\t'; +		s[1] = 0; +		return 1; +	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': +		val = (tm->tm_yday + 7 - tm->tm_wday) / 7; +		fmt = "%02d"; +		goto number; +	case 'W': +		val = (tm->tm_yday + 7 - (tm->tm_wday+6)%7) / 7; +		fmt = "%02d"; +		goto number; +	case 'V': +		val = week_num(tm); +		fmt = "%02d"; +		goto number; +	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': +		val = -tm->__tm_gmtoff; +		return snprintf(s, n, "%+.2d%.2d", val/3600, abs(val%3600)/60); +	case 'Z': +		return snprintf(s, n, "%s", tm->__tm_zone); +	case '%': +		s[0] = '%'; +		s[1] = 0; +		return 1; +	default: +		return 0; +	}  number: -		l += snprintf(s+l, n-l, fmt, val); -		continue; +	return snprintf(s, n, fmt, val);  nl_strcat: -		l += snprintf(s+l, n-l, "%s", __nl_langinfo_l(item, loc)); -		continue; +	return snprintf(s, n, "%s", __nl_langinfo_l(item, loc));  nl_strftime: -		fmt = __nl_langinfo_l(item, loc); +	fmt = __nl_langinfo_l(item, loc);  recu_strftime: -		l += __strftime_l(s+l, n-l, fmt, tm, loc); +	return __strftime_l(s, n, fmt, tm, loc); +} + +size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm, locale_t loc) +{ +	size_t l, k; +	for (l=0; *f && l<n; f++) { +		if (*f != '%') { +			s[l++] = *f; +			continue; +		} +		f++; +		if (*f == 'E' || *f == 'O') f++; +		k = __strftime_fmt_1(s+l, n-l, *f, tm, loc); +		if (!k) return 0; +		l += k;  	}  	if (l >= n) return 0;  	s[l] = 0; | 
