Revision 79ba3fe7c4ebe95ecbe9203a3fb7ac7b13c1cd88 authored by Alexander Kruppa on 28 May 2021, 16:39:08 UTC, committed by Alexander Kruppa on 28 May 2021, 16:39:08 UTC
1 parent fb3f87f
portability.h
/* Portability header file for the CADO project
Copyright 2013 Pierrick Gaudry, Alexander Kruppa,
Emmanuel Thome, Paul Zimmermann
This file is part of the CADO project.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* This header file defines macros (and perhaps static functions) to improve
* portability of the CADO code. They aim to provide a wrapper for some C99
* and POSIX functionality for systems that lack those.
*/
#ifndef CADO_PORTABILITY_H_
#define CADO_PORTABILITY_H_
#ifndef CADO_CONFIG_H_
#error cado_config.h must be included before portability.h
#endif
#include "macros.h"
#ifndef HAVE_STRDUP/*{{{*/
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
static inline char * strdup(const char * const s)
{
const size_t size = strlen(s) + 1;
char * const r = (char *) malloc(size * sizeof(char));
if (r != NULL)
memcpy(r, s, size);
return r;
}
#ifdef __cplusplus
}
#endif
#endif /* HAVE_STRDUP *//*}}}*/
#ifndef HAVE_STRNDUP/*{{{*/
/* strndup is posix-2008. providing a workalike is very easy */
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
static inline char * strndup(const char * const a, const size_t n)
{
const size_t l = strlen(a);
const size_t size = (l < n ? l : n) + 1;
char * const r = (char *) malloc(size * sizeof(char));
if (r != NULL) {
memcpy(r, a, size);
r[size] = '\0';
}
return r;
}
#ifdef __cplusplus
}
#endif
#endif /* HAVE_STRNDUP *//*}}}*/
#ifndef HAVE_STRNLEN/*{{{*/
/* strnlen is posix-2008. providing a workalike is very easy */
#ifdef __cplusplus
extern "C" {
#endif
static inline size_t strnlen (const char *s, size_t maxlen)
{
size_t ret = 0;
for (; ret < maxlen && *s; s++)
ret++;
return ret;
}
#ifdef __cplusplus
}
#endif
#endif/*}}}*/
#ifndef HAVE_STRLCPY/*{{{*/
/* strlcpy is a bsd specificity, but we find it quite handy */
/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
static inline size_t strlcpy(char *dst, const char *src, size_t size) ATTRIBUTE((__warn_unused_result__));
static inline size_t
strlcpy(char *dst, const char *src, size_t siz) ATTRIBUTE_WARN_UNUSED_RESULT;
static inline size_t
strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0) {
while (--n != 0) {
if ((*d++ = *s++) == '\0')
break;
}
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
#ifdef __cplusplus
}
#endif
#endif/*}}}*/
#ifndef HAVE_STRLCAT/*{{{*/
/* strlcat is a bsd specificity, but we find it quite handy */
/* $OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $ */
/*
* Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Appends src to string dst of size dsize (unlike strncat, dsize is the
* full size of dst, not space left). At most dsize-1 characters
* will be copied. Always NUL terminates (unless dsize <= strlen(dst)).
* Returns strlen(src) + MIN(dsize, strlen(initial dst)).
* If retval >= dsize, truncation occurred.
*/
static inline size_t
strlcat(char *dst, const char *src, size_t dsize) ATTRIBUTE_WARN_UNUSED_RESULT;
static inline size_t
strlcat(char *dst, const char *src, size_t dsize)
{
const char *odst = dst;
const char *osrc = src;
size_t n = dsize;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end. */
while (n-- != 0 && *dst != '\0')
dst++;
dlen = dst - odst;
n = dsize - dlen;
if (n-- == 0)
return(dlen + strlen(src));
while (*src != '\0') {
if (n != 0) {
*dst++ = *src;
n--;
}
src++;
}
*dst = '\0';
return(dlen + (src - osrc)); /* count does not include NUL */
}
#ifdef __cplusplus
}
#endif
#endif/*}}}*/
/* MS VS and MinGW use the MS RTL (called MSVCRT for MinGW) which does not
* know the "%zu" format, they use "%Iu" instead. On MinGW, we use wrapper
* functions that rewrite the %zu format accordingly, so the bulk of the
* code can continue to use C99 syntax.
* FIXME: looks like it's a bit of a mess. MinGW, with
* __USE_MINGW_ANSI_STDIO, claims to provide C99 things. But from reading
* the commit logs, it's not completely clear that this holds for the
* full extent of functions we want; maybe it's only *printf, and not
* *scanf.
* Second aspect (below), with C++, it seems that <cstdio> is sometimes
* #undef-ining printf, maybe to the point of thrashing the C99-compliant
* variants we've selected. Does that say that in the end we *have* to
* use substitutes for every call ?
*/
#ifdef HAVE_MINGW/*{{{*/
#include <stdio.h>
/* For C++, including cstdio too is mandatory. Not much because we want
* it, but because it does feel free to do things such as #undef fprintf,
* which of course will get in the way since we want these renamed
* (bear in mind that some side-effect may cause cstdio to be included
* well after this file, unless we want to be #include-order dependent).
*/
#ifdef __cplusplus
#include <cstdio>
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "macros.h"
static inline const char *
subst_zu(const char * const s)
{
char * const r = strdup(s);
const char * const prisiz = "Iu";
const char * const priptrdiff = "Id";
const size_t l = strlen(r);
size_t i;
ASSERT_ALWAYS(strlen(prisiz) == 2);
ASSERT_ALWAYS(strlen(priptrdiff) == 2);
ASSERT_ALWAYS(r != NULL);
for (i = 0; i + 2 < l; i++)
if (r[i] == '%' && r[i+1] == 'z' && r[i+2] == 'u') {
r[i+1] = prisiz[0];
r[i+2] = prisiz[1];
} else if (r[i] == '%' && r[i+1] == 'z' && r[i+2] == 'd') {
r[i+1] = priptrdiff[0];
r[i+2] = priptrdiff[1];
} else if (r[i] == '%' && r[i+1] == 't' && r[i+2] == 'd') {
r[i+1] = priptrdiff[0];
r[i+2] = priptrdiff[1];
}
return r;
}
static inline int
scanf_subst_zu (const char * const format, ...)
{
va_list ap;
const char * const subst_format = subst_zu (format);
int r;
va_start (ap, format);
r = vscanf (subst_format, ap);
free ((void *)subst_format);
va_end (ap);
return r;
}
static inline int
fscanf_subst_zu (FILE * const stream, const char * const format, ...)
{
va_list ap;
const char * const subst_format = subst_zu (format);
int r;
va_start (ap, format);
r = vfscanf (stream, subst_format, ap);
free ((void *)subst_format);
va_end (ap);
return r;
}
static inline int
sscanf_subst_zu (const char * const str, const char * const format, ...)
{
va_list ap;
const char * const subst_format = subst_zu (format);
int r;
va_start (ap, format);
r = vsscanf (str, subst_format, ap);
free ((void *)subst_format);
va_end (ap);
return r;
}
#define scanf scanf_subst_zu
#define fscanf fscanf_subst_zu
#define sscanf sscanf_subst_zu
static inline int
printf_subst_zu (const char * const format, ...)
{
va_list ap;
const char * const subst_format = subst_zu (format);
int r;
va_start (ap, format);
r = vprintf (subst_format, ap);
free ((void *)subst_format);
va_end (ap);
return r;
}
static inline int
fprintf_subst_zu (FILE * const stream, const char * const format, ...)
{
va_list ap;
const char * const subst_format = subst_zu (format);
int r;
va_start (ap, format);
r = vfprintf (stream, subst_format, ap);
free ((void *)subst_format);
va_end (ap);
return r;
}
#define printf printf_subst_zu
#define fprintf fprintf_subst_zu
#endif /* ifdef HAVE_MINGW *//*}}}*/
#ifndef HAVE_ASPRINTF/*{{{*/
/* Copied and improved from
* http://mingw-users.1079350.n2.nabble.com/Query-regarding-offered-alternative-to-asprintf-td6329481.html
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
static inline int
vasprintf( char ** const sptr, const char *const fmt, va_list argv )
{
int wanted = vsnprintf( *sptr = NULL, 0, fmt, argv );
if (wanted<0)
return -1;
*sptr = (char *) malloc(1 + wanted);
if (!*sptr)
return -1;
int rc = vsnprintf(*sptr, 1+wanted, fmt, argv );
return rc;
}
static inline int
asprintf( char ** const sptr, const char * const fmt, ... )
{
int retval;
va_list argv;
va_start(argv, fmt);
retval = vasprintf(sptr, fmt, argv);
va_end(argv);
return retval;
}
#ifdef __cplusplus
}
#endif
#endif /* HAVE_ASPRINTF *//*}}}*/
#ifndef HAVE_LRAND48/*{{{*/
#include <stdlib.h>
#define lrand48 rand
#define mrand48() (rand() - RAND_MAX/2)
#endif/*}}}*/
#if defined(HAVE_MINGW) && !defined(HAVE_REALPATH)/*{{{*/
#include <io.h>
#include <stdlib.h>
#include <errno.h>
/* realpath() function copied from
* http://sourceforge.net/p/mingw/patches/256/?page=0
* Its copyright notice is:
* Written by Keith Marshall <keithmarshall@users.sourceforge.net>
*
* This is free software. You may redistribute and/or modify it as you
* see fit, without restriction of copyright. */
static inline char __cdecl
*realpath( const char *__restrict__ name, char *__restrict__ resolved )
{
char *retname = NULL;
if( name == NULL )
errno = EINVAL;
else if( access( name, 4 ) == 0 )
{
if( (retname = resolved) == NULL )
{
retname = (char *) malloc( _MAX_PATH );
}
if( retname == NULL )
errno = ENOMEM;
else if( (retname = _fullpath( retname, name, _MAX_PATH )) == NULL )
errno = ENAMETOOLONG;
}
return retname;
}
#endif/*}}}*/
#if defined(HAVE_SYSCONF)/*{{{*/
#include <unistd.h>
#endif/*}}}*/
#if defined(_WIN32) || defined(_WIN64) /* mingw lacks pagesize() *//*{{{*/
#include <windows.h>
#endif
static inline long pagesize ()
{
#if defined(_WIN32) || defined(_WIN64)
/* cf http://en.wikipedia.org/wiki/Page_%28computer_memory%29 */
SYSTEM_INFO si;
GetSystemInfo(&si);
return si.dwPageSize;
#elif defined(HAVE_SYSCONF)
return sysconf (_SC_PAGESIZE);
#else
#error "Cannot determine page size"
#endif
}/*}}}*/
#ifdef HAVE_MINGW /* mingw lacks sleep() (!?!!?) *//*{{{*/
/* oh dear... */
#include <windows.h>
#define sleep(seconds) Sleep((seconds)*1000)
#endif /* HAVE_MINGW *//*}}}*/
#endif /* ifndef CADO_PORTABILITY_H_ */
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...