Add graph references
This commit is contained in:
+250
@@ -0,0 +1,250 @@
|
||||
/* alloc.c (dynamic memory allocation) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2000-2013 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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 */
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/* dlsup.c (dynamic linking support) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2008-2013 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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 */
|
||||
+313
@@ -0,0 +1,313 @@
|
||||
/* env.c (GLPK environment initialization/termination) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2000-2017 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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_tls_config.h"
|
||||
|
||||
#include "glpk.h"
|
||||
#include "env.h"
|
||||
|
||||
#include "igraph_error.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 */
|
||||
IGRAPH_FATAL("GLPK initialization failed");
|
||||
}
|
||||
/* initialization successful; retrieve the pointer */
|
||||
env = tls_get_ptr();
|
||||
}
|
||||
/* check if the environment block is valid */
|
||||
if (env->self != env)
|
||||
{
|
||||
IGRAPH_FATAL("Invalid GLPK environment");
|
||||
}
|
||||
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)
|
||||
{
|
||||
IGRAPH_FATAL("Invalid GLPK environment");
|
||||
}
|
||||
/* 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 */
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
/* env.h (GLPK environment) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2000-2017 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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"
|
||||
|
||||
#include "igraph_error.h" /* IGRAPH_FILE_BASENAME */
|
||||
|
||||
typedef struct ENV ENV;
|
||||
typedef struct MBD MBD;
|
||||
|
||||
#ifndef SIZE_T_MAX
|
||||
#define SIZE_T_MAX (~(size_t)0)
|
||||
#endif
|
||||
/* 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_(IGRAPH_FILE_BASENAME, __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, IGRAPH_FILE_BASENAME, __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 */
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
/* error.c (error handling) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2000-2015 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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 "igraph_error.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);
|
||||
IGRAPH_FATAL("Unexpected return from GLPK error hook.");
|
||||
/* 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 */
|
||||
+98
@@ -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 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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_tls_config.h"
|
||||
|
||||
/* 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 */
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/* stdc.h (standard ANSI C headers) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2000-2017 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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 */
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
/* stdout.c (terminal output) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2000-2013 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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"
|
||||
|
||||
#include "igraph_error.h" /* IGRAPH_ASSERT */
|
||||
|
||||
/***********************************************************************
|
||||
* 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) */
|
||||
IGRAPH_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) */
|
||||
IGRAPH_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 */
|
||||
+436
@@ -0,0 +1,436 @@
|
||||
/* stream.c (stream input/output) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2008-2017 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
{ 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;
|
||||
}
|
||||
}
|
||||
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 ((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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
tfree(f->base);
|
||||
tfree(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* eof */
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/* time.c (standard time) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2000-2017 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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"
|
||||
#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 */
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/* tls.c (thread local storage) */
|
||||
|
||||
/***********************************************************************
|
||||
* This code is part of GLPK (GNU Linear Programming Kit).
|
||||
* Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
* Written by Andrew Makhorin <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_tls_config.h"
|
||||
|
||||
#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 */
|
||||
Reference in New Issue
Block a user