snprintf支持格式化结构体
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void *sample_handle = NULL;
|
void *sample_handle = NULL;
|
||||||
void *test_handle = NULL;
|
void *test_handle = NULL;
|
||||||
@@ -19,9 +20,25 @@ int g_thread_num = 0;
|
|||||||
const char *g_zlog_conf = NULL;
|
const char *g_zlog_conf = NULL;
|
||||||
volatile long g_start_time = 0;
|
volatile long g_start_time = 0;
|
||||||
volatile long g_end_time = 0;
|
volatile long g_end_time = 0;
|
||||||
|
struct test_A{
|
||||||
|
int a;
|
||||||
|
char *str;
|
||||||
|
long long b;
|
||||||
|
};
|
||||||
|
int MESA_fmt_handler_A(void *info, char *buf, int maxlen)
|
||||||
|
{
|
||||||
|
struct test_A *obj = (struct test_A *)info;
|
||||||
|
int n = snprintf(buf, maxlen, "a=%d,s=%s,b=%lld", obj->a, obj->str, obj->b);
|
||||||
|
return n < maxlen?n:maxlen - 1;
|
||||||
|
}
|
||||||
|
|
||||||
void call_logger(int log_num, int thread_num)
|
void call_logger(int log_num, int thread_num)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct test_A a;
|
||||||
|
a.a = 10;
|
||||||
|
a.str = "hello";
|
||||||
|
a.b = 123456;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct timespec start, end;
|
struct timespec start, end;
|
||||||
long start_time, end_time, time_cost;
|
long start_time, end_time, time_cost;
|
||||||
@@ -40,12 +57,13 @@ void call_logger(int log_num, int thread_num)
|
|||||||
}
|
}
|
||||||
for(i = 0; i < log_num; i++)
|
for(i = 0; i < log_num; i++)
|
||||||
{
|
{
|
||||||
MESA_handle_runtime_log(sample_handle, RLOG_LV_DEBUG, "sample", "sample_handle MESA_handle_runtime_log, i = %d, thread_num = %d", i, thread_num);
|
//MESA_handle_runtime_log(sample_handle, RLOG_LV_DEBUG, "sample", "sample_handle MESA_handle_runtime_log, i = %d, thread_num = %d", i, thread_num);
|
||||||
//sleep(1);
|
//sleep(1);
|
||||||
MESA_handle_runtime_log(test_handle, RLOG_LV_INFO, "test", "test_handle MESA_handle_runtime_log, i = %d, thread_num = %d", i, thread_num);
|
//MESA_handle_runtime_log(test_handle, RLOG_LV_INFO, "test", "test_handle MESA_handle_runtime_log, i = %d, thread_num = %d", i, thread_num);
|
||||||
//MESA_HANDLE_RUNTIME_LOG(sample_handle, RLOG_LV_FATAL, "sample", "sample_handle RUNTIEM_LOG test, i = %d, thread_num = %d", i, thread_num);
|
MESA_HANDLE_RUNTIME_LOG(sample_handle, RLOG_LV_FATAL, "sample", "sample_handle RUNTIEM_LOG test, i = %d, thread_num = %d", i, thread_num);
|
||||||
//sleep(1);
|
//sleep(1);
|
||||||
//MESA_HANDLE_RUNTIME_LOG(test_handle, RLOG_LV_FATAL, "test", "test_handle RUNTIEM_LOG test, i = %d, thread_num = %d", i, thread_num);
|
MESA_HANDLE_RUNTIME_LOG(test_handle, RLOG_LV_FATAL, "test", "test_handle RUNTIEM_LOG test, i = %d, thread_num = %d", i, thread_num);
|
||||||
|
MESA_HANDLE_RUNTIME_LOG(sample_handle, RLOG_LV_FATAL, "sample", "sample_handle RUNTIEM_LOG test, i = %d, thread_num = %d,struct a =%A", i, thread_num, &a);
|
||||||
}
|
}
|
||||||
clock_gettime(CLOCK_MONOTONIC, &end);
|
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||||
end_time = end.tv_sec*1000000 + end.tv_nsec/1000;
|
end_time = end.tv_sec*1000000 + end.tv_nsec/1000;
|
||||||
@@ -130,6 +148,10 @@ int main(int argc, char ** args)
|
|||||||
printf("get log sample_handle error\n");
|
printf("get log sample_handle error\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if(MESA_handle_fmt_rule_register(sample_handle, 'A', MESA_fmt_handler_A, 512) < 0){
|
||||||
|
printf("struct a register error\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
test_handle = MESA_create_runtime_log_handle("./log/test_log", RLOG_LV_DEBUG);
|
test_handle = MESA_create_runtime_log_handle("./log/test_log", RLOG_LV_DEBUG);
|
||||||
if(test_handle == NULL)
|
if(test_handle == NULL)
|
||||||
|
|||||||
@@ -14,6 +14,19 @@ extern "C"
|
|||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#define MESA_PTHREAD_CACHE_BUF_DEFAULT_LEN 1024
|
||||||
|
#define MESA_PTHREAD_FMT_BUF_DEFAULT_LEN 256
|
||||||
|
extern pthread_key_t MESA_pthread_key;
|
||||||
|
void MESA_pthread_free_handler(void *arg);
|
||||||
|
|
||||||
|
typedef int (*MESA_fmt_handler)(void *info, char *buf, int buflen);
|
||||||
|
int MESA_handle_fmt_rule_register(void *handle, char sign, MESA_fmt_handler handler, int buflen);
|
||||||
|
int MESA_handle_check_fmt_sign(void *handle, char sign, MESA_fmt_handler *handler, char **buf, int *maxlen);
|
||||||
|
void MESA_free_pthread_private(void *arg);
|
||||||
|
|
||||||
|
|
||||||
#define RLOG_LV_DEBUG 10
|
#define RLOG_LV_DEBUG 10
|
||||||
#define RLOG_LV_INFO 20
|
#define RLOG_LV_INFO 20
|
||||||
#define RLOG_LV_FATAL 30
|
#define RLOG_LV_FATAL 30
|
||||||
@@ -21,7 +34,7 @@ extern "C"
|
|||||||
|
|
||||||
int MESA_handle_runtime_log_creation(const char *conf_path);
|
int MESA_handle_runtime_log_creation(const char *conf_path);
|
||||||
int MESA_handle_runtime_log_reconstruction(const char *conf_path);
|
int MESA_handle_runtime_log_reconstruction(const char *conf_path);
|
||||||
void MESA_handle_runtime_log_destruction();
|
void MESA_handle_runtime_log_destruction(void);
|
||||||
|
|
||||||
#define MESA_HANDLE_RUNTIME_LOG(handle, lv, mod, fmt, args...) \
|
#define MESA_HANDLE_RUNTIME_LOG(handle, lv, mod, fmt, args...) \
|
||||||
MESA_handle_runtime_log((handle), (lv), (mod), "file %s, line %d, " fmt, \
|
MESA_handle_runtime_log((handle), (lv), (mod), "file %s, line %d, " fmt, \
|
||||||
|
|||||||
24
inc/snprintf.h
Normal file
24
inc/snprintf.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef _PORTABLE_SNPRINTF_H_
|
||||||
|
#define _PORTABLE_SNPRINTF_H_
|
||||||
|
|
||||||
|
#define PORTABLE_SNPRINTF_VERSION_MAJOR 2
|
||||||
|
#define PORTABLE_SNPRINTF_VERSION_MINOR 2
|
||||||
|
|
||||||
|
#ifdef HAVE_SNPRINTF
|
||||||
|
#include <stdio.h>
|
||||||
|
#else
|
||||||
|
extern int snprintf(char *, size_t, const char *, /*args*/ ...);
|
||||||
|
extern int vsnprintf(char *, size_t, const char *, va_list);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF)
|
||||||
|
extern int portable_snprintf(void * handle, char *str, size_t str_m, const char *fmt, /*args*/ ...);
|
||||||
|
extern int portable_vsnprintf(void *handle, char *str, size_t str_m, const char *fmt, va_list ap);
|
||||||
|
/*#define snprintf portable_snprintf*/ /*others use libc snprintf*/
|
||||||
|
/*#define vsnprintf portable_vsnprintf*/
|
||||||
|
#endif
|
||||||
|
extern int asprintf (void * handle, char **ptr, const char *fmt, /*args*/ ...);
|
||||||
|
extern int vasprintf (void * handle, char **ptr, const char *fmt, va_list ap);
|
||||||
|
extern int asnprintf (void * handle, char **ptr, size_t str_m, const char *fmt, /*args*/ ...);
|
||||||
|
extern int vasnprintf(void * handle, char **ptr, size_t str_m, const char *fmt, va_list ap);
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
#include "MESA_handle_logger.h"
|
#include "MESA_handle_logger.h"
|
||||||
|
#include "snprintf.h"
|
||||||
#include "zlog.h"
|
#include "zlog.h"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -14,12 +17,30 @@ static int g_zlog_conf_fp = -1;
|
|||||||
static char global_conf_filepath[MAX_HANDLE_LOG_PATH] = "";
|
static char global_conf_filepath[MAX_HANDLE_LOG_PATH] = "";
|
||||||
static char tmp_conf_filepath[MAX_HANDLE_LOG_PATH] = "";
|
static char tmp_conf_filepath[MAX_HANDLE_LOG_PATH] = "";
|
||||||
|
|
||||||
|
#define MESA_FORMAT_RULE_MAX 16
|
||||||
|
pthread_key_t MESA_pthread_key;
|
||||||
|
pthread_once_t MESA_pthread_key_once = PTHREAD_ONCE_INIT;
|
||||||
|
|
||||||
|
struct MESA_pthread_private{
|
||||||
|
char *fmt_buf;
|
||||||
|
char *cache_buf;
|
||||||
|
int fmt_buf_len;
|
||||||
|
int cache_buf_len;
|
||||||
|
};
|
||||||
|
struct MESA_fmt_obj{
|
||||||
|
char sign;
|
||||||
|
MESA_fmt_handler handler;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct log_handle_t
|
typedef struct log_handle_t
|
||||||
{
|
{
|
||||||
int runtime_log_level;
|
int runtime_log_level;
|
||||||
|
int fmt_rule_num;
|
||||||
zlog_category_t *zc;
|
zlog_category_t *zc;
|
||||||
const char *global_conf_path;
|
const char *global_conf_path;
|
||||||
char runtime_log_file[MAX_HANDLE_LOG_PATH];
|
char runtime_log_file[MAX_HANDLE_LOG_PATH];
|
||||||
|
int fmt_buf_len;
|
||||||
|
struct MESA_fmt_obj fmt_rule[MESA_FORMAT_RULE_MAX];
|
||||||
} log_handle_t;
|
} log_handle_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -127,6 +148,7 @@ static const char *loglevel_to_name(int level)
|
|||||||
|
|
||||||
static void snapshot_handle_info(const char *handle_name, const char *log_path, int level)
|
static void snapshot_handle_info(const char *handle_name, const char *log_path, int level)
|
||||||
{
|
{
|
||||||
|
int n = 0;
|
||||||
char zlog_rule_conf_content[MAX_HANDLE_LOG_PATH + 1] = "";
|
char zlog_rule_conf_content[MAX_HANDLE_LOG_PATH + 1] = "";
|
||||||
static char *tmp_prefix = "/tmp/MESA_handle_logger/";
|
static char *tmp_prefix = "/tmp/MESA_handle_logger/";
|
||||||
static char *zlog_conf_init_buff = "[global]\ndefault format = \"%d(%c), %V, %F, %U, %m%n\" \n[levels]\nDEBUG=10\nINFO=20\nFATAL=30\n[rules]";
|
static char *zlog_conf_init_buff = "[global]\ndefault format = \"%d(%c), %V, %F, %U, %m%n\" \n[levels]\nDEBUG=10\nINFO=20\nFATAL=30\n[rules]";
|
||||||
@@ -145,13 +167,22 @@ static void snapshot_handle_info(const char *handle_name, const char *log_path,
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
write(g_zlog_conf_fp, zlog_conf_init_buff, strlen(zlog_conf_init_buff));
|
n = write(g_zlog_conf_fp, zlog_conf_init_buff, strlen(zlog_conf_init_buff));
|
||||||
|
if(n < 0){
|
||||||
|
fprintf(stderr,"write g_zlog_conf_fp error, func=%s, line=%d\n",__FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
fsync(g_zlog_conf_fp);
|
fsync(g_zlog_conf_fp);
|
||||||
}
|
}
|
||||||
snprintf(zlog_rule_conf_content, sizeof(zlog_rule_conf_content),
|
n = snprintf(zlog_rule_conf_content, sizeof(zlog_rule_conf_content),
|
||||||
"\n%s.%s \"%s.%%d(%%F)\"",
|
"\n%s.%s \"%s.%%d(%%F)\"",
|
||||||
handle_name, loglevel_to_name(level), log_path);
|
handle_name, loglevel_to_name(level), log_path);
|
||||||
write(g_zlog_conf_fp, zlog_rule_conf_content, strlen(zlog_rule_conf_content));
|
if(n > 0){
|
||||||
|
n = write(g_zlog_conf_fp, zlog_rule_conf_content, strlen(zlog_rule_conf_content));
|
||||||
|
if(n < 0){
|
||||||
|
fprintf(stderr,"write g_zlog_conf_fp error, func=%s, line=%d\n",__FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fsync(g_zlog_conf_fp);
|
fsync(g_zlog_conf_fp);
|
||||||
|
|
||||||
if(g_zlog_inited == 0)
|
if(g_zlog_inited == 0)
|
||||||
@@ -162,15 +193,70 @@ static void snapshot_handle_info(const char *handle_name, const char *log_path,
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
struct MESA_pthread_private *MESA_create_pthread_private(void *handle)
|
||||||
|
{
|
||||||
|
|
||||||
|
log_handle_t *p_handle = (log_handle_t *)handle;
|
||||||
|
struct MESA_pthread_private *pri = malloc(sizeof(struct MESA_pthread_private));
|
||||||
|
if(pri == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(pri, 0 ,sizeof(struct MESA_pthread_private));
|
||||||
|
pri->fmt_buf = malloc(p_handle->fmt_buf_len);
|
||||||
|
if(pri->fmt_buf == NULL){
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
pri->fmt_buf_len = p_handle->fmt_buf_len;
|
||||||
|
pri->cache_buf_len = MESA_PTHREAD_CACHE_BUF_DEFAULT_LEN;
|
||||||
|
pri->cache_buf = malloc(pri->cache_buf_len);
|
||||||
|
if(pri->cache_buf == NULL){
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
return pri;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if(pri->fmt_buf){
|
||||||
|
free(pri->fmt_buf);
|
||||||
|
}
|
||||||
|
if(pri->cache_buf){
|
||||||
|
free(pri->cache_buf);
|
||||||
|
}
|
||||||
|
if(pri){
|
||||||
|
free(pri);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
void MESA_free_pthread_private(void *arg)
|
||||||
|
{
|
||||||
|
struct MESA_pthread_private *pri = (struct MESA_pthread_private *)arg;
|
||||||
|
if(pri == NULL){
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
if(pri->fmt_buf){
|
||||||
|
free(pri->fmt_buf);
|
||||||
|
}
|
||||||
|
if(pri->cache_buf){
|
||||||
|
free(pri->cache_buf);
|
||||||
|
}
|
||||||
|
if(pri){
|
||||||
|
free(pri);
|
||||||
|
}
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MESA_alloc_pthread_key()
|
||||||
|
{
|
||||||
|
pthread_key_create(&MESA_pthread_key, MESA_free_pthread_private);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
void *MESA_create_runtime_log_handle(const char *file_path, int level)
|
void *MESA_create_runtime_log_handle(const char *file_path, int level)
|
||||||
{
|
{
|
||||||
if(file_path == NULL)
|
if(file_path == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
int rc = -1;
|
|
||||||
zlog_category_t *zc = NULL;
|
zlog_category_t *zc = NULL;
|
||||||
FILE *fp = NULL;
|
|
||||||
log_handle_t *p_handle = NULL;
|
log_handle_t *p_handle = NULL;
|
||||||
|
|
||||||
char handle_name[MAX_HANDLE_LOG_PATH];
|
char handle_name[MAX_HANDLE_LOG_PATH];
|
||||||
@@ -199,6 +285,8 @@ void *MESA_create_runtime_log_handle(const char *file_path, int level)
|
|||||||
strncpy(p_handle->runtime_log_file, file_path, sizeof(p_handle->runtime_log_file) - 1);
|
strncpy(p_handle->runtime_log_file, file_path, sizeof(p_handle->runtime_log_file) - 1);
|
||||||
p_handle->runtime_log_level = level;
|
p_handle->runtime_log_level = level;
|
||||||
p_handle->zc = zc;
|
p_handle->zc = zc;
|
||||||
|
p_handle->fmt_buf_len = MESA_PTHREAD_FMT_BUF_DEFAULT_LEN;
|
||||||
|
pthread_once(&MESA_pthread_key_once, MESA_alloc_pthread_key);
|
||||||
return (void *)p_handle;
|
return (void *)p_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,9 +312,31 @@ void MESA_handle_runtime_log(void *handle, int level, const char *module, const
|
|||||||
if(p_handle->zc == NULL)return;
|
if(p_handle->zc == NULL)return;
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
va_list ap_bk;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vzlog(p_handle->zc, p_handle->runtime_log_file, strlen(p_handle->runtime_log_file), module, strlen(module), __LINE__, level, fmt, ap);
|
struct MESA_pthread_private *pri = (struct MESA_pthread_private *)pthread_getspecific(MESA_pthread_key);
|
||||||
|
if(pri == NULL){
|
||||||
|
pri = MESA_create_pthread_private(handle);
|
||||||
|
if(pri == NULL){
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
pthread_setspecific(MESA_pthread_key,(void*)pri);
|
||||||
|
}
|
||||||
|
va_copy(ap_bk, ap);
|
||||||
|
int n = portable_vsnprintf(handle, pri->cache_buf, pri->cache_buf_len, fmt, ap_bk);
|
||||||
|
if(n >= pri->cache_buf_len){
|
||||||
|
char *p = realloc(pri->cache_buf, n + 1);
|
||||||
|
if(p != NULL){
|
||||||
|
pri->cache_buf_len = n + 1;
|
||||||
|
pri->cache_buf = p;
|
||||||
|
va_copy(ap_bk, ap);
|
||||||
|
portable_vsnprintf(handle, pri->cache_buf, pri->cache_buf_len, fmt, ap_bk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
va_end(ap_bk);
|
||||||
|
zlog(p_handle->zc, p_handle->runtime_log_file, strlen(p_handle->runtime_log_file), module, strlen(module), __LINE__, level, "%s", pri->cache_buf);
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,3 +438,51 @@ void MESA_handle_runtime_log_destruction()
|
|||||||
close(g_zlog_conf_fp);
|
close(g_zlog_conf_fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MESA_handle_fmt_rule_register(void *handle, char sign, MESA_fmt_handler handler, int buflen)
|
||||||
|
{
|
||||||
|
log_handle_t *p_handle = (log_handle_t *)handle;
|
||||||
|
int fmt_rule_num = p_handle->fmt_rule_num;
|
||||||
|
if(fmt_rule_num >= MESA_FORMAT_RULE_MAX){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p_handle->fmt_rule[fmt_rule_num].sign = sign;
|
||||||
|
p_handle->fmt_rule[fmt_rule_num].handler = handler;
|
||||||
|
p_handle->fmt_rule_num++;
|
||||||
|
if(buflen > 0 && buflen > p_handle->fmt_buf_len){
|
||||||
|
p_handle->fmt_buf_len = buflen;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int MESA_handle_check_fmt_sign(void *handle, char sign, MESA_fmt_handler *handler, char**buf, int *maxlen)
|
||||||
|
{
|
||||||
|
if(!handle || !handler){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
struct MESA_pthread_private *pthread_pri = NULL;
|
||||||
|
log_handle_t *p_handle = (log_handle_t *)handle;
|
||||||
|
int fmt_rule_num = p_handle->fmt_rule_num;
|
||||||
|
int i = 0;
|
||||||
|
for(i = 0; i < fmt_rule_num; i++){
|
||||||
|
if(p_handle->fmt_rule[i].sign == sign){
|
||||||
|
pthread_pri = (struct MESA_pthread_private *)pthread_getspecific(MESA_pthread_key);
|
||||||
|
if(pthread_pri == NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*handler = p_handle->fmt_rule[i].handler;
|
||||||
|
if(p_handle->fmt_buf_len > pthread_pri->fmt_buf_len){
|
||||||
|
char *p = realloc(pthread_pri->fmt_buf, p_handle->fmt_buf_len);
|
||||||
|
if(p != NULL){
|
||||||
|
pthread_pri->fmt_buf = p;
|
||||||
|
pthread_pri->fmt_buf_len = p_handle->fmt_buf_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*buf = pthread_pri->fmt_buf;
|
||||||
|
*maxlen = pthread_pri->fmt_buf_len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
121
src/portable_snprintf/LICENSE.txt
Normal file
121
src/portable_snprintf/LICENSE.txt
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
The Frontier Artistic License Version 1.0
|
||||||
|
Derived from the Artistic License at OpenSource.org.
|
||||||
|
Submitted to OpenSource.org for Open Source Initiative certification.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The intent of this document is to state the conditions under which a
|
||||||
|
Package may be copied, such that the Copyright Holder maintains some
|
||||||
|
semblance of artistic control over the development of the package,
|
||||||
|
while giving the users of the package the right to use and distribute
|
||||||
|
the Package in a more-or-less customary fashion, plus the right to
|
||||||
|
make reasonable modifications.
|
||||||
|
|
||||||
|
Definitions
|
||||||
|
|
||||||
|
"Package" refers to the script, suite, file, or collection of
|
||||||
|
scripts, suites, and/or files distributed by the Copyright Holder,
|
||||||
|
and to derivatives of that Package created through textual modification.
|
||||||
|
|
||||||
|
"Standard Version" refers to such a Package if it has not been
|
||||||
|
modified, or has been modified in accordance with the wishes of
|
||||||
|
the Copyright Holder.
|
||||||
|
|
||||||
|
"Copyright Holder" is whoever is named in the copyright statement
|
||||||
|
or statements for the package.
|
||||||
|
|
||||||
|
"You" is you, if you're thinking about copying or distributing
|
||||||
|
this Package.
|
||||||
|
|
||||||
|
"Reasonable copying fee" is whatever you can justify on the basis
|
||||||
|
of media cost, duplication charges, time of people involved, and
|
||||||
|
so on. (You will not be required to justify it to the Copyright
|
||||||
|
Holder, but only to the computing community at large as a market
|
||||||
|
that must bear the fee.)
|
||||||
|
|
||||||
|
"Freely Available" means that no fee is charged for the item
|
||||||
|
itself, though there may be fees involved in handling the item.
|
||||||
|
It also means that recipients of the item may redistribute it under
|
||||||
|
the same conditions they received it.
|
||||||
|
|
||||||
|
|
||||||
|
Terms
|
||||||
|
|
||||||
|
1. You may make and give away verbatim copies of the source form of
|
||||||
|
the Standard Version of this Package without restriction, provided
|
||||||
|
that you duplicate all of the original copyright notices and
|
||||||
|
associated disclaimers.
|
||||||
|
|
||||||
|
2. You may apply bug fixes, portability fixes, and other modifications
|
||||||
|
derived from the Public Domain or from the Copyright Holder. A Package
|
||||||
|
modified in such a way shall still be considered the Standard Version.
|
||||||
|
|
||||||
|
3. You may otherwise modify your copy of this Package in any way,
|
||||||
|
provided that you insert a prominent notice in each changed script,
|
||||||
|
suite, or file stating how and when you changed that script, suite,
|
||||||
|
or file, and provided that you do at least ONE of the following:
|
||||||
|
|
||||||
|
a) Use the modified Package only within your corporation or
|
||||||
|
organization, or retain the modified Package solely for personal use.
|
||||||
|
|
||||||
|
b) Place your modifications in the Public Domain or otherwise make
|
||||||
|
them Freely Available, such as by posting said modifications to Usenet
|
||||||
|
or an equivalent medium, or placing the modifications on a major archive
|
||||||
|
site such as ftp.uu.net, or by allowing the Copyright Holder to include
|
||||||
|
your modifications in the Standard Version of the Package.
|
||||||
|
|
||||||
|
c) Rename any non-standard executables so the names do not conflict
|
||||||
|
with standard executables, which must also be provided, and provide
|
||||||
|
a separate manual page (or equivalent) for each non-standard executable
|
||||||
|
that clearly documents how it differs from the Standard Version.
|
||||||
|
|
||||||
|
d) Make other distribution arrangements with the Copyright Holder.
|
||||||
|
|
||||||
|
4. You may distribute the programs of this Package in object code or
|
||||||
|
executable form, provided that you do at least ONE of the following:
|
||||||
|
|
||||||
|
a) Distribute a Standard Version of the executables and library
|
||||||
|
files, together with instructions (in the manual page or
|
||||||
|
equivalent) on where to get the Standard Version.
|
||||||
|
|
||||||
|
b) Accompany the distribution with the machine-readable source of
|
||||||
|
the Package with your modifications.
|
||||||
|
|
||||||
|
c) Accompany any non-standard executables with their corresponding
|
||||||
|
Standard Version executables, give the non-standard executables
|
||||||
|
non-standard names, and clearly document the differences in manual
|
||||||
|
pages (or equivalent), together with instructions on where to get
|
||||||
|
the Standard Version.
|
||||||
|
|
||||||
|
d) Make other distribution arrangements with the Copyright Holder.
|
||||||
|
|
||||||
|
5. You may charge a reasonable copying fee for any distribution of
|
||||||
|
this Package. You may charge any fee you choose for support of this
|
||||||
|
Package. You may not charge a fee for this Package itself. However,
|
||||||
|
you may distribute this Package in aggregate with other (possibly
|
||||||
|
commercial) programs as part of a larger (possibly commercial)
|
||||||
|
software distribution provided that you do not advertise this Package
|
||||||
|
as a product of your own.
|
||||||
|
|
||||||
|
6. The scripts and library files supplied as input to or produced as
|
||||||
|
output from the programs of this Package do not automatically fall
|
||||||
|
under the copyright of this Package, but belong to whomever generated
|
||||||
|
them, and may be sold commercially, and may be aggregated with this
|
||||||
|
Package.
|
||||||
|
|
||||||
|
7. Scripts, suites, or programs supplied by you that depend on or
|
||||||
|
otherwise make use of this Package shall not be considered part of
|
||||||
|
this Package.
|
||||||
|
|
||||||
|
8. The name of the Copyright Holder may not be used to endorse or
|
||||||
|
promote products derived from this software without specific prior
|
||||||
|
written permission.
|
||||||
|
|
||||||
|
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
The End
|
||||||
|
|
||||||
|
|
||||||
|
http://www.spinwardstars.com/frontier/fal.html
|
||||||
54
src/portable_snprintf/Makefile
Normal file
54
src/portable_snprintf/Makefile
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Make sure you include -DHAVE_SNPRINTF in CFLAGS if your system
|
||||||
|
# does have snprintf!
|
||||||
|
|
||||||
|
# If you need (long long int) support and you sprintf supports it,
|
||||||
|
# define -DSNPRINTF_LONGLONG_SUPPORT
|
||||||
|
vpath %.h ../../inc
|
||||||
|
vpath %.a ../../lib
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
CFLAGS = -DPREFER_PORTABLE_SNPRINTF -O3 \
|
||||||
|
-Wall -Wpointer-arith -Wwrite-strings \
|
||||||
|
-Wcast-qual -Wcast-align -Waggregate-return \
|
||||||
|
-Wmissing-prototypes -Wmissing-declarations \
|
||||||
|
-Wshadow -Wstrict-prototypes
|
||||||
|
|
||||||
|
CFLAGS+=-DSNPRINTF_LONGLONG_SUPPORT -DHAVE_SNPRINTF
|
||||||
|
CFLAGS+=-I../../inc/
|
||||||
|
|
||||||
|
# -DNEED_ASPRINTF -DNEED_ASNPRINTF -DNEED_VASPRINTF -DNEED_VASNPRINTF
|
||||||
|
# -DNEED_SNPRINTF_ONLY
|
||||||
|
|
||||||
|
# Digital Unix: native compiler usually produces better code than gcc
|
||||||
|
#CC = cc
|
||||||
|
#CFLAGS = -DPREFER_PORTABLE_SNPRINTF -O4 -std1 -arch host
|
||||||
|
|
||||||
|
# Recommend to leave COMPATIBILITY empty for normal use.
|
||||||
|
# Should be set for bug compatibility when running tests
|
||||||
|
# too keep them less chatty.
|
||||||
|
COMPATIBILITY =
|
||||||
|
|
||||||
|
#COMPATIBILITY = -DSOLARIS_BUG_COMPATIBLE
|
||||||
|
#COMPATIBILITY = -DHPUX_BUG_COMPATIBLE
|
||||||
|
#COMPATIBILITY = -DDIGITAL_UNIX_BUG_COMPATIBLE
|
||||||
|
#COMPATIBILITY = -DPERL_BUG_COMPATIBLE
|
||||||
|
#COMPATIBILITY = -DLINUX_COMPATIBLE
|
||||||
|
|
||||||
|
SRC=snprintf.c
|
||||||
|
OBJS=$(SRC:.c=.o)
|
||||||
|
|
||||||
|
TARGET=libMESA_snprintf.a libMESA_snprintf.so
|
||||||
|
|
||||||
|
all:$(TARGET)
|
||||||
|
cp -f $(TARGET) ../../lib
|
||||||
|
|
||||||
|
libMESA_snprintf.a:$(OBJS)
|
||||||
|
ar cqs $@ $<
|
||||||
|
|
||||||
|
libMESA_snprintf.so:$(OBJS)
|
||||||
|
$(CC) $(CFLAGS) $(LIB) -shared $< -o $@
|
||||||
|
.c.o:
|
||||||
|
|
||||||
|
clean :
|
||||||
|
rm -f $(OBJS) $(TARGET)
|
||||||
283
src/portable_snprintf/README
Normal file
283
src/portable_snprintf/README
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
|
||||||
|
snprintf.c
|
||||||
|
- a portable implementation of snprintf,
|
||||||
|
including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf
|
||||||
|
|
||||||
|
snprintf is a routine to convert numeric and string arguments to
|
||||||
|
formatted strings. It is similar to sprintf(3) provided in a system's
|
||||||
|
C library, yet it requires an additional argument - the buffer size -
|
||||||
|
and it guarantees never to store anything beyond the given buffer,
|
||||||
|
regardless of the format or arguments to be formatted. Some newer
|
||||||
|
operating systems do provide snprintf in their C library, but many do
|
||||||
|
not or do provide an inadequate (slow or idiosyncratic) version, which
|
||||||
|
calls for a portable implementation of this routine.
|
||||||
|
|
||||||
|
Author
|
||||||
|
|
||||||
|
Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
|
||||||
|
Copyright <20> 1999, Mark Martinec
|
||||||
|
|
||||||
|
Terms and conditions ...
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the Frontier Artistic License which comes with
|
||||||
|
this Kit.
|
||||||
|
|
||||||
|
Features
|
||||||
|
|
||||||
|
* careful adherence to specs regarding flags, field width and
|
||||||
|
precision;
|
||||||
|
* good performance for large string handling (large format, large
|
||||||
|
argument or large paddings). Performance is similar to system's
|
||||||
|
sprintf and in several cases significantly better (make sure you
|
||||||
|
compile with optimizations turned on, tell the compiler the code
|
||||||
|
is strict ANSI if necessary to give it more freedom for
|
||||||
|
optimizations);
|
||||||
|
* return value semantics per ISO/IEC 9899:1999 ("ISO C99");
|
||||||
|
* written in standard ISO/ANSI C - requires an ANSI C compiler.
|
||||||
|
|
||||||
|
Supported conversion specifiers and data types
|
||||||
|
|
||||||
|
This snprintf only supports the following conversion specifiers: s, c,
|
||||||
|
d, o, u, x, X, p (and synonyms: i, D, U, O - see below) with flags:
|
||||||
|
'-', '+', ' ', '0' and '#'. An asterisk is supported for field width
|
||||||
|
as well as precision.
|
||||||
|
|
||||||
|
Length modifiers 'h' (short int), 'l' (long int), and 'll' (long long
|
||||||
|
int) are supported.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
|
||||||
|
If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the
|
||||||
|
length modifier 'll' is recognized but treated the same as 'l',
|
||||||
|
which may cause argument value truncation! Defining
|
||||||
|
SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also
|
||||||
|
handles length modifier 'll'. long long int is a language extension
|
||||||
|
which may not be portable.
|
||||||
|
|
||||||
|
Conversion of numeric data (conversion specifiers d, o, u, x, X, p)
|
||||||
|
with length modifiers (none or h, l, ll) is left to the system routine
|
||||||
|
sprintf, but all handling of flags, field width and precision as well
|
||||||
|
as c and s conversions is done very carefully by this portable
|
||||||
|
routine. If a string precision (truncation) is specified (e.g. %.8s)
|
||||||
|
it is guaranteed the string beyond the specified precision will not be
|
||||||
|
referenced.
|
||||||
|
|
||||||
|
Length modifiers h, l and ll are ignored for c and s conversions (data
|
||||||
|
types wint_t and wchar_t are not supported).
|
||||||
|
|
||||||
|
The following common synonyms for conversion characters are supported:
|
||||||
|
* i is a synonym for d
|
||||||
|
* D is a synonym for ld, explicit length modifiers are ignored
|
||||||
|
* U is a synonym for lu, explicit length modifiers are ignored
|
||||||
|
* O is a synonym for lo, explicit length modifiers are ignored
|
||||||
|
|
||||||
|
The D, O and U conversion characters are nonstandard, they are
|
||||||
|
supported for backward compatibility only, and should not be used for
|
||||||
|
new code.
|
||||||
|
|
||||||
|
The following is specifically not supported:
|
||||||
|
* flag ' (thousands' grouping character) is recognized but ignored
|
||||||
|
* numeric conversion specifiers: f, e, E, g, G and synonym F, as
|
||||||
|
well as the new a and A conversion specifiers
|
||||||
|
* length modifier 'L' (long double) and 'q' (quad - use 'll'
|
||||||
|
instead)
|
||||||
|
* wide character/string conversions: lc, ls, and nonstandard
|
||||||
|
synonyms C and S
|
||||||
|
* writeback of converted string length: conversion character n
|
||||||
|
* the n$ specification for direct reference to n-th argument
|
||||||
|
* locales
|
||||||
|
|
||||||
|
It is permitted for str_m to be zero, and it is permitted to specify
|
||||||
|
NULL pointer for resulting string argument if str_m is zero (as per
|
||||||
|
ISO C99).
|
||||||
|
|
||||||
|
The return value is the number of characters which would be generated
|
||||||
|
for the given input, excluding the trailing null. If this value is
|
||||||
|
greater or equal to str_m, not all characters from the result have
|
||||||
|
been stored in str, output bytes beyond the (str_m-1) -th character
|
||||||
|
are discarded. If str_m is greater than zero it is guaranteed the
|
||||||
|
resulting string will be null-terminated.
|
||||||
|
|
||||||
|
NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1,
|
||||||
|
but is different from some older and vendor implementations, and is
|
||||||
|
also different from XPG, XSH5, SUSv2 specifications. For historical
|
||||||
|
discussion on changes in the semantics and standards of snprintf see
|
||||||
|
printf(3) man page in the Linux programmers manual.
|
||||||
|
|
||||||
|
Routines asprintf and vasprintf return a pointer (in the ptr argument)
|
||||||
|
to a buffer sufficiently large to hold the resulting string. This
|
||||||
|
pointer should be passed to free(3) to release the allocated storage
|
||||||
|
when it is no longer needed. If sufficient space cannot be allocated,
|
||||||
|
these functions will return -1 and set ptr to be a NULL pointer. These
|
||||||
|
two routines are a GNU C library extensions (glibc).
|
||||||
|
|
||||||
|
Routines asnprintf and vasnprintf are similar to asprintf and
|
||||||
|
vasprintf, yet, like snprintf and vsnprintf counterparts, will write
|
||||||
|
at most str_m-1 characters into the allocated output string, the last
|
||||||
|
character in the allocated buffer then gets the terminating null. If
|
||||||
|
the formatted string length (the return value) is greater than or
|
||||||
|
equal to the str_m argument, the resulting string was truncated and
|
||||||
|
some of the formatted characters were discarded. These routines
|
||||||
|
present a handy way to limit the amount of allocated memory to some
|
||||||
|
sane value.
|
||||||
|
|
||||||
|
Availability
|
||||||
|
|
||||||
|
http://www.ijs.si/software/snprintf/
|
||||||
|
* snprintf_1.3.tar.gz (1999-06-30), md5 sum: snprintf_1.3.tar.gz.md5
|
||||||
|
* snprintf_2.1.tar.gz (2000-07-14), md5 sum: snprintf_2.1.tar.gz.md5
|
||||||
|
* snprintf_2.2.tar.gz (2000-10-18), md5 sum: snprintf_2.2.tar.gz.md5
|
||||||
|
|
||||||
|
Mailing list
|
||||||
|
|
||||||
|
There is a very low-traffic mailing list snprintf-announce@ijs.si
|
||||||
|
where announcements about new versions will be posted as well as
|
||||||
|
warnings about threatening bugs if discovered. The posting is
|
||||||
|
restricted to snprintf developer(s).
|
||||||
|
|
||||||
|
To subscribe to (or unsubscribe from) the mailing list please visit
|
||||||
|
the list server's web page
|
||||||
|
http://mailman.ijs.si/listinfo/snprintf-announce
|
||||||
|
|
||||||
|
You can also subscribe to the list by mailing the command SUBSCRIBE
|
||||||
|
either in the subject or in the message body to the address
|
||||||
|
snprintf-announce-request@ijs.si . You will be asked for confirmation
|
||||||
|
before subscription will be effective.
|
||||||
|
|
||||||
|
The list of members is only accessible to the list administrator, so
|
||||||
|
there is no need for concern about automatic e-mail address gatherers.
|
||||||
|
|
||||||
|
Questions about the mailing list and concerns for the attention of a
|
||||||
|
person should be sent to snprintf-announce-admin@ijs.si
|
||||||
|
|
||||||
|
There is no general discussion list about portable snprintf at the
|
||||||
|
moment. Please send comments and suggestion to the author.
|
||||||
|
|
||||||
|
Revision history
|
||||||
|
|
||||||
|
Version 1.3 fixes a runaway loop problem from 1.2. Please upgrade.
|
||||||
|
|
||||||
|
1999-06-30 V1.3 Mark Martinec <mark.martinec@ijs.si>
|
||||||
|
|
||||||
|
+ fixed runaway loop (eventually crashing when str_l wraps
|
||||||
|
beyond 2^31) while copying format string without conversion
|
||||||
|
specifiers to a buffer that is too short (thanks to Edwin
|
||||||
|
Young <edwiny@autonomy.com> for spotting the problem);
|
||||||
|
+ added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) to
|
||||||
|
snprintf.h
|
||||||
|
|
||||||
|
2000-02-14 V2.0 (never released) Mark Martinec <mark.martinec@ijs.si>
|
||||||
|
|
||||||
|
+ relaxed license terms: The Artistic License now applies. You
|
||||||
|
may still apply the GNU GENERAL PUBLIC LICENSE as was
|
||||||
|
distributed with previous versions, if you prefer;
|
||||||
|
+ changed REVISION HISTORY dates to use ISO 8601 date format;
|
||||||
|
+ added vsnprintf (patch also independently proposed by Caol<6F>n
|
||||||
|
McNamara 2000-05-04, and Keith M Willenson 2000-06-01)
|
||||||
|
|
||||||
|
2000-06-27 V2.1 Mark Martinec <mark.martinec@ijs.si>
|
||||||
|
|
||||||
|
+ removed POSIX check for str_m < 1; value 0 for str_m is
|
||||||
|
allowed by ISO C99 (and GNU C library 2.1) (pointed out on
|
||||||
|
2000-05-04 by Caol<6F>n McNamara, caolan@ csn dot ul dot ie).
|
||||||
|
Besides relaxed license this change in standards adherence is
|
||||||
|
the main reason to bump up the major version number;
|
||||||
|
+ added nonstandard routines asnprintf, vasnprintf, asprintf,
|
||||||
|
vasprintf that dynamically allocate storage for the resulting
|
||||||
|
string; these routines are not compiled by default, see
|
||||||
|
comments where NEED_V?ASN?PRINTF macros are defined;
|
||||||
|
+ autoconf contributed by Caol<6F>n McNamara
|
||||||
|
|
||||||
|
2000-10-06 V2.2 Mark Martinec <mark.martinec@ijs.si>
|
||||||
|
|
||||||
|
+ BUG FIX: the %c conversion used a temporary variable that was
|
||||||
|
no longer in scope when referenced, possibly causing
|
||||||
|
incorrect resulting character;
|
||||||
|
+ BUG FIX: make precision and minimal field width unsigned to
|
||||||
|
handle huge values (2^31 <= n < 2^32) correctly; also be more
|
||||||
|
careful in the use of signed/unsigned/size_t internal
|
||||||
|
variables -- probably more careful than many vendor
|
||||||
|
implementations, but there may still be a case where huge
|
||||||
|
values of str_m, precision or minimal field could cause
|
||||||
|
incorrect behaviour;
|
||||||
|
+ use separate variables for signed/unsigned arguments, and for
|
||||||
|
short/int, long, and long long argument lengths to avoid
|
||||||
|
possible incompatibilities on certain computer architectures.
|
||||||
|
Also use separate variable arg_sign to hold sign of a numeric
|
||||||
|
argument, to make code more transparent;
|
||||||
|
+ some fiddling with zero padding and "0x" to make it Linux
|
||||||
|
compatible;
|
||||||
|
+ systematically use macros fast_memcpy and fast_memset instead
|
||||||
|
of case-by-case hand optimization; determine some breakeven
|
||||||
|
string lengths for different architectures;
|
||||||
|
+ terminology change: format -> conversion specifier, C9x ->
|
||||||
|
ISO/IEC 9899:1999 ("ISO C99"), alternative form -> alternate
|
||||||
|
form, data type modifier -> length modifier;
|
||||||
|
+ several comments rephrased and new ones added;
|
||||||
|
+ make compiler not complain about 'credits' defined but not
|
||||||
|
used;
|
||||||
|
|
||||||
|
Other implementations of snprintf
|
||||||
|
|
||||||
|
I am aware of some other (more or less) portable implementations of
|
||||||
|
snprintf. I do not claim they are free software - please refer to
|
||||||
|
their respective copyright and licensing terms. If you know of other
|
||||||
|
versions please let me know.
|
||||||
|
* a very thorough implementation (src/util_snprintf.c) by the Apache
|
||||||
|
Group distributed with the Apache web server -
|
||||||
|
http://www.apache.org/ . Does its own floating point conversions
|
||||||
|
using routines ecvt(3), fcvt(3) and gcvt(3) from the standard C
|
||||||
|
library or from the GNU libc.
|
||||||
|
This is from the code:
|
||||||
|
|
||||||
|
This software [...] was originally based on public domain software
|
||||||
|
written at the National Center for Supercomputing Applications,
|
||||||
|
University of Illinois, Urbana-Champaign.
|
||||||
|
[...] This code is based on, and used with the permission of, the
|
||||||
|
SIO stdio-replacement strx_* functions by Panos Tsirigotis
|
||||||
|
<panos@alumni.cs.colorado.edu> for xinetd.
|
||||||
|
* QCI Utilities use a modified version of snprintf from the Apache
|
||||||
|
group.
|
||||||
|
* implementations as distributed with OpenBSD, FreeBSD, and NetBSD
|
||||||
|
are all wrappers to vfprintf.c, which is derived from software
|
||||||
|
contributed to Berkeley by Chris Torek.
|
||||||
|
* implementation from Prof. Patrick Powell <papowell@sdsu.edu>,
|
||||||
|
Dept. Electrical and Computer Engineering, San Diego State
|
||||||
|
University, San Diego, CA 92182-1309, published in Bugtraq
|
||||||
|
archives for 3rd quarter (Jul-Aug) 1995. No floating point
|
||||||
|
conversions.
|
||||||
|
* Brandon Long's <blong@fiction.net> modified version of Prof.
|
||||||
|
Patrick Powell's snprintf with contributions from others. With
|
||||||
|
minimal floating point support.
|
||||||
|
* implementation (src/snprintf.c) as distributed with sendmail -
|
||||||
|
http://www.sendmail.org/ is a cleaned up Prof. Patrick Powell's
|
||||||
|
version to compile properly and to support .precision and %lx.
|
||||||
|
* implementation from Caol<6F>n McNamara available at
|
||||||
|
http://www.csn.ul.ie/~caolan/publink/snprintf-1.1.tar.gz, handles
|
||||||
|
floating point.
|
||||||
|
* implementation used by newlog (a replacement for syslog(3)) made
|
||||||
|
available by the SOS Corporation. Enabling floating point support
|
||||||
|
is a compile-time option.
|
||||||
|
* implementation by Michael Richardson <mcr@metis.milkyway.com> is
|
||||||
|
available at http://sandelman.ottawa.on.ca/SSW/snp/snp.html. It is
|
||||||
|
based on BSD44-lite's vfprintf() call, modified to function on
|
||||||
|
SunOS. Needs internal routines from the 4.4 strtod (included),
|
||||||
|
requires GCC to compile the long long (aka quad_t) portions.
|
||||||
|
* implementation from Tomi Salo <ttsalo@ssh.fi> distributed with SSH
|
||||||
|
2.0 Unix Server. Not in public domain. Floating point conversions
|
||||||
|
done by system's sprintf.
|
||||||
|
* and for completeness: my portable version described in this very
|
||||||
|
document available at http://www.ijs.si/software/snprintf/ .
|
||||||
|
|
||||||
|
In retrospect, it appears that a lot of effort was wasted by many
|
||||||
|
people for not being aware of what others are doing. Sigh.
|
||||||
|
|
||||||
|
Also of interest: The Approved Base Working Group Resolution for XSH5,
|
||||||
|
Ref: bwg98-006, Topic: snprintf.
|
||||||
|
_________________________________________________________________
|
||||||
|
|
||||||
|
mm
|
||||||
|
Last updated: 2000-10-18
|
||||||
|
|
||||||
|
Valid HTML 4.0!
|
||||||
382
src/portable_snprintf/README.html
Normal file
382
src/portable_snprintf/README.html
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rev="made" href="mailto:mark.martinec@ijs.si">
|
||||||
|
<title>
|
||||||
|
snprintf.c - a portable implementation of snprintf
|
||||||
|
(including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf)
|
||||||
|
</title>
|
||||||
|
<meta http-equiv="Content-Language" content="en">
|
||||||
|
<meta name="author" content="Mark Martinec">
|
||||||
|
<meta name="copyright" content="Copyright 2000 Mark Martinec, All Rights Reserved">
|
||||||
|
<meta name="date" content="2000-10-18">
|
||||||
|
<meta name="keywords" lang="en"
|
||||||
|
content="snprintf,portable,vsnprintf,asnprintf,vasnprintf,asprintf,vasprintf
|
||||||
|
ISO/IEC 9899:1999,ISO C99,ISO C9x,POSIX">
|
||||||
|
<style type="text/css">
|
||||||
|
<!--
|
||||||
|
body { background: white; color: black }
|
||||||
|
-->
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1><b>snprintf.c</b>
|
||||||
|
<br> - a portable implementation of snprintf,
|
||||||
|
<br><font size="+1">including
|
||||||
|
vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf</font>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p><b>snprintf</b> is a routine to convert numeric and string arguments
|
||||||
|
to formatted strings. It is similar to sprintf(3) provided in a
|
||||||
|
system's C library, yet it requires an additional argument - the buffer
|
||||||
|
size - and it guarantees never to store anything beyond the given buffer,
|
||||||
|
regardless of the format or arguments to be formatted. Some newer
|
||||||
|
operating systems do provide <b>snprintf</b> in their C library,
|
||||||
|
but many do not or do provide an inadequate (slow or idiosyncratic)
|
||||||
|
version, which calls for a portable implementation of this routine.
|
||||||
|
|
||||||
|
<h2>Author</h2>
|
||||||
|
|
||||||
|
<p><a href="http://www.ijs.si/people/mark/">Mark Martinec</a>
|
||||||
|
<<a href="mailto:mark.martinec@ijs.si">mark.martinec@ijs.si</a>>,
|
||||||
|
April 1999, June 2000
|
||||||
|
<br>Copyright © 1999, Mark Martinec
|
||||||
|
|
||||||
|
<h2>Terms and conditions ...</h2>
|
||||||
|
|
||||||
|
<p>This program is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the
|
||||||
|
<i><a href="./LICENSE.txt">Frontier Artistic License</a></i>
|
||||||
|
which comes with this Kit.
|
||||||
|
|
||||||
|
<h2>Features</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>careful adherence to specs regarding flags, field width and precision;
|
||||||
|
<li>good performance for large string handling (large format, large argument
|
||||||
|
or large paddings). Performance is similar to system's <b>sprintf</b>
|
||||||
|
and in several cases significantly better (make sure you compile with
|
||||||
|
optimizations turned on, tell the compiler the code is strict ANSI
|
||||||
|
if necessary to give it more freedom for optimizations);
|
||||||
|
<li>return value semantics per ISO/IEC 9899:1999 ("ISO C99");
|
||||||
|
<li>written in standard ISO/ANSI C - requires an ANSI C compiler.
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Supported conversion specifiers and data types</h2>
|
||||||
|
|
||||||
|
<p>This <b>snprintf</b> only supports the following conversion specifiers:
|
||||||
|
s, c, d, o, u, x, X, p (and synonyms: i, D, U, O - see below)
|
||||||
|
with flags: '-', '+', ' ', '0' and '#'.
|
||||||
|
An asterisk is supported for field width as well as precision.
|
||||||
|
|
||||||
|
<p>Length modifiers 'h' (<i>short int</i>), 'l' (<i>long int</i>),
|
||||||
|
and 'll' (<i>long long int</i>) are supported.
|
||||||
|
|
||||||
|
<p>NOTE:
|
||||||
|
<blockquote>
|
||||||
|
If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default)
|
||||||
|
the length modifier 'll' is recognized but treated the same as 'l',
|
||||||
|
which may cause argument value truncation!
|
||||||
|
Defining SNPRINTF_LONGLONG_SUPPORT requires that your system's
|
||||||
|
<b>sprintf</b> also handles length modifier 'll'.
|
||||||
|
<i>long long int</i> is a language extension which may not be portable.
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>Conversion of numeric data (conversion specifiers d, o, u, x, X, p)
|
||||||
|
with length modifiers (none or h, l, ll) is left to the system
|
||||||
|
routine <b>sprintf</b>, but all handling of flags, field width and precision
|
||||||
|
as well as c and s conversions is done very carefully by this portable routine.
|
||||||
|
If a string precision (truncation) is specified (e.g. %.8s) it is
|
||||||
|
guaranteed the string beyond the specified precision will not be referenced.
|
||||||
|
|
||||||
|
<p>Length modifiers h, l and ll are ignored for c and s conversions
|
||||||
|
(data types <i>wint_t</i> and <i>wchar_t</i> are not supported).
|
||||||
|
|
||||||
|
<p>The following common synonyms for conversion characters are supported:
|
||||||
|
<ul>
|
||||||
|
<li>i is a synonym for d
|
||||||
|
<li>D is a synonym for ld, explicit length modifiers are ignored
|
||||||
|
<li>U is a synonym for lu, explicit length modifiers are ignored
|
||||||
|
<li>O is a synonym for lo, explicit length modifiers are ignored
|
||||||
|
</ul>
|
||||||
|
The D, O and U conversion characters are nonstandard, they are supported
|
||||||
|
for backward compatibility only, and should not be used for new code.
|
||||||
|
|
||||||
|
<p>The following is specifically <b>not</b> supported:
|
||||||
|
<ul>
|
||||||
|
<li>flag ' (thousands' grouping character) is recognized but ignored
|
||||||
|
<li>numeric conversion specifiers: f, e, E, g, G and synonym F,
|
||||||
|
as well as the new a and A conversion specifiers
|
||||||
|
<li>length modifier 'L' (<i>long double</i>)
|
||||||
|
and 'q' (<i>quad</i> - use 'll' instead)
|
||||||
|
<li>wide character/string conversions: lc, ls, and nonstandard
|
||||||
|
synonyms C and S
|
||||||
|
<li>writeback of converted string length: conversion character n
|
||||||
|
<li>the n$ specification for direct reference to n-th argument
|
||||||
|
<li>locales
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>It is permitted for str_m to be zero, and it is permitted to specify NULL
|
||||||
|
pointer for resulting string argument if str_m is zero (as per ISO C99).
|
||||||
|
|
||||||
|
<p>The return value is the number of characters which would be generated
|
||||||
|
for the given input, <i>excluding</i> the trailing null. If this value
|
||||||
|
is greater or equal to str_m, not all characters from the result
|
||||||
|
have been stored in str, output bytes beyond the (str_m-1) -th character
|
||||||
|
are discarded. If str_m is greater than zero it is guaranteed
|
||||||
|
the resulting string will be null-terminated.
|
||||||
|
|
||||||
|
<p>NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1,
|
||||||
|
but is different from some older and vendor implementations,
|
||||||
|
and is also different from XPG, XSH5, SUSv2 specifications.
|
||||||
|
For historical discussion on changes in the semantics and standards
|
||||||
|
of snprintf see printf(3) man page in the Linux programmers manual.
|
||||||
|
|
||||||
|
<p>Routines asprintf and vasprintf return a pointer (in the ptr argument)
|
||||||
|
to a buffer sufficiently large to hold the resulting string. This pointer
|
||||||
|
should be passed to free(3) to release the allocated storage when it is
|
||||||
|
no longer needed. If sufficient space cannot be allocated, these functions
|
||||||
|
will return -1 and set ptr to be a NULL pointer. These two routines are a
|
||||||
|
GNU C library extensions (glibc).
|
||||||
|
|
||||||
|
<p>Routines asnprintf and vasnprintf are similar to asprintf and vasprintf,
|
||||||
|
yet, like snprintf and vsnprintf counterparts, will write at most str_m-1
|
||||||
|
characters into the allocated output string, the last character in the
|
||||||
|
allocated buffer then gets the terminating null. If the formatted string
|
||||||
|
length (the return value) is greater than or equal to the str_m argument,
|
||||||
|
the resulting string was truncated and some of the formatted characters
|
||||||
|
were discarded. These routines present a handy way to limit the amount
|
||||||
|
of allocated memory to some sane value.
|
||||||
|
|
||||||
|
<h2>Availability</h2>
|
||||||
|
|
||||||
|
<p><a href="http://www.ijs.si/software/snprintf/"
|
||||||
|
>http://www.ijs.si/software/snprintf/</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="./snprintf_1.3.tar.gz">snprintf_1.3.tar.gz</a> (1999-06-30),
|
||||||
|
md5 sum: <a href="./snprintf_1.3.tar.gz.md5">snprintf_1.3.tar.gz.md5</a>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="./snprintf_2.1.tar.gz">snprintf_2.1.tar.gz</a> (2000-07-14),
|
||||||
|
md5 sum: <a href="./snprintf_2.1.tar.gz.md5">snprintf_2.1.tar.gz.md5</a>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="./snprintf_2.2.tar.gz">snprintf_2.2.tar.gz</a> (2000-10-18),
|
||||||
|
md5 sum: <a href="./snprintf_2.2.tar.gz.md5">snprintf_2.2.tar.gz.md5</a>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Mailing list</h2>
|
||||||
|
|
||||||
|
<p>There is a very low-traffic mailing list <i>snprintf-announce@ijs.si</i>
|
||||||
|
where announcements about new versions will be posted
|
||||||
|
as well as warnings about threatening bugs if discovered.
|
||||||
|
The posting is restricted to snprintf developer(s).
|
||||||
|
|
||||||
|
<p>To subscribe to (or unsubscribe from) the mailing list
|
||||||
|
please visit the list server's web page
|
||||||
|
<a href="http://mailman.ijs.si/listinfo/snprintf-announce"
|
||||||
|
>http://mailman.ijs.si/listinfo/snprintf-announce</a>
|
||||||
|
|
||||||
|
<p>You can also subscribe to the list by mailing
|
||||||
|
the command SUBSCRIBE either in the subject or in the message body
|
||||||
|
to the address <a href="mailto:snprintf-announce-request@ijs.si"
|
||||||
|
>snprintf-announce-request@ijs.si</a> . You will be asked for
|
||||||
|
confirmation before subscription will be effective.
|
||||||
|
|
||||||
|
<p>The list of members is only accessible to the list administrator,
|
||||||
|
so there is no need for concern about automatic e-mail address gatherers.
|
||||||
|
|
||||||
|
<p>Questions about the mailing list and concerns for the attention
|
||||||
|
of a person should be sent to <a href="mailto:snprintf-announce-admin@ijs.si"
|
||||||
|
>snprintf-announce-admin@ijs.si</a>
|
||||||
|
|
||||||
|
<p>There is no <i>general</i> discussion list about portable snprintf
|
||||||
|
at the moment. Please send comments and suggestion to the author.
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Revision history</h2>
|
||||||
|
|
||||||
|
<p><b>Version 1.3 fixes a runaway loop problem from 1.2. Please upgrade.</b>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>1999-06-30 V1.3 Mark Martinec <mark.martinec@ijs.si>
|
||||||
|
<dd><ul>
|
||||||
|
<li>fixed runaway loop (eventually crashing when str_l wraps
|
||||||
|
beyond 2^31) while copying format string without
|
||||||
|
conversion specifiers to a buffer that is too short
|
||||||
|
(thanks to Edwin Young <edwiny@autonomy.com> for spotting the problem);
|
||||||
|
<li>added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) to snprintf.h
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<dt>2000-02-14 V2.0 (never released) Mark Martinec <mark.martinec@ijs.si>
|
||||||
|
<dd><ul>
|
||||||
|
<li>relaxed license terms:
|
||||||
|
<a href="./LICENSE.txt">The Artistic License</a> now applies.
|
||||||
|
You may still apply the GNU GENERAL PUBLIC LICENSE
|
||||||
|
as was distributed with previous versions, if you prefer;
|
||||||
|
<li>changed REVISION HISTORY dates to use
|
||||||
|
<a href="http://www.cl.cam.ac.uk/~mgk25/iso-time.html">ISO 8601
|
||||||
|
date format</a>;
|
||||||
|
<li>added vsnprintf (patch also independently proposed by
|
||||||
|
Caolán McNamara 2000-05-04, and Keith M Willenson 2000-06-01)
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<dt>2000-06-27 V2.1 Mark Martinec <mark.martinec@ijs.si>
|
||||||
|
<dd><ul>
|
||||||
|
<li>removed POSIX check for str_m < 1; value 0 for str_m is
|
||||||
|
allowed by ISO C99 (and GNU C library 2.1) (pointed out
|
||||||
|
on 2000-05-04 by Caolán McNamara, caolan@ csn dot ul dot ie).
|
||||||
|
Besides relaxed license this change in standards adherence
|
||||||
|
is the main reason to bump up the major version number;
|
||||||
|
<li>added nonstandard routines asnprintf, vasnprintf, asprintf,
|
||||||
|
vasprintf that dynamically allocate storage for the
|
||||||
|
resulting string; these routines are not compiled by default,
|
||||||
|
see comments where NEED_V?ASN?PRINTF macros are defined;
|
||||||
|
<li>autoconf contributed by Caolán McNamara
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<dt>2000-10-06 V2.2 Mark Martinec <mark.martinec@ijs.si>
|
||||||
|
<dd><ul>
|
||||||
|
<li><b>BUG FIX</b>: the %c conversion used a temporary variable
|
||||||
|
that was no longer in scope when referenced,
|
||||||
|
possibly causing incorrect resulting character;
|
||||||
|
<li>BUG FIX: make precision and minimal field width unsigned
|
||||||
|
to handle huge values (2^31 <= n < 2^32) correctly;
|
||||||
|
also be more careful in the use of signed/unsigned/size_t
|
||||||
|
internal variables -- probably more careful than many
|
||||||
|
vendor implementations, but there may still be a case
|
||||||
|
where huge values of str_m, precision or minimal field
|
||||||
|
could cause incorrect behaviour;
|
||||||
|
<li>use separate variables for signed/unsigned arguments,
|
||||||
|
and for short/int, long, and long long argument lengths
|
||||||
|
to avoid possible incompatibilities on certain
|
||||||
|
computer architectures. Also use separate variable
|
||||||
|
arg_sign to hold sign of a numeric argument,
|
||||||
|
to make code more transparent;
|
||||||
|
<li>some fiddling with zero padding and "0x" to make it
|
||||||
|
Linux compatible;
|
||||||
|
<li>systematically use macros fast_memcpy and fast_memset
|
||||||
|
instead of case-by-case hand optimization; determine some
|
||||||
|
breakeven string lengths for different architectures;
|
||||||
|
<li>terminology change: <i>format</i> -> <i>conversion specifier</i>,
|
||||||
|
<i>C9x</i> -> <i>ISO/IEC 9899:1999 ("ISO C99")</i>,
|
||||||
|
<i>alternative form</i> -> <i>alternate form</i>,
|
||||||
|
<i>data type modifier</i> -> <i>length modifier</i>;
|
||||||
|
<li>several comments rephrased and new ones added;
|
||||||
|
<li>make compiler not complain about 'credits' defined but
|
||||||
|
not used;
|
||||||
|
</ul>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h2>Other implementations of snprintf</h2>
|
||||||
|
|
||||||
|
<p>I am aware of some other (more or less) portable implementations
|
||||||
|
of <b>snprintf</b>. I do not claim they are free software - please refer
|
||||||
|
to their respective copyright and licensing terms.
|
||||||
|
If you know of other versions please let
|
||||||
|
<a href="http://www.ijs.si/people/mark/">me</a> know.
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>a very thorough implementation (src/util_snprintf.c)
|
||||||
|
by the Apache Group distributed with the
|
||||||
|
<a href="http://www.apache.org/">Apache web server
|
||||||
|
- http://www.apache.org/</a> .
|
||||||
|
Does its own floating point conversions using routines
|
||||||
|
ecvt(3), fcvt(3) and gcvt(3) from the standard C library
|
||||||
|
or from the GNU libc.
|
||||||
|
|
||||||
|
<br>This is from the code:
|
||||||
|
<blockquote>
|
||||||
|
This software [...] was originally based
|
||||||
|
on public domain software written at the
|
||||||
|
<a href="http://www.ncsa.uiuc.edu/ncsa.html">National Center
|
||||||
|
for Supercomputing Applications</a>, University of Illinois,
|
||||||
|
Urbana-Champaign.<br>
|
||||||
|
[...] This code is based on, and used with the permission of,
|
||||||
|
the SIO stdio-replacement strx_* functions by Panos Tsirigotis
|
||||||
|
<<a href="mailto:panos@alumni.cs.colorado.edu">panos@alumni.cs.colorado.edu</a>> for xinetd.
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<li><a href="http://www.qlue.com/downloads/c_utils_README.html">QCI
|
||||||
|
Utilities</a> use a modified version of snprintf from the Apache group.
|
||||||
|
|
||||||
|
<li>implementations as distributed with
|
||||||
|
<a href="http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/">OpenBSD</a>,
|
||||||
|
<a href="http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/stdio/">FreeBSD</a>, and
|
||||||
|
<a href="http://cvsweb.netbsd.org/cgi-bin/cvsweb.cgi/basesrc/lib/libc/stdio/">NetBSD</a>
|
||||||
|
are all wrappers to vfprintf.c, which is derived from software
|
||||||
|
contributed to Berkeley by Chris Torek.
|
||||||
|
|
||||||
|
<li>implementation from Prof. Patrick Powell
|
||||||
|
<<a href="mailto:papowell@sdsu.edu">papowell@sdsu.edu</a>>,
|
||||||
|
Dept. Electrical and Computer Engineering, San Diego State University,
|
||||||
|
San Diego, CA 92182-1309, published in
|
||||||
|
<a href="http://www.geek-girl.com/bugtraq/1995_3/0217.html">Bugtraq
|
||||||
|
archives for 3rd quarter (Jul-Aug) 1995</a>.
|
||||||
|
No floating point conversions.
|
||||||
|
|
||||||
|
<li>Brandon Long's
|
||||||
|
<<a href="mailto:blong@fiction.net">blong@fiction.net</a>>
|
||||||
|
<a href="http://www.fiction.net/~blong/programs/">modified version</a>
|
||||||
|
of Prof. Patrick Powell's snprintf with contributions from others.
|
||||||
|
With minimal floating point support.
|
||||||
|
|
||||||
|
<li>implementation (src/snprintf.c) as distributed with
|
||||||
|
<a href="http://www.sendmail.org/">sendmail - http://www.sendmail.org/</a>
|
||||||
|
is a cleaned up Prof. Patrick Powell's version
|
||||||
|
to compile properly and to support .precision and %lx.
|
||||||
|
|
||||||
|
<li>implementation from <a href="http://www.csn.ul.ie/~caolan/"
|
||||||
|
>Caolán McNamara</a> available at
|
||||||
|
<a href="http://www.csn.ul.ie/~caolan/publink/snprintf-1.1.tar.gz"
|
||||||
|
>http://www.csn.ul.ie/~caolan/publink/snprintf-1.1.tar.gz</a>,
|
||||||
|
handles floating point.
|
||||||
|
|
||||||
|
<li>implementation used by
|
||||||
|
<a href="ftp://ftp.soscorp.com/pub/sos/lib">newlog</a>
|
||||||
|
(a replacement for syslog(3)) made available by
|
||||||
|
the <a href="http://www.soscorp.com">SOS Corporation</a>.
|
||||||
|
Enabling floating point support is a compile-time option.
|
||||||
|
|
||||||
|
<li>implementation by Michael Richardson
|
||||||
|
<<a href="mailto:mcr@metis.milkyway.com">mcr@metis.milkyway.com</a>>
|
||||||
|
is available at
|
||||||
|
<a href="http://sandelman.ottawa.on.ca/SSW/snp/snp.html"
|
||||||
|
>http://sandelman.ottawa.on.ca/SSW/snp/snp.html</a>.
|
||||||
|
It is based on BSD44-lite's vfprintf() call, modified to function
|
||||||
|
on SunOS. Needs internal routines from the 4.4 strtod (included),
|
||||||
|
requires GCC to compile the long long (aka quad_t) portions.
|
||||||
|
|
||||||
|
<li>implementation from Tomi Salo
|
||||||
|
<<a href="mailto:ttsalo@ssh.fi">ttsalo@ssh.fi</a>>
|
||||||
|
distributed with
|
||||||
|
<a href="http://www.Europe.DataFellows.com/f-secure/ssh/">SSH 2.0
|
||||||
|
Unix Server</a>. Not in public domain.
|
||||||
|
Floating point conversions done by system's sprintf.
|
||||||
|
|
||||||
|
<li>and for completeness: <a href="http://www.ijs.si/people/mark/">my</a>
|
||||||
|
portable version described in this very document available at
|
||||||
|
<a href="http://www.ijs.si/software/snprintf/"
|
||||||
|
>http://www.ijs.si/software/snprintf/</a> .
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
In retrospect, it appears that a lot of effort was wasted by many
|
||||||
|
people for not being aware of what others are doing. Sigh.
|
||||||
|
|
||||||
|
<p>Also of interest:
|
||||||
|
<a href="http://www.opengroup.org/platform/resolutions/bwg98-006.html"
|
||||||
|
>The Approved Base Working Group Resolution for XSH5,
|
||||||
|
Ref: bwg98-006, Topic: snprintf</a>.
|
||||||
|
|
||||||
|
<p><hr>
|
||||||
|
<i><a href="http://www.ijs.si/people/mark/">mm</a></i>
|
||||||
|
<br>Last updated: 2000-10-18
|
||||||
|
|
||||||
|
<p><a href="http://validator.w3.org/check/referer"
|
||||||
|
><img src="/images/vh40.gif" alt="Valid HTML 4.0!"
|
||||||
|
border="0" width="88" height="31"></a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1044
src/portable_snprintf/snprintf.c
Normal file
1044
src/portable_snprintf/snprintf.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user