forked from KolibriOS/kolibrios
newlib: update
git-svn-id: svn://kolibrios.org@3900 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
77fa251527
commit
2a2d8df30d
@ -2,7 +2,7 @@
|
|||||||
CC = gcc
|
CC = gcc
|
||||||
|
|
||||||
CFLAGS = -c -O2 -fomit-frame-pointer -DBUILD_DLL
|
CFLAGS = -c -O2 -fomit-frame-pointer -DBUILD_DLL
|
||||||
LDFLAGS = -nostdlib -shared -s -T libcdll.lds --out-implib libcimp.a --image-base 0
|
LDFLAGS = -nostdlib -shared -s -T libcdll.lds --output-def libc.orig.def --out-implib libc.dll.a --image-base 0
|
||||||
|
|
||||||
LIBC_TOPDIR = .
|
LIBC_TOPDIR = .
|
||||||
LIBC_INCLUDES = $(LIBC_TOPDIR)/include
|
LIBC_INCLUDES = $(LIBC_TOPDIR)/include
|
||||||
@ -40,6 +40,7 @@ LIBCRT_SRCS:= \
|
|||||||
crt/start.S \
|
crt/start.S \
|
||||||
crt/chkstk.S \
|
crt/chkstk.S \
|
||||||
crt/crt3.c \
|
crt/crt3.c \
|
||||||
|
crt/pseudo-reloc.c \
|
||||||
pe/crtloader.c
|
pe/crtloader.c
|
||||||
|
|
||||||
CORE_SRCS:= \
|
CORE_SRCS:= \
|
||||||
@ -126,8 +127,7 @@ CORE_SRCS:= \
|
|||||||
time/strftime.c \
|
time/strftime.c \
|
||||||
time/time.c \
|
time/time.c \
|
||||||
time/tzlock.c \
|
time/tzlock.c \
|
||||||
time/tzvars.c \
|
time/tzvars.c
|
||||||
unpack/unpacker.asm
|
|
||||||
|
|
||||||
|
|
||||||
STDLIB_SRCS= \
|
STDLIB_SRCS= \
|
||||||
@ -177,6 +177,8 @@ STRING_SRCS= memcpy.c \
|
|||||||
memmove.c \
|
memmove.c \
|
||||||
memset.c \
|
memset.c \
|
||||||
memchr.c \
|
memchr.c \
|
||||||
|
stpcpy.c \
|
||||||
|
stpncpy.c \
|
||||||
strcat.c \
|
strcat.c \
|
||||||
strchr.c \
|
strchr.c \
|
||||||
strcmp.c \
|
strcmp.c \
|
||||||
@ -368,7 +370,10 @@ shared: $(NAME).dll libcrt.a libdll.a
|
|||||||
|
|
||||||
|
|
||||||
$(NAME).dll: $(LIB_OBJS) $(SRC_DEP) Makefile
|
$(NAME).dll: $(LIB_OBJS) $(SRC_DEP) Makefile
|
||||||
ld $(LDFLAGS) -Map libcmap -L. -o $@ $(LIB_OBJS) -lgcc
|
ld $(LDFLAGS) --exclude-symbols __chkstk,__chkstk_ms,_alloca -Map libcmap -L. -o $@ $(LIB_OBJS) -lgcc --version-script libc.ver
|
||||||
|
sed -e "s/ @[^ ]*//" libc.orig.def > libc.def
|
||||||
|
sed -f cmd1.sed libc.def > mem
|
||||||
|
sed -f cmd2.sed mem >libc.inc
|
||||||
|
|
||||||
|
|
||||||
libcrt.a: $(LIBCRT_OBJS) Makefile
|
libcrt.a: $(LIBCRT_OBJS) Makefile
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
|
|
||||||
void _pei386_runtime_relocator (void);
|
extern void _pei386_runtime_relocator (void);
|
||||||
|
|
||||||
int DllStartup(void *module, int reason);
|
|
||||||
|
|
||||||
|
|
||||||
int DllStartup(void *module, int reason)
|
int DllStartup(void *module, int reason)
|
||||||
{
|
{
|
||||||
|
@ -130,8 +130,8 @@ do_pseudo_reloc (void * start, void * end, void * base)
|
|||||||
/* Check if this is a known version. */
|
/* Check if this is a known version. */
|
||||||
if (v2_hdr->version != RP_VERSION_V2)
|
if (v2_hdr->version != RP_VERSION_V2)
|
||||||
{
|
{
|
||||||
printf(" Unknown pseudo relocation protocol version %d.\n",
|
// printf(" Unknown pseudo relocation protocol version %d.\n",
|
||||||
(int) v2_hdr->version);
|
// (int) v2_hdr->version);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,8 +176,8 @@ do_pseudo_reloc (void * start, void * end, void * base)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
reldata=0;
|
reldata=0;
|
||||||
printf(" Unknown pseudo relocation bit size %d.\n",
|
// printf(" Unknown pseudo relocation bit size %d.\n",
|
||||||
(int) (r->flags & 0xff));
|
// (int) (r->flags & 0xff));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ typedef union
|
|||||||
}ufile_t;
|
}ufile_t;
|
||||||
|
|
||||||
|
|
||||||
static inline ufile_t load_file(char *path)
|
static inline ufile_t load_file(const char *path)
|
||||||
{
|
{
|
||||||
ufile_t uf;
|
ufile_t uf;
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ typedef struct
|
|||||||
int path_len;
|
int path_len;
|
||||||
}dll_path_t;
|
}dll_path_t;
|
||||||
|
|
||||||
module_t* load_module(const char *name);
|
module_t* load_library(const char *name);
|
||||||
|
|
||||||
LIST_HEAD(path_list);
|
LIST_HEAD(path_list);
|
||||||
|
|
||||||
@ -145,14 +145,13 @@ void init_loader(void *libc_image)
|
|||||||
PIMAGE_NT_HEADERS32 nt;
|
PIMAGE_NT_HEADERS32 nt;
|
||||||
PIMAGE_EXPORT_DIRECTORY exp;
|
PIMAGE_EXPORT_DIRECTORY exp;
|
||||||
|
|
||||||
struct app_hdr *header;
|
struct app_hdr *header = NULL;
|
||||||
dll_path_t *path;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
dll_path_t *path;
|
dll_path_t *path;
|
||||||
int len;
|
int len;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
if(__appenv_size)
|
if(__appenv_size)
|
||||||
{
|
{
|
||||||
char *env;
|
char *env;
|
||||||
@ -197,8 +196,7 @@ void init_loader(void *libc_image)
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
header = (struct app_hdr*)NULL;
|
|
||||||
|
|
||||||
len = strrchr(header->path, '/') - header->path+1;
|
len = strrchr(header->path, '/') - header->path+1;
|
||||||
p = (char*)malloc(len+1);
|
p = (char*)malloc(len+1);
|
||||||
@ -212,7 +210,6 @@ void init_loader(void *libc_image)
|
|||||||
DBG("add libraries path %s\n", path->path);
|
DBG("add libraries path %s\n", path->path);
|
||||||
list_add_tail(&path->list, &path_list);
|
list_add_tail(&path->list, &path_list);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
path = (dll_path_t*)malloc(sizeof(dll_path_t));
|
path = (dll_path_t*)malloc(sizeof(dll_path_t));
|
||||||
INIT_LIST_HEAD(&path->list);
|
INIT_LIST_HEAD(&path->list);
|
||||||
@ -243,20 +240,6 @@ void init_loader(void *libc_image)
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const module_t* find_module(const char *name)
|
|
||||||
{
|
|
||||||
module_t* mod = &libc_dll;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if( !strncmp(name, mod->img_name, 16))
|
|
||||||
return mod;
|
|
||||||
mod = (module_t*)mod->list.next;
|
|
||||||
}while(mod != &libc_dll);
|
|
||||||
|
|
||||||
return load_module(name);
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void sec_copy(void *dst, void *src, size_t len)
|
static inline void sec_copy(void *dst, void *src, size_t len)
|
||||||
{
|
{
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
@ -397,7 +380,7 @@ int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp)
|
|||||||
|
|
||||||
DBG("import from %s\n",libname);
|
DBG("import from %s\n",libname);
|
||||||
|
|
||||||
api = find_module(libname);
|
api = load_library(libname);
|
||||||
if(unlikely(api == NULL))
|
if(unlikely(api == NULL))
|
||||||
{
|
{
|
||||||
printf("library %s not found\n", libname);
|
printf("library %s not found\n", libname);
|
||||||
@ -625,72 +608,110 @@ void *get_proc_address(module_t *module, char *proc_name)
|
|||||||
return function;
|
return function;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void *load_lib_internal(const char *path)
|
||||||
module_t* load_module(const char *name)
|
|
||||||
{
|
|
||||||
dll_path_t *dllpath;
|
|
||||||
|
|
||||||
char *path;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = strlen(name);
|
|
||||||
|
|
||||||
list_for_each_entry(dllpath, &path_list, list)
|
|
||||||
{
|
{
|
||||||
PIMAGE_DOS_HEADER dos;
|
PIMAGE_DOS_HEADER dos;
|
||||||
PIMAGE_NT_HEADERS32 nt;
|
PIMAGE_NT_HEADERS32 nt;
|
||||||
PIMAGE_EXPORT_DIRECTORY exp;
|
PIMAGE_EXPORT_DIRECTORY exp;
|
||||||
|
|
||||||
module_t *module;
|
|
||||||
ufile_t uf;
|
ufile_t uf;
|
||||||
void *raw_img;
|
void *raw_img;
|
||||||
size_t raw_size;
|
size_t raw_size;
|
||||||
void *img_base;
|
void *img_base = NULL;
|
||||||
|
|
||||||
path = alloca(len+dllpath->path_len+1);
|
|
||||||
memcpy(path, dllpath->path, dllpath->path_len);
|
|
||||||
|
|
||||||
memcpy(path+dllpath->path_len, name, len);
|
|
||||||
path[len+dllpath->path_len]=0;
|
|
||||||
|
|
||||||
// printf("%s %s\n", path);
|
|
||||||
|
|
||||||
uf = load_file(path);
|
uf = load_file(path);
|
||||||
raw_img = uf.data;
|
raw_img = uf.data;
|
||||||
raw_size = uf.size;
|
raw_size = uf.size;
|
||||||
|
|
||||||
if(raw_img == NULL)
|
if(raw_img == NULL)
|
||||||
continue;
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
if( validate_pe(raw_img, raw_size, 0) == 0)
|
if( validate_pe(raw_img, raw_size, 0) == 0)
|
||||||
{
|
{
|
||||||
printf("invalide module %s\n", path);
|
printf("invalide module %s\n", path);
|
||||||
user_free(raw_img);
|
user_free(raw_img);
|
||||||
continue;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
img_base = create_image(raw_img);
|
img_base = create_image(raw_img);
|
||||||
user_free(raw_img);
|
user_free(raw_img);
|
||||||
|
|
||||||
if( unlikely(img_base == NULL) )
|
if( unlikely(img_base == NULL) )
|
||||||
{
|
|
||||||
printf("cannot create image %s\n",path);
|
printf("cannot create image %s\n",path);
|
||||||
|
|
||||||
|
return img_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_t* load_library(const char *name)
|
||||||
|
{
|
||||||
|
PIMAGE_DOS_HEADER dos;
|
||||||
|
PIMAGE_NT_HEADERS32 nt;
|
||||||
|
PIMAGE_EXPORT_DIRECTORY exp;
|
||||||
|
|
||||||
|
module_t *module, *mod = &libc_dll;
|
||||||
|
dll_path_t *dllpath;
|
||||||
|
char *path;
|
||||||
|
int len;
|
||||||
|
char *libname, *tmp;
|
||||||
|
void *img_base;
|
||||||
|
|
||||||
|
|
||||||
|
/* check for already loaded libraries */
|
||||||
|
|
||||||
|
tmp = strrchr(name, '/');
|
||||||
|
libname = path = tmp != NULL ? tmp+1 : (char*)name;
|
||||||
|
|
||||||
|
// printf("path %s\n", path);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if( !strncmp(path, mod->img_name, 16))
|
||||||
|
return mod;
|
||||||
|
mod = (module_t*)mod->list.next;
|
||||||
|
}while(mod != &libc_dll);
|
||||||
|
|
||||||
|
if(name[0] == '/')
|
||||||
|
{
|
||||||
|
path = (char*)name;
|
||||||
|
img_base = load_lib_internal(path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = strlen(libname);
|
||||||
|
list_for_each_entry(dllpath, &path_list, list)
|
||||||
|
{
|
||||||
|
path = alloca(len+dllpath->path_len+1);
|
||||||
|
memcpy(path, dllpath->path, dllpath->path_len);
|
||||||
|
|
||||||
|
memcpy(path+dllpath->path_len, libname, len);
|
||||||
|
path[len+dllpath->path_len]=0;
|
||||||
|
|
||||||
|
printf("%s\n", path);
|
||||||
|
|
||||||
|
img_base = load_lib_internal(path);
|
||||||
|
|
||||||
|
if( unlikely(img_base == NULL) )
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if( unlikely(img_base == NULL) )
|
||||||
|
{
|
||||||
|
printf("unable to load %s\n", name);
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
|
||||||
module = (module_t*)malloc(sizeof(module_t));
|
module = (module_t*)malloc(sizeof(module_t));
|
||||||
|
|
||||||
if(unlikely(module == NULL))
|
if(unlikely(module == NULL))
|
||||||
{
|
{
|
||||||
printf("%s epic fail: no enough memory\n",__FUNCTION__);
|
printf("%s epic fail: no enough memory\n",__FUNCTION__);
|
||||||
user_free(img_base);
|
goto err1;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_LIST_HEAD(&module->list);
|
INIT_LIST_HEAD(&module->list);
|
||||||
|
|
||||||
module->img_name = strdup(name);
|
module->img_name = strdup(libname);
|
||||||
module->img_path = strdup(path);
|
module->img_path = strdup(path);
|
||||||
module->start = img_base;
|
module->start = img_base;
|
||||||
module->entry = get_entry_point(img_base);
|
module->entry = get_entry_point(img_base);
|
||||||
@ -719,16 +740,27 @@ module_t* load_module(const char *name)
|
|||||||
nt->OptionalHeader.DataDirectory[1].VirtualAddress);
|
nt->OptionalHeader.DataDirectory[1].VirtualAddress);
|
||||||
|
|
||||||
if(link_image(img_base, imp) == 0)
|
if(link_image(img_base, imp) == 0)
|
||||||
return NULL;
|
goto err2;
|
||||||
|
|
||||||
dll_startup = get_proc_address(module, "DllStartup");
|
dll_startup = get_proc_address(module, "DllStartup");
|
||||||
if( dll_startup )
|
if( dll_startup )
|
||||||
|
{
|
||||||
if( 0 == dll_startup(module, 1))
|
if( 0 == dll_startup(module, 1))
|
||||||
return NULL;
|
goto err2;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
};
|
|
||||||
|
err2:
|
||||||
|
list_del(&module->list);
|
||||||
|
free(module->img_name);
|
||||||
|
free(module->img_path);
|
||||||
|
free(module);
|
||||||
|
err1:
|
||||||
|
user_free(img_base);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
91
programs/develop/libraries/newlib/string/stpcpy.c
Normal file
91
programs/develop/libraries/newlib/string/stpcpy.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
FUNCTION
|
||||||
|
<<stpcpy>>---copy string returning a pointer to its end
|
||||||
|
|
||||||
|
INDEX
|
||||||
|
stpcpy
|
||||||
|
|
||||||
|
ANSI_SYNOPSIS
|
||||||
|
#include <string.h>
|
||||||
|
char *stpcpy(char *<[dst]>, const char *<[src]>);
|
||||||
|
|
||||||
|
TRAD_SYNOPSIS
|
||||||
|
#include <string.h>
|
||||||
|
char *stpcpy(<[dst]>, <[src]>)
|
||||||
|
char *<[dst]>;
|
||||||
|
char *<[src]>;
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
<<stpcpy>> copies the string pointed to by <[src]>
|
||||||
|
(including the terminating null character) to the array
|
||||||
|
pointed to by <[dst]>.
|
||||||
|
|
||||||
|
RETURNS
|
||||||
|
This function returns a pointer to the end of the destination string,
|
||||||
|
thus pointing to the trailing '\0'.
|
||||||
|
|
||||||
|
PORTABILITY
|
||||||
|
<<stpcpy>> is a GNU extension, candidate for inclusion into POSIX/SUSv4.
|
||||||
|
|
||||||
|
<<stpcpy>> requires no supporting OS subroutines.
|
||||||
|
|
||||||
|
QUICKREF
|
||||||
|
stpcpy gnu
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
/*SUPPRESS 560*/
|
||||||
|
/*SUPPRESS 530*/
|
||||||
|
|
||||||
|
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
|
||||||
|
#define UNALIGNED(X, Y) \
|
||||||
|
(((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
|
||||||
|
|
||||||
|
#if LONG_MAX == 2147483647L
|
||||||
|
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
|
||||||
|
#else
|
||||||
|
#if LONG_MAX == 9223372036854775807L
|
||||||
|
/* Nonzero if X (a long int) contains a NULL byte. */
|
||||||
|
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
|
||||||
|
#else
|
||||||
|
#error long int is not a 32bit or 64bit type.
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DETECTNULL
|
||||||
|
#error long int is not a 32bit or 64bit byte
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char*
|
||||||
|
_DEFUN (stpcpy, (dst, src),
|
||||||
|
char *dst _AND
|
||||||
|
_CONST char *src)
|
||||||
|
{
|
||||||
|
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
|
||||||
|
long *aligned_dst;
|
||||||
|
_CONST long *aligned_src;
|
||||||
|
|
||||||
|
/* If SRC or DEST is unaligned, then copy bytes. */
|
||||||
|
if (!UNALIGNED (src, dst))
|
||||||
|
{
|
||||||
|
aligned_dst = (long*)dst;
|
||||||
|
aligned_src = (long*)src;
|
||||||
|
|
||||||
|
/* SRC and DEST are both "long int" aligned, try to do "long int"
|
||||||
|
sized copies. */
|
||||||
|
while (!DETECTNULL(*aligned_src))
|
||||||
|
{
|
||||||
|
*aligned_dst++ = *aligned_src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = (char*)aligned_dst;
|
||||||
|
src = (char*)aligned_src;
|
||||||
|
}
|
||||||
|
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||||
|
|
||||||
|
while ((*dst++ = *src++))
|
||||||
|
;
|
||||||
|
return --dst;
|
||||||
|
}
|
114
programs/develop/libraries/newlib/string/stpncpy.c
Normal file
114
programs/develop/libraries/newlib/string/stpncpy.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
FUNCTION
|
||||||
|
<<stpncpy>>---counted copy string returning a pointer to its end
|
||||||
|
|
||||||
|
INDEX
|
||||||
|
stpncpy
|
||||||
|
|
||||||
|
ANSI_SYNOPSIS
|
||||||
|
#include <string.h>
|
||||||
|
char *stpncpy(char *<[dst]>, const char *<[src]>, size_t <[length]>);
|
||||||
|
|
||||||
|
TRAD_SYNOPSIS
|
||||||
|
#include <string.h>
|
||||||
|
char *stpncpy(<[dst]>, <[src]>, <[length]>)
|
||||||
|
char *<[dst]>;
|
||||||
|
char *<[src]>;
|
||||||
|
size_t <[length]>;
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
<<stpncpy>> copies not more than <[length]> characters from the
|
||||||
|
the string pointed to by <[src]> (including the terminating
|
||||||
|
null character) to the array pointed to by <[dst]>. If the
|
||||||
|
string pointed to by <[src]> is shorter than <[length]>
|
||||||
|
characters, null characters are appended to the destination
|
||||||
|
array until a total of <[length]> characters have been
|
||||||
|
written.
|
||||||
|
|
||||||
|
RETURNS
|
||||||
|
This function returns a pointer to the end of the destination string,
|
||||||
|
thus pointing to the trailing '\0', or, if the destination string is
|
||||||
|
not null-terminated, pointing to dst + n.
|
||||||
|
|
||||||
|
PORTABILITY
|
||||||
|
<<stpncpy>> is a GNU extension, candidate for inclusion into POSIX/SUSv4.
|
||||||
|
|
||||||
|
<<stpncpy>> requires no supporting OS subroutines.
|
||||||
|
|
||||||
|
QUICKREF
|
||||||
|
stpncpy gnu
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
/*SUPPRESS 560*/
|
||||||
|
/*SUPPRESS 530*/
|
||||||
|
|
||||||
|
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
|
||||||
|
#define UNALIGNED(X, Y) \
|
||||||
|
(((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
|
||||||
|
|
||||||
|
#if LONG_MAX == 2147483647L
|
||||||
|
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
|
||||||
|
#else
|
||||||
|
#if LONG_MAX == 9223372036854775807L
|
||||||
|
/* Nonzero if X (a long int) contains a NULL byte. */
|
||||||
|
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
|
||||||
|
#else
|
||||||
|
#error long int is not a 32bit or 64bit type.
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DETECTNULL
|
||||||
|
#error long int is not a 32bit or 64bit byte
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TOO_SMALL(LEN) ((LEN) < sizeof (long))
|
||||||
|
|
||||||
|
char *
|
||||||
|
_DEFUN (stpncpy, (dst, src),
|
||||||
|
char *dst _AND
|
||||||
|
_CONST char *src _AND
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
char *ret = NULL;
|
||||||
|
|
||||||
|
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
|
||||||
|
long *aligned_dst;
|
||||||
|
_CONST long *aligned_src;
|
||||||
|
|
||||||
|
/* If SRC and DEST is aligned and count large enough, then copy words. */
|
||||||
|
if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
|
||||||
|
{
|
||||||
|
aligned_dst = (long*)dst;
|
||||||
|
aligned_src = (long*)src;
|
||||||
|
|
||||||
|
/* SRC and DEST are both "long int" aligned, try to do "long int"
|
||||||
|
sized copies. */
|
||||||
|
while (count >= sizeof (long int) && !DETECTNULL(*aligned_src))
|
||||||
|
{
|
||||||
|
count -= sizeof (long int);
|
||||||
|
*aligned_dst++ = *aligned_src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = (char*)aligned_dst;
|
||||||
|
src = (char*)aligned_src;
|
||||||
|
}
|
||||||
|
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||||
|
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
--count;
|
||||||
|
if ((*dst++ = *src++) == '\0')
|
||||||
|
{
|
||||||
|
ret = dst - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count-- > 0)
|
||||||
|
*dst++ = '\0';
|
||||||
|
|
||||||
|
return ret ? ret : dst;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user