diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2009-09-19 09:47:30 +0300 |
---|---|---|
committer | Lasse Collin <lasse.collin@tukaani.org> | 2009-09-19 09:47:30 +0300 |
commit | e599bba4216c0edb8cc8f40adad3a6dba88685f4 (patch) | |
tree | d52c699f599e276ff65302e5854a26998da1a928 /src/common | |
parent | Fix incorrect use of "restrict". (diff) | |
download | xz-e599bba4216c0edb8cc8f40adad3a6dba88685f4.tar.xz |
Various changes.
Separate a few reusable components from XZ Utils specific
code. The reusable code is now in "tuklib" modules. A few
more could be separated still, e.g. bswap.h.
Fix some bugs in lzmainfo.
Fix physmem and cpucores code on OS/2. Thanks to Elbert Pol
for help.
Add OpenVMS support into physmem. Add a few #ifdefs to ease
building XZ Utils on OpenVMS. Thanks to Jouk Jansen for the
original patch.
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/sysdefs.h | 4 | ||||
-rw-r--r-- | src/common/tuklib_common.h | 67 | ||||
-rw-r--r-- | src/common/tuklib_config.h | 1 | ||||
-rw-r--r-- | src/common/tuklib_cpucores.c (renamed from src/common/cpucores.h) | 39 | ||||
-rw-r--r-- | src/common/tuklib_cpucores.h | 23 | ||||
-rw-r--r-- | src/common/tuklib_exit.c | 57 | ||||
-rw-r--r-- | src/common/tuklib_exit.h | 25 | ||||
-rw-r--r-- | src/common/tuklib_gettext.h | 44 | ||||
-rw-r--r-- | src/common/tuklib_open_stdxxx.c (renamed from src/common/open_stdxxx.h) | 24 | ||||
-rw-r--r-- | src/common/tuklib_open_stdxxx.h | 23 | ||||
-rw-r--r-- | src/common/tuklib_physmem.c (renamed from src/common/physmem.h) | 58 | ||||
-rw-r--r-- | src/common/tuklib_physmem.h | 28 | ||||
-rw-r--r-- | src/common/tuklib_progname.c | 50 | ||||
-rw-r--r-- | src/common/tuklib_progname.h | 32 |
14 files changed, 410 insertions, 65 deletions
diff --git a/src/common/sysdefs.h b/src/common/sysdefs.h index fbc9176a..aa8ddcc2 100644 --- a/src/common/sysdefs.h +++ b/src/common/sysdefs.h @@ -147,10 +147,6 @@ typedef unsigned char _Bool; // Macros // //////////// -#if defined(_WIN32) || defined(__MSDOS__) || defined(__OS2__) -# define DOSLIKE 1 -#endif - #undef memzero #define memzero(s, n) memset(s, 0, n) diff --git a/src/common/tuklib_common.h b/src/common/tuklib_common.h new file mode 100644 index 00000000..d2642f8b --- /dev/null +++ b/src/common/tuklib_common.h @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_common.h +/// \brief Common definitions for tuklib modules +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_COMMON_H +#define TUKLIB_COMMON_H + +// The config file may be replaced by a package-specific file. +// It should include at least stddef.h, inttypes.h, and limits.h. +#include "tuklib_config.h" + +// TUKLIB_SYMBOL_PREFIX is prefixed to all symbols exported by +// the tuklib modules. If you use a tuklib module in a library, +// you should use TUKLIB_SYMBOL_PREFIX to make sure that there +// are no symbol conflicts in case someone links your library +// into application that also uses the same tuklib module. +#ifndef TUKLIB_SYMBOL_PREFIX +# define TUKLIB_SYMBOL_PREFIX +#endif + +#define TUKLIB_CAT_X(a, b) a ## b +#define TUKLIB_CAT(a, b) TUKLIB_CAT_X(a, b) + +#ifndef TUKLIB_SYMBOL +# define TUKLIB_SYMBOL(sym) TUKLIB_CAT(TUKLIB_SYMBOL_PREFIX, sym) +#endif + +#ifndef TUKLIB_DECLS_BEGIN +# ifdef __cplusplus +# define TUKLIB_DECLS_BEGIN extern "C" { +# else +# define TUKLIB_DECLS_BEGIN +# endif +#endif + +#ifndef TUKLIB_DECLS_END +# ifdef __cplusplus +# define TUKLIB_DECLS_END } +# else +# define TUKLIB_DECLS_END +# endif +#endif + +#define TUKLIB_GNUC_REQ(major, minor) \ + (defined(__GNUC__) && defined(__GNUC_MINOR__) \ + && ((__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)) \ + || __GNUC__ > (major))) + +#if TUKLIB_GNUC_REQ(2, 5) +# define tuklib_attr_noreturn __attribute__((__noreturn__)) +#else +# define tuklib_attr_noreturn +#endif + +#if defined(_WIN32) || defined(__OS2__) || defined(__MSDOS__) +# define TUKLIB_DOSLIKE 1 +#endif + +#endif diff --git a/src/common/tuklib_config.h b/src/common/tuklib_config.h new file mode 100644 index 00000000..3fe21451 --- /dev/null +++ b/src/common/tuklib_config.h @@ -0,0 +1 @@ +#include "sysdefs.h" diff --git a/src/common/cpucores.h b/src/common/tuklib_cpucores.c index 370c3cec..0a8081ff 100644 --- a/src/common/cpucores.h +++ b/src/common/tuklib_cpucores.c @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////// // -/// \file cpucores.h -/// \brief Get the number of online CPU cores +/// \file tuklib_cpucores.c +/// \brief Get the number of CPU cores online // // Author: Lasse Collin // @@ -10,42 +10,37 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef CPUCORES_H -#define CPUCORES_H +#include "tuklib_cpucores.h" -#if defined(HAVE_CPUCORES_SYSCONF) -# include <unistd.h> - -#elif defined(HAVE_CPUCORES_SYSCTL) +#if defined(TUKLIB_CPUCORES_SYSCTL) # ifdef HAVE_SYS_PARAM_H # include <sys/param.h> # endif -# ifdef HAVE_SYS_SYSCTL_H -# include <sys/sysctl.h> -# endif +# include <sys/sysctl.h> + +#elif defined(TUKLIB_CPUCORES_SYSCONF) +# include <unistd.h> #endif -static inline uint32_t -cpucores(void) +extern uint32_t +tuklib_cpucores(void) { uint32_t ret = 0; -#if defined(HAVE_CPUCORES_SYSCONF) - const long cpus = sysconf(_SC_NPROCESSORS_ONLN); - if (cpus > 0) - ret = (uint32_t)(cpus); - -#elif defined(HAVE_CPUCORES_SYSCTL) +#if defined(TUKLIB_CPUCORES_SYSCTL) int name[2] = { CTL_HW, HW_NCPU }; int cpus; size_t cpus_size = sizeof(cpus); if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1 && cpus_size == sizeof(cpus) && cpus > 0) - ret = (uint32_t)(cpus); + ret = (uint32_t)cpus; + +#elif defined(TUKLIB_CPUCORES_SYSCONF) + const long cpus = sysconf(_SC_NPROCESSORS_ONLN); + if (cpus > 0) + ret = (uint32_t)cpus; #endif return ret; } - -#endif diff --git a/src/common/tuklib_cpucores.h b/src/common/tuklib_cpucores.h new file mode 100644 index 00000000..be1ce1c1 --- /dev/null +++ b/src/common/tuklib_cpucores.h @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_cpucores.h +/// \brief Get the number of CPU cores online +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_CPUCORES_H +#define TUKLIB_CPUCORES_H + +#include "tuklib_common.h" +TUKLIB_DECLS_BEGIN + +#define tuklib_cpucores TUKLIB_SYMBOL(tuklib_cpucores) +extern uint32_t tuklib_cpucores(void); + +TUKLIB_DECLS_END +#endif diff --git a/src/common/tuklib_exit.c b/src/common/tuklib_exit.c new file mode 100644 index 00000000..c393be64 --- /dev/null +++ b/src/common/tuklib_exit.c @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_exit.c +/// \brief Close stdout and stderr, and exit +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tuklib_common.h" + +#include <stdlib.h> +#include <stdio.h> + +#include "tuklib_gettext.h" +#include "tuklib_progname.h" +#include "tuklib_exit.h" + + +extern void +tuklib_exit(int status, int err_status, int show_error) +{ + if (status != err_status) { + // Close stdout. If something goes wrong, + // print an error message to stderr. + const int ferror_err = ferror(stdout); + const int fclose_err = fclose(stdout); + if (ferror_err || fclose_err) { + status = err_status; + + // If it was fclose() that failed, we have the reason + // in errno. If only ferror() indicated an error, + // we have no idea what the reason was. + if (show_error) + fprintf(stderr, "%s: %s: %s\n", progname, + _("Writing to standard " + "output failed"), + fclose_err ? strerror(errno) + : _("Unknown error")); + } + } + + if (status != err_status) { + // Close stderr. If something goes wrong, there's + // nothing where we could print an error message. + // Just set the exit status. + const int ferror_err = ferror(stderr); + const int fclose_err = fclose(stderr); + if (fclose_err || ferror_err) + status = err_status; + } + + exit(status); +} diff --git a/src/common/tuklib_exit.h b/src/common/tuklib_exit.h new file mode 100644 index 00000000..b11776f0 --- /dev/null +++ b/src/common/tuklib_exit.h @@ -0,0 +1,25 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_exit.h +/// \brief Close stdout and stderr, and exit +/// \note Requires tuklib_progname and tuklib_gettext modules +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_EXIT_H +#define TUKLIB_EXIT_H + +#include "tuklib_common.h" +TUKLIB_DECLS_BEGIN + +#define tuklib_exit TUKLIB_SYMBOL(tuklib_exit) +extern void tuklib_exit(int status, int err_status, int show_error) + tuklib_attr_noreturn; + +TUKLIB_DECLS_END +#endif diff --git a/src/common/tuklib_gettext.h b/src/common/tuklib_gettext.h new file mode 100644 index 00000000..24852134 --- /dev/null +++ b/src/common/tuklib_gettext.h @@ -0,0 +1,44 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_gettext.h +/// \brief Wrapper for gettext and friends +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_GETTEXT_H +#define TUKLIB_GETTEXT_H + +#include "tuklib_common.h" +#include <locale.h> + +#ifndef TUKLIB_GETTEXT +# ifdef ENABLE_NLS +# define TUKLIB_GETTEXT 1 +# else +# define TUKLIB_GETTEXT 0 +# endif +#endif + +#if TUKLIB_GETTEXT +# include <libintl.h> +# define tuklib_gettext_init(package, localedir) \ + do { \ + setlocale(LC_ALL, ""); \ + bindtextdomain(package, localedir); \ + textdomain(package); \ + } while (0) +# define _(msgid) gettext(msgid) +# define N_(msgid1, msgid2, n) ngettext(msgid1, msgid2, n) +#else +# define tuklib_gettext_init(package, localedir) \ + setlocale(LC_ALL, "") +# define _(msgid) (msgid) +# define N_(msgid1, msgid2, n) ((n) == 1 ? (msgid1) : (msgid2)) +#endif + +#endif diff --git a/src/common/open_stdxxx.h b/src/common/tuklib_open_stdxxx.c index 22300851..70c8e73d 100644 --- a/src/common/open_stdxxx.h +++ b/src/common/tuklib_open_stdxxx.c @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -/// \file open_stdxxx.h +/// \file tuklib_open_stdxxx.c /// \brief Make sure that file descriptors 0, 1, and 2 are open // // Author: Lasse Collin @@ -10,17 +10,20 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef OPEN_STDXXX_H -#define OPEN_STDXXX_H +#include "tuklib_open_stdxxx.h" -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> +#ifndef TUKLIB_DOSLIKE +# include <stdlib.h> +# include <errno.h> +# include <fcntl.h> +# include <unistd.h> +#endif -static void -open_stdxxx(int status) +extern void +tuklib_open_stdxxx(int err_status) { +#ifndef TUKLIB_DOSLIKE for (int i = 0; i <= 2; ++i) { // We use fcntl() to check if the file descriptor is open. if (fcntl(i, F_GETFD) == -1 && errno == EBADF) { @@ -38,12 +41,11 @@ open_stdxxx(int status) // may very well be non-existent. This // error should be extremely rare. (void)close(fd); - exit(status); + exit(err_status); } } } +#endif return; } - -#endif diff --git a/src/common/tuklib_open_stdxxx.h b/src/common/tuklib_open_stdxxx.h new file mode 100644 index 00000000..b9116160 --- /dev/null +++ b/src/common/tuklib_open_stdxxx.h @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_open_stdxxx.h +/// \brief Make sure that file descriptors 0, 1, and 2 are open +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_OPEN_STDXXX_H +#define TUKLIB_OPEN_STDXXX_H + +#include "tuklib_common.h" +TUKLIB_DECLS_BEGIN + +#define tuklib_open_stdxx TUKLIB_SYMBOL(tuklib_open_stdxxx) +extern void tuklib_open_stdxxx(int err_status); + +TUKLIB_DECLS_END +#endif diff --git a/src/common/physmem.h b/src/common/tuklib_physmem.c index 6ca6eafe..b2d21283 100644 --- a/src/common/physmem.h +++ b/src/common/tuklib_physmem.c @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -/// \file physmem.h +/// \file tuklib_physmem.c /// \brief Get the amount of physical memory // // Author: Lasse Collin @@ -10,12 +10,11 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef PHYSMEM_H -#define PHYSMEM_H +#include "tuklib_physmem.h" -// Test for Windows first, because we want to use Windows-specific code -// on Cygwin, which also has memory information available via sysconf(), but -// on Cygwin 1.5 and older it gives wrong results (from our point of view). +// We want to use Windows-specific code on Cygwin, which also has memory +// information available via sysconf(), but on Cygwin 1.5 and older it +// gives wrong results (from our point of view). #if defined(_WIN32) || defined(__CYGWIN__) # ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0500 @@ -29,28 +28,28 @@ #elif defined(__DJGPP__) # include <dpmi.h> -#elif defined(HAVE_PHYSMEM_SYSCONF) +#elif defined(__VMS) +# include <lib$routines.h> +# include <syidef.h> +# include <ssdef.h> + +#elif defined(TUKLIB_PHYSMEM_SYSCONF) # include <unistd.h> -#elif defined(HAVE_PHYSMEM_SYSCTL) +#elif defined(TUKLIB_PHYSMEM_SYSCTL) # ifdef HAVE_SYS_PARAM_H # include <sys/param.h> # endif -# ifdef HAVE_SYS_SYSCTL_H -# include <sys/sysctl.h> -# endif +# include <sys/sysctl.h> -#elif defined(HAVE_PHYSMEM_SYSINFO) +// This sysinfo() is Linux-specific. +#elif defined(TUKLIB_PHYSMEM_SYSINFO) # include <sys/sysinfo.h> #endif -/// \brief Get the amount of physical memory in bytes -/// -/// \return Amount of physical memory in bytes. On error, zero is -/// returned. -static inline uint64_t -physmem(void) +extern uint64_t +tuklib_physmem(void) { uint64_t ret = 0; @@ -93,11 +92,16 @@ physmem(void) __dpmi_free_mem_info meminfo; if (__dpmi_get_free_memory_information(&meminfo) == 0 && meminfo.total_number_of_physical_pages - != (unsigned long)(-1)) - ret = (uint64_t)(meminfo.total_number_of_physical_pages) - * 4096; + != (unsigned long)-1) + ret = (uint64_t)meminfo.total_number_of_physical_pages * 4096; + +#elif defined(__VMS) + int vms_mem; + int val = SYI$_MEMSIZE; + if (LIB$GETSYI(&val, &vms_mem, 0, 0, 0, 0) == SS$_NORMAL) + ret = (uint64_t)vms_mem * 8192; -#elif defined(HAVE_PHYSMEM_SYSCONF) +#elif defined(TUKLIB_PHYSMEM_SYSCONF) const long pagesize = sysconf(_SC_PAGESIZE); const long pages = sysconf(_SC_PHYS_PAGES); if (pagesize != -1 || pages != -1) @@ -106,9 +110,9 @@ physmem(void) // which may report exactly 4 GiB of RAM, and "long" // being 32-bit will overflow. Casting to uint64_t // hopefully avoids overflows in the near future. - ret = (uint64_t)(pagesize) * (uint64_t)(pages); + ret = (uint64_t)pagesize * (uint64_t)pages; -#elif defined(HAVE_PHYSMEM_SYSCTL) +#elif defined(TUKLIB_PHYSMEM_SYSCTL) int name[2] = { CTL_HW, #ifdef HW_PHYSMEM64 @@ -132,13 +136,11 @@ physmem(void) ret = mem.u32; } -#elif defined(HAVE_PHYSMEM_SYSINFO) +#elif defined(TUKLIB_PHYSMEM_SYSINFO) struct sysinfo si; if (sysinfo(&si) == 0) - ret = (uint64_t)(si.totalram) * si.mem_unit; + ret = (uint64_t)si.totalram * si.mem_unit; #endif return ret; } - -#endif diff --git a/src/common/tuklib_physmem.h b/src/common/tuklib_physmem.h new file mode 100644 index 00000000..09e2a513 --- /dev/null +++ b/src/common/tuklib_physmem.h @@ -0,0 +1,28 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_physmem.h +/// \brief Get the amount of physical memory +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_PHYSMEM_H +#define TUKLIB_PHYSMEM_H + +#include "tuklib_common.h" +TUKLIB_DECLS_BEGIN + +#define tuklib_physmem TUKLIB_SYMBOL(tuklib_physmem) +extern uint64_t tuklib_physmem(void); +///< +/// \brief Get the amount of physical memory in bytes +/// +/// \return Amount of physical memory in bytes. On error, zero is +/// returned. + +TUKLIB_DECLS_END +#endif diff --git a/src/common/tuklib_progname.c b/src/common/tuklib_progname.c new file mode 100644 index 00000000..12ac8ae1 --- /dev/null +++ b/src/common/tuklib_progname.c @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_progname.c +/// \brief Program name to be displayd in messages +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tuklib_progname.h" +#include <string.h> + + +#if !HAVE_DECL_PROGRAM_INVOCATION_NAME +char *progname = NULL; +#endif + + +extern void +tuklib_progname_init(char **argv) +{ +#ifdef TUKLIB_DOSLIKE + // On these systems, argv[0] always has the full path and .exe + // suffix even if the user just types the plain program name. + // We modify argv[0] to make it nicer to read. + + // Strip the leading path. + char *p = argv[0] + strlen(argv[0]); + while (argv[0] < p && p[-1] != '/' && p[-1] != '\\') + --p; + + argv[0] = p; + + // Strip the .exe suffix. + p = strrchr(p, '.'); + if (p != NULL) + *p = '\0'; + + // Make it lowercase. + for (p = argv[0]; *p != '\0'; ++p) + if (*p >= 'A' && *p <= 'Z') + *p = *p - 'A' + 'a'; +#endif + + progname = argv[0]; + return; +} diff --git a/src/common/tuklib_progname.h b/src/common/tuklib_progname.h new file mode 100644 index 00000000..579daa34 --- /dev/null +++ b/src/common/tuklib_progname.h @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file tuklib_progname.h +/// \brief Program name to be displayd in messages +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TUKLIB_PROGNAME_H +#define TUKLIB_PROGNAME_H + +#include "tuklib_common.h" +#include <errno.h> + +TUKLIB_DECLS_BEGIN + +#if HAVE_DECL_PROGRAM_INVOCATION_NAME +# define progname program_invocation_name +#else +# define progname TUKLIB_SYMBOL(tuklib_progname) + extern char *progname; +#endif + +#define tuklib_progname_init TUKLIB_SYMBOL(tuklib_progname_init) +extern void tuklib_progname_init(char **argv); + +TUKLIB_DECLS_END +#endif |