aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2009-09-19 09:47:30 +0300
committerLasse Collin <lasse.collin@tukaani.org>2009-09-19 09:47:30 +0300
commite599bba4216c0edb8cc8f40adad3a6dba88685f4 (patch)
treed52c699f599e276ff65302e5854a26998da1a928 /src/common
parentFix incorrect use of "restrict". (diff)
downloadxz-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.h4
-rw-r--r--src/common/tuklib_common.h67
-rw-r--r--src/common/tuklib_config.h1
-rw-r--r--src/common/tuklib_cpucores.c (renamed from src/common/cpucores.h)39
-rw-r--r--src/common/tuklib_cpucores.h23
-rw-r--r--src/common/tuklib_exit.c57
-rw-r--r--src/common/tuklib_exit.h25
-rw-r--r--src/common/tuklib_gettext.h44
-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.h23
-rw-r--r--src/common/tuklib_physmem.c (renamed from src/common/physmem.h)58
-rw-r--r--src/common/tuklib_physmem.h28
-rw-r--r--src/common/tuklib_progname.c50
-rw-r--r--src/common/tuklib_progname.h32
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