aboutsummaryrefslogtreecommitdiffstats
path: root/test/monniaux/glpk-4.65/src/env
diff options
context:
space:
mode:
Diffstat (limited to 'test/monniaux/glpk-4.65/src/env')
-rw-r--r--test/monniaux/glpk-4.65/src/env/alloc.c252
-rw-r--r--test/monniaux/glpk-4.65/src/env/dlsup.c167
-rw-r--r--test/monniaux/glpk-4.65/src/env/env.c316
-rw-r--r--test/monniaux/glpk-4.65/src/env/env.h274
-rw-r--r--test/monniaux/glpk-4.65/src/env/error.c200
-rw-r--r--test/monniaux/glpk-4.65/src/env/stdc.c98
-rw-r--r--test/monniaux/glpk-4.65/src/env/stdc.h73
-rw-r--r--test/monniaux/glpk-4.65/src/env/stdout.c262
-rw-r--r--test/monniaux/glpk-4.65/src/env/stream.c517
-rw-r--r--test/monniaux/glpk-4.65/src/env/time.c150
-rw-r--r--test/monniaux/glpk-4.65/src/env/tls.c128
11 files changed, 2437 insertions, 0 deletions
diff --git a/test/monniaux/glpk-4.65/src/env/alloc.c b/test/monniaux/glpk-4.65/src/env/alloc.c
new file mode 100644
index 00000000..8e2d613d
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/alloc.c
@@ -0,0 +1,252 @@
+/* alloc.c (dynamic memory allocation) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+
+#define ALIGN 16
+/* some processors need data to be properly aligned, so this macro
+ * defines the alignment boundary, in bytes, provided by glpk memory
+ * allocation routines; looks like 16-byte alignment boundary is
+ * sufficient for all 32- and 64-bit platforms (8-byte boundary is not
+ * sufficient for some 64-bit platforms because of jmp_buf) */
+
+#define MBD_SIZE (((sizeof(MBD) + (ALIGN - 1)) / ALIGN) * ALIGN)
+/* size of memory block descriptor, in bytes, rounded up to multiple
+ * of the alignment boundary */
+
+/***********************************************************************
+* dma - dynamic memory allocation (basic routine)
+*
+* This routine performs dynamic memory allocation. It is similar to
+* the standard realloc function, however, it provides every allocated
+* memory block with a descriptor, which is used for sanity checks on
+* reallocating/freeing previously allocated memory blocks as well as
+* for book-keeping the memory usage statistics. */
+
+static void *dma(const char *func, void *ptr, size_t size)
+{ ENV *env = get_env_ptr();
+ MBD *mbd;
+ if (ptr == NULL)
+ { /* new memory block will be allocated */
+ mbd = NULL;
+ }
+ else
+ { /* allocated memory block will be reallocated or freed */
+ /* get pointer to the block descriptor */
+ mbd = (MBD *)((char *)ptr - MBD_SIZE);
+ /* make sure that the block descriptor is valid */
+ if (mbd->self != mbd)
+ xerror("%s: ptr = %p; invalid pointer\n", func, ptr);
+ /* remove the block from the linked list */
+ mbd->self = NULL;
+ if (mbd->prev == NULL)
+ env->mem_ptr = mbd->next;
+ else
+ mbd->prev->next = mbd->next;
+ if (mbd->next == NULL)
+ ;
+ else
+ mbd->next->prev = mbd->prev;
+ /* decrease usage counts */
+ if (!(env->mem_count >= 1 && env->mem_total >= mbd->size))
+ xerror("%s: memory allocation error\n", func);
+ env->mem_count--;
+ env->mem_total -= mbd->size;
+ if (size == 0)
+ { /* free the memory block */
+ free(mbd);
+ return NULL;
+ }
+ }
+ /* allocate/reallocate memory block */
+ if (size > SIZE_T_MAX - MBD_SIZE)
+ xerror("%s: block too large\n", func);
+ size += MBD_SIZE;
+ if (size > env->mem_limit - env->mem_total)
+ xerror("%s: memory allocation limit exceeded\n", func);
+ if (env->mem_count == INT_MAX)
+ xerror("%s: too many memory blocks allocated\n", func);
+ mbd = (mbd == NULL ? malloc(size) : realloc(mbd, size));
+ if (mbd == NULL)
+ xerror("%s: no memory available\n", func);
+ /* setup the block descriptor */
+ mbd->size = size;
+ mbd->self = mbd;
+ mbd->prev = NULL;
+ mbd->next = env->mem_ptr;
+ /* add the block to the beginning of the linked list */
+ if (mbd->next != NULL)
+ mbd->next->prev = mbd;
+ env->mem_ptr = mbd;
+ /* increase usage counts */
+ env->mem_count++;
+ if (env->mem_cpeak < env->mem_count)
+ env->mem_cpeak = env->mem_count;
+ env->mem_total += size;
+ if (env->mem_tpeak < env->mem_total)
+ env->mem_tpeak = env->mem_total;
+ return (char *)mbd + MBD_SIZE;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_alloc - allocate memory block
+*
+* SYNOPSIS
+*
+* void *glp_alloc(int n, int size);
+*
+* DESCRIPTION
+*
+* The routine glp_alloc allocates a memory block of n * size bytes
+* long.
+*
+* Note that being allocated the memory block contains arbitrary data
+* (not binary zeros!).
+*
+* RETURNS
+*
+* The routine glp_alloc returns a pointer to the block allocated.
+* To free this block the routine glp_free (not free!) must be used. */
+
+void *glp_alloc(int n, int size)
+{ if (n < 1)
+ xerror("glp_alloc: n = %d; invalid parameter\n", n);
+ if (size < 1)
+ xerror("glp_alloc: size = %d; invalid parameter\n", size);
+ if ((size_t)n > SIZE_T_MAX / (size_t)size)
+ xerror("glp_alloc: n = %d, size = %d; block too large\n",
+ n, size);
+ return dma("glp_alloc", NULL, (size_t)n * (size_t)size);
+}
+
+/**********************************************************************/
+
+void *glp_realloc(void *ptr, int n, int size)
+{ /* reallocate memory block */
+ if (ptr == NULL)
+ xerror("glp_realloc: ptr = %p; invalid pointer\n", ptr);
+ if (n < 1)
+ xerror("glp_realloc: n = %d; invalid parameter\n", n);
+ if (size < 1)
+ xerror("glp_realloc: size = %d; invalid parameter\n", size);
+ if ((size_t)n > SIZE_T_MAX / (size_t)size)
+ xerror("glp_realloc: n = %d, size = %d; block too large\n",
+ n, size);
+ return dma("glp_realloc", ptr, (size_t)n * (size_t)size);
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_free - free (deallocate) memory block
+*
+* SYNOPSIS
+*
+* void glp_free(void *ptr);
+*
+* DESCRIPTION
+*
+* The routine glp_free frees (deallocates) a memory block pointed to
+* by ptr, which was previuosly allocated by the routine glp_alloc or
+* reallocated by the routine glp_realloc. */
+
+void glp_free(void *ptr)
+{ if (ptr == NULL)
+ xerror("glp_free: ptr = %p; invalid pointer\n", ptr);
+ dma("glp_free", ptr, 0);
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_mem_limit - set memory usage limit
+*
+* SYNOPSIS
+*
+* void glp_mem_limit(int limit);
+*
+* DESCRIPTION
+*
+* The routine glp_mem_limit limits the amount of memory available for
+* dynamic allocation (in GLPK routines) to limit megabytes. */
+
+void glp_mem_limit(int limit)
+{ ENV *env = get_env_ptr();
+ if (limit < 1)
+ xerror("glp_mem_limit: limit = %d; invalid parameter\n",
+ limit);
+ if ((size_t)limit <= (SIZE_T_MAX >> 20))
+ env->mem_limit = (size_t)limit << 20;
+ else
+ env->mem_limit = SIZE_T_MAX;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_mem_usage - get memory usage information
+*
+* SYNOPSIS
+*
+* void glp_mem_usage(int *count, int *cpeak, size_t *total,
+* size_t *tpeak);
+*
+* DESCRIPTION
+*
+* The routine glp_mem_usage reports some information about utilization
+* of the memory by GLPK routines. Information is stored to locations
+* specified by corresponding parameters (see below). Any parameter can
+* be specified as NULL, in which case its value is not stored.
+*
+* *count is the number of the memory blocks currently allocated by the
+* routines glp_malloc and glp_calloc (one call to glp_malloc or
+* glp_calloc results in allocating one memory block).
+*
+* *cpeak is the peak value of *count reached since the initialization
+* of the GLPK library environment.
+*
+* *total is the total amount, in bytes, of the memory blocks currently
+* allocated by the routines glp_malloc and glp_calloc.
+*
+* *tpeak is the peak value of *total reached since the initialization
+* of the GLPK library envirionment. */
+
+void glp_mem_usage(int *count, int *cpeak, size_t *total,
+ size_t *tpeak)
+{ ENV *env = get_env_ptr();
+ if (count != NULL)
+ *count = env->mem_count;
+ if (cpeak != NULL)
+ *cpeak = env->mem_cpeak;
+ if (total != NULL)
+ *total = env->mem_total;
+ if (tpeak != NULL)
+ *tpeak = env->mem_tpeak;
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/dlsup.c b/test/monniaux/glpk-4.65/src/env/dlsup.c
new file mode 100644
index 00000000..54c56c6d
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/dlsup.c
@@ -0,0 +1,167 @@
+/* dlsup.c (dynamic linking support) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2008-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "env.h"
+
+/* GNU version ********************************************************/
+
+#if defined(HAVE_LTDL)
+
+#include <ltdl.h>
+
+void *xdlopen(const char *module)
+{ /* open dynamically linked library */
+ void *h = NULL;
+ if (lt_dlinit() != 0)
+ { put_err_msg(lt_dlerror());
+ goto done;
+ }
+ h = lt_dlopen(module);
+ if (h == NULL)
+ { put_err_msg(lt_dlerror());
+ if (lt_dlexit() != 0)
+ xerror("xdlopen: %s\n", lt_dlerror());
+ }
+done: return h;
+}
+
+void *xdlsym(void *h, const char *symbol)
+{ /* obtain address of symbol from dynamically linked library */
+ void *ptr;
+ xassert(h != NULL);
+ ptr = lt_dlsym(h, symbol);
+ if (ptr == NULL)
+ xerror("xdlsym: %s: %s\n", symbol, lt_dlerror());
+ return ptr;
+}
+
+void xdlclose(void *h)
+{ /* close dynamically linked library */
+ xassert(h != NULL);
+ if (lt_dlclose(h) != 0)
+ xerror("xdlclose: %s\n", lt_dlerror());
+ if (lt_dlexit() != 0)
+ xerror("xdlclose: %s\n", lt_dlerror());
+ return;
+}
+
+/* POSIX version ******************************************************/
+
+#elif defined(HAVE_DLFCN)
+
+#include <dlfcn.h>
+
+void *xdlopen(const char *module)
+{ /* open dynamically linked library */
+ void *h;
+ h = dlopen(module, RTLD_NOW);
+ if (h == NULL)
+ put_err_msg(dlerror());
+ return h;
+}
+
+void *xdlsym(void *h, const char *symbol)
+{ /* obtain address of symbol from dynamically linked library */
+ void *ptr;
+ xassert(h != NULL);
+ ptr = dlsym(h, symbol);
+ if (ptr == NULL)
+ xerror("xdlsym: %s: %s\n", symbol, dlerror());
+ return ptr;
+}
+
+void xdlclose(void *h)
+{ /* close dynamically linked library */
+ xassert(h != NULL);
+ if (dlclose(h) != 0)
+ xerror("xdlclose: %s\n", dlerror());
+ return;
+}
+
+/* MS Windows version *************************************************/
+
+#elif defined(__WOE__)
+
+#include <windows.h>
+
+void *xdlopen(const char *module)
+{ /* open dynamically linked library */
+ void *h;
+ h = LoadLibrary(module);
+ if (h == NULL)
+ { char msg[20];
+ sprintf(msg, "Error %d", GetLastError());
+ put_err_msg(msg);
+ }
+ return h;
+}
+
+void *xdlsym(void *h, const char *symbol)
+{ /* obtain address of symbol from dynamically linked library */
+ void *ptr;
+ xassert(h != NULL);
+ ptr = GetProcAddress(h, symbol);
+ if (ptr == NULL)
+ xerror("xdlsym: %s: Error %d\n", symbol, GetLastError());
+ return ptr;
+}
+
+void xdlclose(void *h)
+{ /* close dynamically linked library */
+ xassert(h != NULL);
+ if (!FreeLibrary(h))
+ xerror("xdlclose: Error %d\n", GetLastError());
+ return;
+}
+
+/* NULL version *******************************************************/
+
+#else
+
+void *xdlopen(const char *module)
+{ /* open dynamically linked library */
+ xassert(module == module);
+ put_err_msg("Shared libraries not supported");
+ return NULL;
+}
+
+void *xdlsym(void *h, const char *symbol)
+{ /* obtain address of symbol from dynamically linked library */
+ xassert(h != h);
+ xassert(symbol != symbol);
+ return NULL;
+}
+
+void xdlclose(void *h)
+{ /* close dynamically linked library */
+ xassert(h != h);
+ return;
+}
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/env.c b/test/monniaux/glpk-4.65/src/env/env.c
new file mode 100644
index 00000000..5b901f35
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/env.c
@@ -0,0 +1,316 @@
+/* env.c (GLPK environment initialization/termination) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "glpk.h"
+#include "env.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_init_env - initialize GLPK environment
+*
+* SYNOPSIS
+*
+* int glp_init_env(void);
+*
+* DESCRIPTION
+*
+* The routine glp_init_env initializes the GLPK environment. Normally
+* the application program does not need to call this routine, because
+* it is called automatically on the first call to any API routine.
+*
+* RETURNS
+*
+* The routine glp_init_env returns one of the following codes:
+*
+* 0 - initialization successful;
+* 1 - environment has been already initialized;
+* 2 - initialization failed (insufficient memory);
+* 3 - initialization failed (unsupported programming model). */
+
+int glp_init_env(void)
+{ ENV *env;
+ int ok;
+ /* check if the programming model is supported */
+ ok = (CHAR_BIT == 8 && sizeof(char) == 1 &&
+ sizeof(short) == 2 && sizeof(int) == 4 &&
+ (sizeof(void *) == 4 || sizeof(void *) == 8));
+ if (!ok)
+ return 3;
+ /* check if the environment is already initialized */
+ if (tls_get_ptr() != NULL)
+ return 1;
+ /* allocate and initialize the environment block */
+ env = malloc(sizeof(ENV));
+ if (env == NULL)
+ return 2;
+ memset(env, 0, sizeof(ENV));
+#if 0 /* 14/I-2017 */
+ sprintf(env->version, "%d.%d",
+ GLP_MAJOR_VERSION, GLP_MINOR_VERSION);
+#endif
+ env->self = env;
+ env->term_buf = malloc(TBUF_SIZE);
+ if (env->term_buf == NULL)
+ { free(env);
+ return 2;
+ }
+ env->term_out = GLP_ON;
+ env->term_hook = NULL;
+ env->term_info = NULL;
+ env->tee_file = NULL;
+#if 1 /* 23/XI-2015 */
+ env->err_st = 0;
+#endif
+ env->err_file = NULL;
+ env->err_line = 0;
+ env->err_hook = NULL;
+ env->err_info = NULL;
+ env->err_buf = malloc(EBUF_SIZE);
+ if (env->err_buf == NULL)
+ { free(env->term_buf);
+ free(env);
+ return 2;
+ }
+ env->err_buf[0] = '\0';
+ env->mem_limit = SIZE_T_MAX;
+ env->mem_ptr = NULL;
+ env->mem_count = env->mem_cpeak = 0;
+ env->mem_total = env->mem_tpeak = 0;
+#if 1 /* 23/XI-2015 */
+ env->gmp_pool = NULL;
+ env->gmp_size = 0;
+ env->gmp_work = NULL;
+#endif
+ env->h_odbc = env->h_mysql = NULL;
+ /* save pointer to the environment block */
+ tls_set_ptr(env);
+ /* initialization successful */
+ return 0;
+}
+
+/***********************************************************************
+* NAME
+*
+* get_env_ptr - retrieve pointer to environment block
+*
+* SYNOPSIS
+*
+* #include "env.h"
+* ENV *get_env_ptr(void);
+*
+* DESCRIPTION
+*
+* The routine get_env_ptr retrieves and returns a pointer to the GLPK
+* environment block.
+*
+* If the GLPK environment has not been initialized yet, the routine
+* performs initialization. If initialization fails, the routine prints
+* an error message to stderr and terminates the program.
+*
+* RETURNS
+*
+* The routine returns a pointer to the environment block. */
+
+ENV *get_env_ptr(void)
+{ ENV *env = tls_get_ptr();
+ /* check if the environment has been initialized */
+ if (env == NULL)
+ { /* not initialized yet; perform initialization */
+ if (glp_init_env() != 0)
+ { /* initialization failed; display an error message */
+ fprintf(stderr, "GLPK initialization failed\n");
+ fflush(stderr);
+ /* and abnormally terminate the program */
+ abort();
+ }
+ /* initialization successful; retrieve the pointer */
+ env = tls_get_ptr();
+ }
+ /* check if the environment block is valid */
+ if (env->self != env)
+ { fprintf(stderr, "Invalid GLPK environment\n");
+ fflush(stderr);
+ abort();
+ }
+ return env;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_version - determine library version
+*
+* SYNOPSIS
+*
+* const char *glp_version(void);
+*
+* RETURNS
+*
+* The routine glp_version returns a pointer to a null-terminated
+* character string, which specifies the version of the GLPK library in
+* the form "X.Y", where X is the major version number, and Y is the
+* minor version number, for example, "4.16". */
+
+#define str(s) # s
+#define xstr(s) str(s)
+
+const char *glp_version(void)
+#if 0 /* 14/I-2017 */
+{ ENV *env = get_env_ptr();
+ return env->version;
+}
+#else /* suggested by Heinrich */
+{ return
+ xstr(GLP_MAJOR_VERSION) "." xstr(GLP_MINOR_VERSION);
+}
+#endif
+
+/***********************************************************************
+* NAME
+*
+* glp_config - determine library configuration
+*
+* SYNOPSIS
+*
+* const char *glp_config(const char *option);
+*
+* DESCRIPTION
+*
+* The routine glp_config determines some options which were specified
+* on configuring the GLPK library.
+*
+* RETURNS
+*
+* The routine glp_config returns a pointer to a null-terminating
+* string depending on the option inquired.
+*
+* For option = "TLS" the routine returns the thread local storage
+* class specifier used (e.g. "_Thread_local") if the GLPK library was
+* configured to run in multi-threaded environment, or NULL otherwise.
+*
+* For option = "ODBC_DLNAME" the routine returns the name of ODBC
+* shared library if this option was enabled, or NULL otherwise.
+*
+* For option = "MYSQL_DLNAME" the routine returns the name of MySQL
+* shared library if this option was enabled, or NULL otherwise. */
+
+const char *glp_config(const char *option)
+{ const char *s;
+ if (strcmp(option, "TLS") == 0)
+#ifndef TLS
+ s = NULL;
+#else
+ s = xstr(TLS);
+#endif
+ else if (strcmp(option, "ODBC_DLNAME") == 0)
+#ifndef ODBC_DLNAME
+ s = NULL;
+#else
+ s = ODBC_DLNAME;
+#endif
+ else if (strcmp(option, "MYSQL_DLNAME") == 0)
+#ifndef MYSQL_DLNAME
+ s = NULL;
+#else
+ s = MYSQL_DLNAME;
+#endif
+ else
+ { /* invalid option is always disabled */
+ s = NULL;
+ }
+ return s;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_free_env - free GLPK environment
+*
+* SYNOPSIS
+*
+* int glp_free_env(void);
+*
+* DESCRIPTION
+*
+* The routine glp_free_env frees all resources used by GLPK routines
+* (memory blocks, etc.) which are currently still in use.
+*
+* Normally the application program does not need to call this routine,
+* because GLPK routines always free all unused resources. However, if
+* the application program even has deleted all problem objects, there
+* will be several memory blocks still allocated for the library needs.
+* For some reasons the application program may want GLPK to free this
+* memory, in which case it should call glp_free_env.
+*
+* Note that a call to glp_free_env invalidates all problem objects as
+* if no GLPK routine were called.
+*
+* RETURNS
+*
+* 0 - termination successful;
+* 1 - environment is inactive (was not initialized). */
+
+int glp_free_env(void)
+{ ENV *env = tls_get_ptr();
+ MBD *desc;
+ /* check if the environment is active */
+ if (env == NULL)
+ return 1;
+ /* check if the environment block is valid */
+ if (env->self != env)
+ { fprintf(stderr, "Invalid GLPK environment\n");
+ fflush(stderr);
+ abort();
+ }
+ /* close handles to shared libraries */
+ if (env->h_odbc != NULL)
+ xdlclose(env->h_odbc);
+ if (env->h_mysql != NULL)
+ xdlclose(env->h_mysql);
+ /* free memory blocks which are still allocated */
+ while (env->mem_ptr != NULL)
+ { desc = env->mem_ptr;
+ env->mem_ptr = desc->next;
+ free(desc);
+ }
+ /* close text file used for copying terminal output */
+ if (env->tee_file != NULL)
+ fclose(env->tee_file);
+ /* invalidate the environment block */
+ env->self = NULL;
+ /* free memory allocated to the environment block */
+ free(env->term_buf);
+ free(env->err_buf);
+ free(env);
+ /* reset a pointer to the environment block */
+ tls_set_ptr(NULL);
+ /* termination successful */
+ return 0;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/env.h b/test/monniaux/glpk-4.65/src/env/env.h
new file mode 100644
index 00000000..67214ef6
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/env.h
@@ -0,0 +1,274 @@
+/* env.h (GLPK environment) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef ENV_H
+#define ENV_H
+
+#include "stdc.h"
+
+typedef struct ENV ENV;
+typedef struct MBD MBD;
+
+#define SIZE_T_MAX (~(size_t)0)
+/* largest value of size_t type */
+
+#define TBUF_SIZE 4096
+/* terminal output buffer size, in bytes */
+
+#define EBUF_SIZE 1024
+/* error message buffer size, in bytes */
+
+/* enable/disable flag: */
+#define GLP_ON 1
+#define GLP_OFF 0
+
+struct ENV
+{ /* GLPK environment block */
+#if 0 /* 14/I-2007 */
+ char version[7+1];
+ /* version string returned by the routine glp_version */
+#endif
+ ENV *self;
+ /* pointer to this block to check its validity */
+ /*--------------------------------------------------------------*/
+ /* terminal output */
+ char *term_buf; /* char term_buf[TBUF_SIZE]; */
+ /* terminal output buffer */
+ int term_out;
+ /* flag to enable/disable terminal output */
+ int (*term_hook)(void *info, const char *s);
+ /* user-defined routine to intercept terminal output */
+ void *term_info;
+ /* transit pointer (cookie) passed to the routine term_hook */
+ FILE *tee_file;
+ /* output stream used to copy terminal output */
+ /*--------------------------------------------------------------*/
+ /* error handling */
+#if 1 /* 07/XI-2015 */
+ int err_st;
+ /* error state flag; set on entry to glp_error */
+#endif
+ const char *err_file;
+ /* value of the __FILE__ macro passed to glp_error */
+ int err_line;
+ /* value of the __LINE__ macro passed to glp_error */
+ void (*err_hook)(void *info);
+ /* user-defined routine to intercept abnormal termination */
+ void *err_info;
+ /* transit pointer (cookie) passed to the routine err_hook */
+ char *err_buf; /* char err_buf[EBUF_SIZE]; */
+ /* buffer to store error messages (used by I/O routines) */
+ /*--------------------------------------------------------------*/
+ /* dynamic memory allocation */
+ size_t mem_limit;
+ /* maximal amount of memory, in bytes, available for dynamic
+ * allocation */
+ MBD *mem_ptr;
+ /* pointer to the linked list of allocated memory blocks */
+ int mem_count;
+ /* total number of currently allocated memory blocks */
+ int mem_cpeak;
+ /* peak value of mem_count */
+ size_t mem_total;
+ /* total amount of currently allocated memory, in bytes; it is
+ * the sum of the size field over all memory block descriptors */
+ size_t mem_tpeak;
+ /* peak value of mem_total */
+#if 1 /* 23/XI-2015 */
+ /*--------------------------------------------------------------*/
+ /* bignum module working area */
+ void *gmp_pool; /* DMP *gmp_pool; */
+ /* working memory pool */
+ int gmp_size;
+ /* size of working array */
+ unsigned short *gmp_work; /* ushort gmp_work[gmp_size]; */
+ /* working array */
+#endif
+ /*--------------------------------------------------------------*/
+ /* dynamic linking support (optional) */
+ void *h_odbc;
+ /* handle to ODBC shared library */
+ void *h_mysql;
+ /* handle to MySQL shared library */
+};
+
+struct MBD
+{ /* memory block descriptor */
+ size_t size;
+ /* size of block, in bytes, including descriptor */
+ MBD *self;
+ /* pointer to this descriptor to check its validity */
+ MBD *prev;
+ /* pointer to previous memory block descriptor */
+ MBD *next;
+ /* pointer to next memory block descriptor */
+};
+
+#define get_env_ptr _glp_get_env_ptr
+ENV *get_env_ptr(void);
+/* retrieve pointer to environment block */
+
+#define tls_set_ptr _glp_tls_set_ptr
+void tls_set_ptr(void *ptr);
+/* store global pointer in TLS */
+
+#define tls_get_ptr _glp_tls_get_ptr
+void *tls_get_ptr(void);
+/* retrieve global pointer from TLS */
+
+#define xputs glp_puts
+void glp_puts(const char *s);
+/* write string on terminal */
+
+#define xprintf glp_printf
+void glp_printf(const char *fmt, ...);
+/* write formatted output on terminal */
+
+#define xvprintf glp_vprintf
+void glp_vprintf(const char *fmt, va_list arg);
+/* write formatted output on terminal */
+
+int glp_term_out(int flag);
+/* enable/disable terminal output */
+
+void glp_term_hook(int (*func)(void *info, const char *s), void *info);
+/* install hook to intercept terminal output */
+
+int glp_open_tee(const char *fname);
+/* start copying terminal output to text file */
+
+int glp_close_tee(void);
+/* stop copying terminal output to text file */
+
+#ifndef GLP_ERRFUNC_DEFINED
+#define GLP_ERRFUNC_DEFINED
+typedef void (*glp_errfunc)(const char *fmt, ...);
+#endif
+
+#define xerror glp_error_(__FILE__, __LINE__)
+glp_errfunc glp_error_(const char *file, int line);
+/* display fatal error message and terminate execution */
+
+#define xassert(expr) \
+ ((void)((expr) || (glp_assert_(#expr, __FILE__, __LINE__), 1)))
+void glp_assert_(const char *expr, const char *file, int line);
+/* check for logical condition */
+
+void glp_error_hook(void (*func)(void *info), void *info);
+/* install hook to intercept abnormal termination */
+
+#define put_err_msg _glp_put_err_msg
+void put_err_msg(const char *msg);
+/* provide error message string */
+
+#define get_err_msg _glp_get_err_msg
+const char *get_err_msg(void);
+/* obtain error message string */
+
+#define xmalloc(size) glp_alloc(1, size)
+/* allocate memory block (obsolete) */
+
+#define xcalloc(n, size) glp_alloc(n, size)
+/* allocate memory block (obsolete) */
+
+#define xalloc(n, size) glp_alloc(n, size)
+#define talloc(n, type) ((type *)glp_alloc(n, sizeof(type)))
+void *glp_alloc(int n, int size);
+/* allocate memory block */
+
+#define xrealloc(ptr, n, size) glp_realloc(ptr, n, size)
+#define trealloc(ptr, n, type) ((type *)glp_realloc(ptr, n, \
+ sizeof(type)))
+void *glp_realloc(void *ptr, int n, int size);
+/* reallocate memory block */
+
+#define xfree(ptr) glp_free(ptr)
+#define tfree(ptr) glp_free(ptr)
+void glp_free(void *ptr);
+/* free memory block */
+
+void glp_mem_limit(int limit);
+/* set memory usage limit */
+
+void glp_mem_usage(int *count, int *cpeak, size_t *total,
+ size_t *tpeak);
+/* get memory usage information */
+
+typedef struct glp_file glp_file;
+/* sequential stream descriptor */
+
+#define glp_open _glp_open
+glp_file *glp_open(const char *name, const char *mode);
+/* open stream */
+
+#define glp_eof _glp_eof
+int glp_eof(glp_file *f);
+/* test end-of-file indicator */
+
+#define glp_ioerr _glp_ioerr
+int glp_ioerr(glp_file *f);
+/* test I/O error indicator */
+
+#define glp_read _glp_read
+int glp_read(glp_file *f, void *buf, int nnn);
+/* read data from stream */
+
+#define glp_getc _glp_getc
+int glp_getc(glp_file *f);
+/* read character from stream */
+
+#define glp_write _glp_write
+int glp_write(glp_file *f, const void *buf, int nnn);
+/* write data to stream */
+
+#define glp_format _glp_format
+int glp_format(glp_file *f, const char *fmt, ...);
+/* write formatted data to stream */
+
+#define glp_close _glp_close
+int glp_close(glp_file *f);
+/* close stream */
+
+#define xtime glp_time
+double glp_time(void);
+/* determine current universal time */
+
+#define xdifftime glp_difftime
+double glp_difftime(double t1, double t0);
+/* compute difference between two time values */
+
+#define xdlopen _glp_dlopen
+void *xdlopen(const char *module);
+/* open dynamically linked library */
+
+#define xdlsym _glp_dlsym
+void *xdlsym(void *h, const char *symbol);
+/* obtain address of symbol from dynamically linked library */
+
+#define xdlclose _glp_dlclose
+void xdlclose(void *h);
+/* close dynamically linked library */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/error.c b/test/monniaux/glpk-4.65/src/env/error.c
new file mode 100644
index 00000000..a898b768
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/error.c
@@ -0,0 +1,200 @@
+/* error.c (error handling) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2015 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_error - display fatal error message and terminate execution
+*
+* SYNOPSIS
+*
+* void glp_error(const char *fmt, ...);
+*
+* DESCRIPTION
+*
+* The routine glp_error (implemented as a macro) formats its
+* parameters using the format control string fmt, writes the formatted
+* message on the terminal, and abnormally terminates the program. */
+
+static void errfunc(const char *fmt, ...)
+{ ENV *env = get_env_ptr();
+ va_list arg;
+#if 1 /* 07/XI-2015 */
+ env->err_st = 1;
+#endif
+ env->term_out = GLP_ON;
+ va_start(arg, fmt);
+ xvprintf(fmt, arg);
+ va_end(arg);
+ xprintf("Error detected in file %s at line %d\n",
+ env->err_file, env->err_line);
+ if (env->err_hook != NULL)
+ env->err_hook(env->err_info);
+ abort();
+ exit(EXIT_FAILURE);
+ /* no return */
+}
+
+glp_errfunc glp_error_(const char *file, int line)
+{ ENV *env = get_env_ptr();
+ env->err_file = file;
+ env->err_line = line;
+ return errfunc;
+}
+
+#if 1 /* 07/XI-2015 */
+/***********************************************************************
+* NAME
+*
+* glp_at_error - check for error state
+*
+* SYNOPSIS
+*
+* int glp_at_error(void);
+*
+* DESCRIPTION
+*
+* The routine glp_at_error checks if the GLPK environment is at error
+* state, i.e. if the call to the routine is (indirectly) made from the
+* glp_error routine via an user-defined hook routine.
+*
+* RETURNS
+*
+* If the GLPK environment is at error state, the routine glp_at_error
+* returns non-zero, otherwise zero. */
+
+int glp_at_error(void)
+{ ENV *env = get_env_ptr();
+ return env->err_st;
+}
+#endif
+
+/***********************************************************************
+* NAME
+*
+* glp_assert - check for logical condition
+*
+* SYNOPSIS
+*
+* void glp_assert(int expr);
+*
+* DESCRIPTION
+*
+* The routine glp_assert (implemented as a macro) checks for a logical
+* condition specified by the parameter expr. If the condition is false
+* (i.e. the value of expr is zero), the routine writes a message on
+* the terminal and abnormally terminates the program. */
+
+void glp_assert_(const char *expr, const char *file, int line)
+{ glp_error_(file, line)("Assertion failed: %s\n", expr);
+ /* no return */
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_error_hook - install hook to intercept abnormal termination
+*
+* SYNOPSIS
+*
+* void glp_error_hook(void (*func)(void *info), void *info);
+*
+* DESCRIPTION
+*
+* The routine glp_error_hook installs a user-defined hook routine to
+* intercept abnormal termination.
+*
+* The parameter func specifies the user-defined hook routine. It is
+* called from the routine glp_error before the latter calls the abort
+* function to abnormally terminate the application program because of
+* fatal error. The parameter info is a transit pointer, specified in
+* the corresponding call to the routine glp_error_hook; it may be used
+* to pass some information to the hook routine.
+*
+* To uninstall the hook routine the parameters func and info should be
+* both specified as NULL. */
+
+void glp_error_hook(void (*func)(void *info), void *info)
+{ ENV *env = get_env_ptr();
+ if (func == NULL)
+ { env->err_hook = NULL;
+ env->err_info = NULL;
+ }
+ else
+ { env->err_hook = func;
+ env->err_info = info;
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* put_err_msg - provide error message string
+*
+* SYNOPSIS
+*
+* #include "env.h"
+* void put_err_msg(const char *msg);
+*
+* DESCRIPTION
+*
+* The routine put_err_msg stores an error message string pointed to by
+* msg to the environment block. */
+
+void put_err_msg(const char *msg)
+{ ENV *env = get_env_ptr();
+ int len;
+ len = strlen(msg);
+ if (len >= EBUF_SIZE)
+ len = EBUF_SIZE - 1;
+ memcpy(env->err_buf, msg, len);
+ if (len > 0 && env->err_buf[len-1] == '\n')
+ len--;
+ env->err_buf[len] = '\0';
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* get_err_msg - obtain error message string
+*
+* SYNOPSIS
+*
+* #include "env.h"
+* const char *get_err_msg(void);
+*
+* RETURNS
+*
+* The routine get_err_msg returns a pointer to an error message string
+* previously stored by the routine put_err_msg. */
+
+const char *get_err_msg(void)
+{ ENV *env = get_env_ptr();
+ return env->err_buf;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/stdc.c b/test/monniaux/glpk-4.65/src/env/stdc.c
new file mode 100644
index 00000000..59331e22
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/stdc.c
@@ -0,0 +1,98 @@
+/* stdc.c (replacements for standard non-thread-safe functions) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2017 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* portable ANSI C version ********************************************/
+
+#if !defined(TLS)
+
+#define ENABLE_NON_SAFE
+#include "stdc.h"
+
+struct tm *xgmtime(const time_t *timer)
+{ return
+ gmtime(timer);
+}
+
+char *xstrerr(int errnum)
+{ return
+ strerror(errnum);
+}
+
+char *xstrtok(char *s1, const char *s2)
+{ return
+ strtok(s1, s2);
+}
+
+/* MS Windows version *************************************************/
+
+#elif defined(__WOE__)
+
+#include "stdc.h"
+
+struct tm *xgmtime(const time_t *timer)
+{ static TLS struct tm result;
+ gmtime_s(&result, timer);
+ return &result;
+}
+
+char *xstrerr(int errnum)
+{ static TLS char s[1023+1];
+ strerror_s(s, sizeof(s), errnum);
+ return s;
+}
+
+char *xstrtok(char *s1, const char *s2)
+{ static TLS char *ptr;
+ return strtok_s(s1, s2, &ptr);
+}
+
+/* GNU/Linux version **************************************************/
+
+#else
+
+#include "stdc.h"
+
+struct tm *xgmtime(const time_t *timer)
+{ static TLS struct tm result;
+ gmtime_r(timer, &result);
+ return &result;
+}
+
+char *xstrerr(int errnum)
+{ static TLS char s[1023+1];
+ strerror_r(errnum, s, sizeof(s));
+ return s;
+}
+
+char *xstrtok(char *s1, const char *s2)
+{ static TLS char *ptr;
+ return strtok_r(s1, s2, &ptr);
+}
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/stdc.h b/test/monniaux/glpk-4.65/src/env/stdc.h
new file mode 100644
index 00000000..a376f2c9
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/stdc.h
@@ -0,0 +1,73 @@
+/* stdc.h (standard ANSI C headers) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef STDC_H
+#define STDC_H
+
+#include <ctype.h>
+#include <errno.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef ENABLE_NON_SAFE /* 29/I-2017 */
+/* disable using non-thread-safe functions directly */
+#undef gmtime
+#define gmtime ???
+#undef strerror
+#define strerror ???
+#undef strtok
+#define strtok ???
+#endif
+
+#if 1 /* 29/I-2017 */
+/* provide replacements for these functions on a per-thread basis */
+#define xgmtime _glp_xgmtime
+struct tm *xgmtime(const time_t *);
+#define xstrerr _glp_xstrerr
+char *xstrerr(int);
+#define xstrtok _glp_xstrtok
+char *xstrtok(char *, const char *);
+#endif
+
+#if 1 /* 06/II-2018 */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifndef __WOE__
+#define CDECL
+#else
+#define CDECL __cdecl
+#endif
+#endif
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/stdout.c b/test/monniaux/glpk-4.65/src/env/stdout.c
new file mode 100644
index 00000000..94eee02a
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/stdout.c
@@ -0,0 +1,262 @@
+/* stdout.c (terminal output) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#undef NDEBUG
+#include <assert.h>
+#include "env.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_puts - write string on terminal
+*
+* SYNOPSIS
+*
+* void glp_puts(const char *s);
+*
+* The routine glp_puts writes the string s on the terminal. */
+
+void glp_puts(const char *s)
+{ ENV *env = get_env_ptr();
+ /* if terminal output is disabled, do nothing */
+ if (!env->term_out)
+ goto skip;
+ /* pass the string to the hook routine, if defined */
+ if (env->term_hook != NULL)
+ { if (env->term_hook(env->term_info, s) != 0)
+ goto skip;
+ }
+ /* write the string on the terminal */
+ fputs(s, stdout);
+ fflush(stdout);
+ /* write the string on the tee file, if required */
+ if (env->tee_file != NULL)
+ { fputs(s, env->tee_file);
+ fflush(env->tee_file);
+ }
+skip: return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_printf - write formatted output on terminal
+*
+* SYNOPSIS
+*
+* void glp_printf(const char *fmt, ...);
+*
+* DESCRIPTION
+*
+* The routine glp_printf uses the format control string fmt to format
+* its parameters and writes the formatted output on the terminal. */
+
+void glp_printf(const char *fmt, ...)
+{ ENV *env = get_env_ptr();
+ va_list arg;
+ /* if terminal output is disabled, do nothing */
+ if (!env->term_out)
+ goto skip;
+ /* format the output */
+ va_start(arg, fmt);
+ vsprintf(env->term_buf, fmt, arg);
+ /* (do not use xassert) */
+ assert(strlen(env->term_buf) < TBUF_SIZE);
+ va_end(arg);
+ /* write the formatted output on the terminal */
+ glp_puts(env->term_buf);
+skip: return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_vprintf - write formatted output on terminal
+*
+* SYNOPSIS
+*
+* void glp_vprintf(const char *fmt, va_list arg);
+*
+* DESCRIPTION
+*
+* The routine glp_vprintf uses the format control string fmt to format
+* its parameters specified by the list arg and writes the formatted
+* output on the terminal. */
+
+void glp_vprintf(const char *fmt, va_list arg)
+{ ENV *env = get_env_ptr();
+ /* if terminal output is disabled, do nothing */
+ if (!env->term_out)
+ goto skip;
+ /* format the output */
+ vsprintf(env->term_buf, fmt, arg);
+ /* (do not use xassert) */
+ assert(strlen(env->term_buf) < TBUF_SIZE);
+ /* write the formatted output on the terminal */
+ glp_puts(env->term_buf);
+skip: return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_term_out - enable/disable terminal output
+*
+* SYNOPSIS
+*
+* int glp_term_out(int flag);
+*
+* DESCRIPTION
+*
+* Depending on the parameter flag the routine glp_term_out enables or
+* disables terminal output performed by glpk routines:
+*
+* GLP_ON - enable terminal output;
+* GLP_OFF - disable terminal output.
+*
+* RETURNS
+*
+* The routine glp_term_out returns the previous value of the terminal
+* output flag. */
+
+int glp_term_out(int flag)
+{ ENV *env = get_env_ptr();
+ int old = env->term_out;
+ if (!(flag == GLP_ON || flag == GLP_OFF))
+ xerror("glp_term_out: flag = %d; invalid parameter\n", flag);
+ env->term_out = flag;
+ return old;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_term_hook - install hook to intercept terminal output
+*
+* SYNOPSIS
+*
+* void glp_term_hook(int (*func)(void *info, const char *s),
+* void *info);
+*
+* DESCRIPTION
+*
+* The routine glp_term_hook installs a user-defined hook routine to
+* intercept all terminal output performed by glpk routines.
+*
+* This feature can be used to redirect the terminal output to other
+* destination, for example to a file or a text window.
+*
+* The parameter func specifies the user-defined hook routine. It is
+* called from an internal printing routine, which passes to it two
+* parameters: info and s. The parameter info is a transit pointer,
+* specified in the corresponding call to the routine glp_term_hook;
+* it may be used to pass some information to the hook routine. The
+* parameter s is a pointer to the null terminated character string,
+* which is intended to be written to the terminal. If the hook routine
+* returns zero, the printing routine writes the string s to the
+* terminal in a usual way; otherwise, if the hook routine returns
+* non-zero, no terminal output is performed.
+*
+* To uninstall the hook routine the parameters func and info should be
+* specified as NULL. */
+
+void glp_term_hook(int (*func)(void *info, const char *s), void *info)
+{ ENV *env = get_env_ptr();
+ if (func == NULL)
+ { env->term_hook = NULL;
+ env->term_info = NULL;
+ }
+ else
+ { env->term_hook = func;
+ env->term_info = info;
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_open_tee - start copying terminal output to text file
+*
+* SYNOPSIS
+*
+* int glp_open_tee(const char *name);
+*
+* DESCRIPTION
+*
+* The routine glp_open_tee starts copying all the terminal output to
+* an output text file, whose name is specified by the character string
+* name.
+*
+* RETURNS
+*
+* 0 - operation successful
+* 1 - copying terminal output is already active
+* 2 - unable to create output file */
+
+int glp_open_tee(const char *name)
+{ ENV *env = get_env_ptr();
+ if (env->tee_file != NULL)
+ { /* copying terminal output is already active */
+ return 1;
+ }
+ env->tee_file = fopen(name, "w");
+ if (env->tee_file == NULL)
+ { /* unable to create output file */
+ return 2;
+ }
+ return 0;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_close_tee - stop copying terminal output to text file
+*
+* SYNOPSIS
+*
+* int glp_close_tee(void);
+*
+* DESCRIPTION
+*
+* The routine glp_close_tee stops copying the terminal output to the
+* output text file previously open by the routine glp_open_tee closing
+* that file.
+*
+* RETURNS
+*
+* 0 - operation successful
+* 1 - copying terminal output was not started */
+
+int glp_close_tee(void)
+{ ENV *env = get_env_ptr();
+ if (env->tee_file == NULL)
+ { /* copying terminal output was not started */
+ return 1;
+ }
+ fclose(env->tee_file);
+ env->tee_file = NULL;
+ return 0;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/stream.c b/test/monniaux/glpk-4.65/src/env/stream.c
new file mode 100644
index 00000000..906e5b04
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/stream.c
@@ -0,0 +1,517 @@
+/* stream.c (stream input/output) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2008-2017 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "zlib.h"
+
+struct glp_file
+{ /* sequential stream descriptor */
+ char *base;
+ /* pointer to buffer */
+ int size;
+ /* size of buffer, in bytes */
+ char *ptr;
+ /* pointer to next byte in buffer */
+ int cnt;
+ /* count of bytes in buffer */
+ int flag;
+ /* stream flags: */
+#define IONULL 0x01 /* null file */
+#define IOSTD 0x02 /* standard stream */
+#define IOGZIP 0x04 /* gzipped file */
+#define IOWRT 0x08 /* output stream */
+#define IOEOF 0x10 /* end of file */
+#define IOERR 0x20 /* input/output error */
+ void *file;
+ /* pointer to underlying control object */
+};
+
+/***********************************************************************
+* NAME
+*
+* glp_open - open stream
+*
+* SYNOPSIS
+*
+* glp_file *glp_open(const char *name, const char *mode);
+*
+* DESCRIPTION
+*
+* The routine glp_open opens a file whose name is a string pointed to
+* by name and associates a stream with it.
+*
+* The following special filenames are recognized by the routine (this
+* feature is platform independent):
+*
+* "/dev/null" empty (null) file;
+* "/dev/stdin" standard input stream;
+* "/dev/stdout" standard output stream;
+* "/dev/stderr" standard error stream.
+*
+* If the specified filename is ended with ".gz", it is assumed that
+* the file is in gzipped format. In this case the file is compressed
+* or decompressed by the I/O routines "on the fly".
+*
+* The parameter mode points to a string, which indicates the open mode
+* and should be one of the following:
+*
+* "r" open text file for reading;
+* "w" truncate to zero length or create text file for writing;
+* "a" append, open or create text file for writing at end-of-file;
+* "rb" open binary file for reading;
+* "wb" truncate to zero length or create binary file for writing;
+* "ab" append, open or create binary file for writing at end-of-file.
+*
+* RETURNS
+*
+* The routine glp_open returns a pointer to the object controlling the
+* stream. If the operation fails, the routine returns NULL. */
+
+glp_file *glp_open(const char *name, const char *mode)
+{ glp_file *f;
+ int flag;
+ void *file;
+ if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0)
+ flag = 0;
+ else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0)
+ flag = IOWRT;
+#if 1 /* 08/V-2014 */
+ else if (strcmp(mode, "a") == 0 || strcmp(mode, "ab") == 0)
+ flag = IOWRT;
+#endif
+ else
+ xerror("glp_open: invalid mode string\n");
+ if (strcmp(name, "/dev/null") == 0)
+ { flag |= IONULL;
+ file = NULL;
+ }
+ else if (strcmp(name, "/dev/stdin") == 0)
+ { flag |= IOSTD;
+ file = stdin;
+ }
+ else if (strcmp(name, "/dev/stdout") == 0)
+ { flag |= IOSTD;
+ file = stdout;
+ }
+ else if (strcmp(name, "/dev/stderr") == 0)
+ { flag |= IOSTD;
+ file = stderr;
+ }
+ else
+ { char *ext = strrchr(name, '.');
+ if (ext == NULL || strcmp(ext, ".gz") != 0)
+ { file = fopen(name, mode);
+ if (file == NULL)
+#if 0 /* 29/I-2017 */
+ { put_err_msg(strerror(errno));
+#else
+ { put_err_msg(xstrerr(errno));
+#endif
+ return NULL;
+ }
+ }
+ else
+ { flag |= IOGZIP;
+ if (strcmp(mode, "r") == 0)
+ mode = "rb";
+ else if (strcmp(mode, "w") == 0)
+ mode = "wb";
+#if 1 /* 08/V-2014; this mode seems not to work */
+ else if (strcmp(mode, "a") == 0)
+ mode = "ab";
+#endif
+ file = gzopen(name, mode);
+ if (file == NULL)
+#if 0 /* 29/I-2017 */
+ { put_err_msg(strerror(errno));
+#else
+ { put_err_msg(xstrerr(errno));
+#endif
+ return NULL;
+ }
+ }
+ }
+ f = talloc(1, glp_file);
+ f->base = talloc(BUFSIZ, char);
+ f->size = BUFSIZ;
+ f->ptr = f->base;
+ f->cnt = 0;
+ f->flag = flag;
+ f->file = file;
+ return f;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_eof - test end-of-file indicator
+*
+* SYNOPSIS
+*
+* int glp_eof(glp_file *f);
+*
+* DESCRIPTION
+*
+* The routine glp_eof tests the end-of-file indicator for the stream
+* pointed to by f.
+*
+* RETURNS
+*
+* The routine glp_eof returns non-zero if and only if the end-of-file
+* indicator is set for the specified stream. */
+
+int glp_eof(glp_file *f)
+{ return
+ f->flag & IOEOF;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_ioerr - test I/O error indicator
+*
+* SYNOPSIS
+*
+* int glp_ioerr(glp_file *f);
+*
+* DESCRIPTION
+*
+* The routine glp_ioerr tests the I/O error indicator for the stream
+* pointed to by f.
+*
+* RETURNS
+*
+* The routine glp_ioerr returns non-zero if and only if the I/O error
+* indicator is set for the specified stream. */
+
+int glp_ioerr(glp_file *f)
+{ return
+ f->flag & IOERR;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_read - read data from stream
+*
+* SYNOPSIS
+*
+* int glp_read(glp_file *f, void *buf, int nnn);
+*
+* DESCRIPTION
+*
+* The routine glp_read reads, into the buffer pointed to by buf, up to
+* nnn bytes, from the stream pointed to by f.
+*
+* RETURNS
+*
+* The routine glp_read returns the number of bytes successfully read
+* (which may be less than nnn). If an end-of-file is encountered, the
+* end-of-file indicator for the stream is set and glp_read returns
+* zero. If a read error occurs, the error indicator for the stream is
+* set and glp_read returns a negative value. */
+
+int glp_read(glp_file *f, void *buf, int nnn)
+{ int nrd, cnt;
+ if (f->flag & IOWRT)
+ xerror("glp_read: attempt to read from output stream\n");
+ if (nnn < 1)
+ xerror("glp_read: nnn = %d; invalid parameter\n", nnn);
+ for (nrd = 0; nrd < nnn; nrd += cnt)
+ { if (f->cnt == 0)
+ { /* buffer is empty; fill it */
+ if (f->flag & IONULL)
+ cnt = 0;
+ else if (!(f->flag & IOGZIP))
+ { cnt = fread(f->base, 1, f->size, (FILE *)(f->file));
+ if (ferror((FILE *)(f->file)))
+ { f->flag |= IOERR;
+#if 0 /* 29/I-2017 */
+ put_err_msg(strerror(errno));
+#else
+ put_err_msg(xstrerr(errno));
+#endif
+ return EOF;
+ }
+ }
+ else
+ { int errnum;
+ const char *msg;
+ cnt = gzread((gzFile)(f->file), f->base, f->size);
+ if (cnt < 0)
+ { f->flag |= IOERR;
+ msg = gzerror((gzFile)(f->file), &errnum);
+ if (errnum == Z_ERRNO)
+#if 0 /* 29/I-2017 */
+ put_err_msg(strerror(errno));
+#else
+ put_err_msg(xstrerr(errno));
+#endif
+ else
+ put_err_msg(msg);
+ return EOF;
+ }
+ }
+ if (cnt == 0)
+ { if (nrd == 0)
+ f->flag |= IOEOF;
+ break;
+ }
+ f->ptr = f->base;
+ f->cnt = cnt;
+ }
+ cnt = nnn - nrd;
+ if (cnt > f->cnt)
+ cnt = f->cnt;
+ memcpy((char *)buf + nrd, f->ptr, cnt);
+ f->ptr += cnt;
+ f->cnt -= cnt;
+ }
+ return nrd;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_getc - read character from stream
+*
+* SYNOPSIS
+*
+* int glp_getc(glp_file *f);
+*
+* DESCRIPTION
+*
+* The routine glp_getc obtains a next character as an unsigned char
+* converted to an int from the input stream pointed to by f.
+*
+* RETURNS
+*
+* The routine glp_getc returns the next character obtained. However,
+* if an end-of-file is encountered or a read error occurs, the routine
+* returns EOF. (An end-of-file and a read error can be distinguished
+* by use of the routines glp_eof and glp_ioerr.) */
+
+int glp_getc(glp_file *f)
+{ unsigned char buf[1];
+ if (f->flag & IOWRT)
+ xerror("glp_getc: attempt to read from output stream\n");
+ if (glp_read(f, buf, 1) != 1)
+ return EOF;
+ return buf[0];
+}
+
+/***********************************************************************
+* do_flush - flush output stream
+*
+* This routine causes buffered data for the specified output stream to
+* be written to the associated file.
+*
+* If the operation was successful, the routine returns zero, otherwise
+* non-zero. */
+
+static int do_flush(glp_file *f)
+{ xassert(f->flag & IOWRT);
+ if (f->cnt > 0)
+ { if (f->flag & IONULL)
+ ;
+ else if (!(f->flag & IOGZIP))
+ { if ((int)fwrite(f->base, 1, f->cnt, (FILE *)(f->file))
+ != f->cnt)
+ { f->flag |= IOERR;
+#if 0 /* 29/I-2017 */
+ put_err_msg(strerror(errno));
+#else
+ put_err_msg(xstrerr(errno));
+#endif
+ return EOF;
+ }
+ }
+ else
+ { int errnum;
+ const char *msg;
+ if (gzwrite((gzFile)(f->file), f->base, f->cnt) != f->cnt)
+ { f->flag |= IOERR;
+ msg = gzerror((gzFile)(f->file), &errnum);
+ if (errnum == Z_ERRNO)
+#if 0 /* 29/I-2017 */
+ put_err_msg(strerror(errno));
+#else
+ put_err_msg(xstrerr(errno));
+#endif
+ else
+ put_err_msg(msg);
+ return EOF;
+ }
+ }
+ }
+ f->ptr = f->base;
+ f->cnt = 0;
+ return 0;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_write - write data to stream
+*
+* SYNOPSIS
+*
+* int glp_write(glp_file *f, const void *buf, int nnn);
+*
+* DESCRIPTION
+*
+* The routine glp_write writes, from the buffer pointed to by buf, up
+* to nnn bytes, to the stream pointed to by f.
+*
+* RETURNS
+*
+* The routine glp_write returns the number of bytes successfully
+* written (which is equal to nnn). If a write error occurs, the error
+* indicator for the stream is set and glp_write returns a negative
+* value. */
+
+int glp_write(glp_file *f, const void *buf, int nnn)
+{ int nwr, cnt;
+ if (!(f->flag & IOWRT))
+ xerror("glp_write: attempt to write to input stream\n");
+ if (nnn < 1)
+ xerror("glp_write: nnn = %d; invalid parameter\n", nnn);
+ for (nwr = 0; nwr < nnn; nwr += cnt)
+ { cnt = nnn - nwr;
+ if (cnt > f->size - f->cnt)
+ cnt = f->size - f->cnt;
+ memcpy(f->ptr, (const char *)buf + nwr, cnt);
+ f->ptr += cnt;
+ f->cnt += cnt;
+ if (f->cnt == f->size)
+ { /* buffer is full; flush it */
+ if (do_flush(f) != 0)
+ return EOF;
+ }
+ }
+ return nwr;
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_format - write formatted data to stream
+*
+* SYNOPSIS
+*
+* int glp_format(glp_file *f, const char *fmt, ...);
+*
+* DESCRIPTION
+*
+* The routine glp_format writes formatted data to the stream pointed
+* to by f. The format control string pointed to by fmt specifies how
+* subsequent arguments are converted for output.
+*
+* RETURNS
+*
+* The routine glp_format returns the number of characters written, or
+* a negative value if an output error occurs. */
+
+int glp_format(glp_file *f, const char *fmt, ...)
+{ ENV *env = get_env_ptr();
+ va_list arg;
+ int nnn;
+ if (!(f->flag & IOWRT))
+ xerror("glp_format: attempt to write to input stream\n");
+ va_start(arg, fmt);
+ nnn = vsprintf(env->term_buf, fmt, arg);
+ xassert(0 <= nnn && nnn < TBUF_SIZE);
+ va_end(arg);
+ return nnn == 0 ? 0 : glp_write(f, env->term_buf, nnn);
+}
+
+/***********************************************************************
+* NAME
+*
+* glp_close - close stream
+*
+* SYNOPSIS
+*
+* int glp_close(glp_file *f);
+*
+* DESCRIPTION
+*
+* The routine glp_close closes the stream pointed to by f.
+*
+* RETURNS
+*
+* If the operation was successful, the routine returns zero, otherwise
+* non-zero. */
+
+int glp_close(glp_file *f)
+{ int ret = 0;
+ if (f->flag & IOWRT)
+ { if (do_flush(f) != 0)
+ ret = EOF;
+ }
+ if (f->flag & (IONULL | IOSTD))
+ ;
+ else if (!(f->flag & IOGZIP))
+ { if (fclose((FILE *)(f->file)) != 0)
+ { if (ret == 0)
+#if 0 /* 29/I-2017 */
+ { put_err_msg(strerror(errno));
+#else
+ { put_err_msg(xstrerr(errno));
+#endif
+ ret = EOF;
+ }
+ }
+ }
+ else
+ { int errnum;
+ errnum = gzclose((gzFile)(f->file));
+ if (errnum == Z_OK)
+ ;
+ else if (errnum == Z_ERRNO)
+ { if (ret == 0)
+#if 0 /* 29/I-2017 */
+ { put_err_msg(strerror(errno));
+#else
+ { put_err_msg(xstrerr(errno));
+#endif
+ ret = EOF;
+ }
+ }
+#if 1 /* FIXME */
+ else
+ { if (ret == 0)
+ { ENV *env = get_env_ptr();
+ sprintf(env->term_buf, "gzclose returned %d", errnum);
+ put_err_msg(env->term_buf);
+ ret = EOF;
+ }
+ }
+#endif
+ }
+ tfree(f->base);
+ tfree(f);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/time.c b/test/monniaux/glpk-4.65/src/env/time.c
new file mode 100644
index 00000000..1ffb28e9
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/time.c
@@ -0,0 +1,150 @@
+/* time.c (standard time) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <address@hidden>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "env.h"
+#include "jd.h"
+
+/***********************************************************************
+* NAME
+*
+* glp_time - determine current universal time
+*
+* SYNOPSIS
+*
+* double glp_time(void);
+*
+* RETURNS
+*
+* The routine glp_time returns the current universal time (UTC), in
+* milliseconds, elapsed since 00:00:00 GMT January 1, 1970. */
+
+#define EPOCH 2440588 /* = jday(1, 1, 1970) */
+
+/* POSIX version ******************************************************/
+
+#if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY)
+
+#if 0 /* 29/VI-2017 */
+#include <sys/time.h>
+#include <time.h>
+
+double glp_time(void)
+{ struct timeval tv;
+ struct tm *tm;
+ int j;
+ double t;
+ gettimeofday(&tv, NULL);
+#if 0 /* 29/I-2017 */
+ tm = gmtime(&tv.tv_sec);
+#else
+ tm = xgmtime(&tv.tv_sec);
+#endif
+ j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year);
+ xassert(j >= 0);
+ t = ((((double)(j - EPOCH) * 24.0 + (double)tm->tm_hour) * 60.0 +
+ (double)tm->tm_min) * 60.0 + (double)tm->tm_sec) * 1000.0 +
+ (double)(tv.tv_usec / 1000);
+ return t;
+}
+#else
+#include <sys/time.h>
+
+double glp_time(void)
+{ struct timeval tv;
+ double t;
+ gettimeofday(&tv, NULL);
+ t = (double)tv.tv_sec + (double)(tv.tv_usec) / 1e6;
+ xassert(0.0 <= t && t < 4294967296.0);
+ return 1000.0 * t;
+}
+#endif
+
+/* MS Windows version *************************************************/
+
+#elif defined(__WOE__)
+
+#include <windows.h>
+
+double glp_time(void)
+{ SYSTEMTIME st;
+ int j;
+ double t;
+ GetSystemTime(&st);
+ j = jday(st.wDay, st.wMonth, st.wYear);
+ xassert(j >= 0);
+ t = ((((double)(j - EPOCH) * 24.0 + (double)st.wHour) * 60.0 +
+ (double)st.wMinute) * 60.0 + (double)st.wSecond) * 1000.0 +
+ (double)st.wMilliseconds;
+ return t;
+}
+
+/* portable ANSI C version ********************************************/
+
+#else
+
+#include <time.h>
+
+double glp_time(void)
+{ time_t timer;
+ struct tm *tm;
+ int j;
+ double t;
+ timer = time(NULL);
+#if 0 /* 29/I-2017 */
+ tm = gmtime(&timer);
+#else
+ tm = xgmtime(&timer);
+#endif
+ j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year);
+ xassert(j >= 0);
+ t = ((((double)(j - EPOCH) * 24.0 + (double)tm->tm_hour) * 60.0 +
+ (double)tm->tm_min) * 60.0 + (double)tm->tm_sec) * 1000.0;
+ return t;
+}
+
+#endif
+
+/***********************************************************************
+* NAME
+*
+* glp_difftime - compute difference between two time values
+*
+* SYNOPSIS
+*
+* double glp_difftime(double t1, double t0);
+*
+* RETURNS
+*
+* The routine glp_difftime returns the difference between two time
+* values t1 and t0, expressed in seconds. */
+
+double glp_difftime(double t1, double t0)
+{ return
+ (t1 - t0) / 1000.0;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/env/tls.c b/test/monniaux/glpk-4.65/src/env/tls.c
new file mode 100644
index 00000000..4062ee4c
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/env/tls.c
@@ -0,0 +1,128 @@
+/* tls.c (thread local storage) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2001-2017 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK 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 General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "env.h"
+
+#ifndef TLS
+static void *tls = NULL;
+#else
+static TLS void *tls = NULL;
+/* this option allows running multiple independent instances of GLPK in
+ * different threads of a multi-threaded application, in which case the
+ * variable tls should be placed in the Thread Local Storage (TLS);
+ * it is assumed that the macro TLS is previously defined to something
+ * like '__thread', '_Thread_local', etc. */
+#endif
+
+/***********************************************************************
+* NAME
+*
+* tls_set_ptr - store global pointer in TLS
+*
+* SYNOPSIS
+*
+* #include "env.h"
+* void tls_set_ptr(void *ptr);
+*
+* DESCRIPTION
+*
+* The routine tls_set_ptr stores a pointer specified by the parameter
+* ptr in the Thread Local Storage (TLS). */
+
+void tls_set_ptr(void *ptr)
+{ tls = ptr;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* tls_get_ptr - retrieve global pointer from TLS
+*
+* SYNOPSIS
+*
+* #include "env.h"
+* void *tls_get_ptr(void);
+*
+* RETURNS
+*
+* The routine tls_get_ptr returns a pointer previously stored by the
+* routine tls_set_ptr. If the latter has not been called yet, NULL is
+* returned. */
+
+void *tls_get_ptr(void)
+{ void *ptr;
+ ptr = tls;
+ return ptr;
+}
+
+/**********************************************************************/
+
+#ifdef __WOE__
+
+/*** Author: Heinrich Schuchardt <xypron.glpk@gmx.de> ***/
+
+#pragma comment(lib, "user32.lib")
+
+#include <windows.h>
+
+#define VISTA 0x06
+
+/* This is the main entry point of the DLL. */
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID
+ lpvReserved)
+{ DWORD version;
+ DWORD major_version;
+#ifdef TLS
+ switch (fdwReason)
+ { case DLL_PROCESS_ATTACH:
+ /* @TODO:
+ * GetVersion is deprecated but the version help functions are
+ * not available in Visual Studio 2010. So lets use it until
+ * we remove the outdated Build files. */
+ version = GetVersion();
+ major_version = version & 0xff;
+ if (major_version < VISTA)
+ { MessageBoxA(NULL,
+ "The GLPK library called by this application is configur"
+ "ed to use thread local storage which is not fully suppo"
+ "rted by your version of Microsoft Windows.\n\n"
+ "Microsoft Windows Vista or a later version of Windows i"
+ "s required to run this application.",
+ "GLPK", MB_OK | MB_ICONERROR);
+ return FALSE;
+ }
+ break;
+ }
+#endif /* TLS */
+ return TRUE;
+}
+
+#endif /* __WOE__ */
+
+/* eof */