1 /* glpenv01.c (environment initialization/termination) */
2 
3 /***********************************************************************
4 *  This code is part of GLPK (GNU Linear Programming Kit).
5 *
6 *  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
7 *  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
8 *  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
9 *  E-mail: <mao@gnu.org>.
10 *
11 *  GLPK is free software: you can redistribute it and/or modify it
12 *  under the terms of the GNU General Public License as published by
13 *  the Free Software Foundation, either version 3 of the License, or
14 *  (at your option) any later version.
15 *
16 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
17 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 *  License for more details.
20 *
21 *  You should have received a copy of the GNU General Public License
22 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
23 ***********************************************************************/
24 
25 #include "glpapi.h"
26 
27 /***********************************************************************
28 *  NAME
29 *
30 *  glp_init_env - initialize GLPK environment
31 *
32 *  SYNOPSIS
33 *
34 *  int glp_init_env(void);
35 *
36 *  DESCRIPTION
37 *
38 *  The routine glp_init_env initializes the GLPK environment. Normally
39 *  the application program does not need to call this routine, because
40 *  it is called automatically on the first call to any API routine.
41 *
42 *  RETURNS
43 *
44 *  The routine glp_init_env returns one of the following codes:
45 *
46 *  0 - initialization successful;
47 *  1 - environment has been already initialized;
48 *  2 - initialization failed (insufficient memory);
49 *  3 - initialization failed (unsupported programming model). */
50 
glp_init_env(void)51 int glp_init_env(void)
52 {     ENV *env;
53       int ok;
54       /* check if the programming model is supported */
55       ok = (CHAR_BIT == 8 && sizeof(char) == 1 &&
56          sizeof(short) == 2 && sizeof(int) == 4 &&
57          (sizeof(void *) == 4 || sizeof(void *) == 8));
58       if (!ok) return 3;
59       /* check if the environment is already initialized */
60       if (tls_get_ptr() != NULL) return 1;
61       /* allocate and initialize the environment block */
62       env = malloc(sizeof(ENV));
63       if (env == NULL) return 2;
64       env->magic = ENV_MAGIC;
65       sprintf(env->version, "%d.%d",
66          GLP_MAJOR_VERSION, GLP_MINOR_VERSION);
67       env->term_buf = malloc(TERM_BUF_SIZE);
68       if (env->term_buf == NULL)
69       {  free(env);
70          return 2;
71       }
72       env->term_out = GLP_ON;
73       env->term_hook = NULL;
74       env->term_info = NULL;
75       env->tee_file = NULL;
76       env->err_file = "";
77       env->err_line = 0;
78       env->err_hook = NULL;
79       env->err_info = NULL;
80       env->mem_limit.hi = 0x7FFFFFFF, env->mem_limit.lo = 0xFFFFFFFF;
81       env->mem_ptr = NULL;
82       env->mem_count = env->mem_cpeak = 0;
83       env->mem_total = env->mem_tpeak = xlset(0);
84       env->file_ptr = NULL;
85       env->ioerr_msg = malloc(IOERR_MSG_SIZE);
86       if (env->ioerr_msg == NULL)
87       {  free(env->term_buf);
88          free(env);
89          return 2;
90       }
91       strcpy(env->ioerr_msg, "No error");
92       env->h_odbc = env->h_mysql = NULL;
93       /* save pointer to the environment block */
94       tls_set_ptr(env);
95       /* initialization successful */
96       return 0;
97 }
98 
99 /***********************************************************************
100 *  NAME
101 *
102 *  get_env_ptr - retrieve pointer to environment block
103 *
104 *  SYNOPSIS
105 *
106 *  #include "glpenv.h"
107 *  ENV *get_env_ptr(void);
108 *
109 *  DESCRIPTION
110 *
111 *  The routine get_env_ptr retrieves and returns a pointer to the GLPK
112 *  environment block.
113 *
114 *  If the GLPK environment has not been initialized yet, the routine
115 *  performs initialization. If initialization fails, the routine prints
116 *  an error message to stderr and terminates the program.
117 *
118 *  RETURNS
119 *
120 *  The routine returns a pointer to the environment block. */
121 
get_env_ptr(void)122 ENV *get_env_ptr(void)
123 {     ENV *env = tls_get_ptr();
124       /* check if the environment has been initialized */
125       if (env == NULL)
126       {  /* not initialized yet; perform initialization */
127          if (glp_init_env() != 0)
128          {  /* initialization failed; display an error message */
129             fprintf(stderr, "GLPK initialization failed\n");
130             fflush(stderr);
131             /* and abnormally terminate the program */
132             abort();
133          }
134          /* initialization successful; retrieve the pointer */
135          env = tls_get_ptr();
136       }
137       /* check if the environment block is valid */
138       if (env->magic != ENV_MAGIC)
139       {  fprintf(stderr, "Invalid GLPK environment\n");
140          fflush(stderr);
141          abort();
142       }
143       return env;
144 }
145 
146 /***********************************************************************
147 *  NAME
148 *
149 *  glp_version - determine library version
150 *
151 *  SYNOPSIS
152 *
153 *  const char *glp_version(void);
154 *
155 *  RETURNS
156 *
157 *  The routine glp_version returns a pointer to a null-terminated
158 *  character string, which specifies the version of the GLPK library in
159 *  the form "X.Y", where X is the major version number, and Y is the
160 *  minor version number, for example, "4.16". */
161 
glp_version(void)162 const char *glp_version(void)
163 {     ENV *env = get_env_ptr();
164       return env->version;
165 }
166 
167 /***********************************************************************
168 *  NAME
169 *
170 *  glp_free_env - free GLPK environment
171 *
172 *  SYNOPSIS
173 *
174 *  int glp_free_env(void);
175 *
176 *  DESCRIPTION
177 *
178 *  The routine glp_free_env frees all resources used by GLPK routines
179 *  (memory blocks, etc.) which are currently still in use.
180 *
181 *  Normally the application program does not need to call this routine,
182 *  because GLPK routines always free all unused resources. However, if
183 *  the application program even has deleted all problem objects, there
184 *  will be several memory blocks still allocated for the library needs.
185 *  For some reasons the application program may want GLPK to free this
186 *  memory, in which case it should call glp_free_env.
187 *
188 *  Note that a call to glp_free_env invalidates all problem objects as
189 *  if no GLPK routine were called.
190 *
191 *  RETURNS
192 *
193 *  0 - termination successful;
194 *  1 - environment is inactive (was not initialized). */
195 
glp_free_env(void)196 int glp_free_env(void)
197 {     ENV *env = tls_get_ptr();
198       MEM *desc;
199       /* check if the environment is active */
200       if (env == NULL) return 1;
201       /* check if the environment block is valid */
202       if (env->magic != ENV_MAGIC)
203       {  fprintf(stderr, "Invalid GLPK environment\n");
204          fflush(stderr);
205          abort();
206       }
207       /* close handles to shared libraries */
208       if (env->h_odbc != NULL)
209          xdlclose(env->h_odbc);
210       if (env->h_mysql != NULL)
211          xdlclose(env->h_mysql);
212       /* close streams which are still open */
213       while (env->file_ptr != NULL)
214          xfclose(env->file_ptr);
215       /* free memory blocks which are still allocated */
216       while (env->mem_ptr != NULL)
217       {  desc = env->mem_ptr;
218          env->mem_ptr = desc->next;
219          free(desc);
220       }
221       /* invalidate the environment block */
222       env->magic = -1;
223       /* free memory allocated to the environment block */
224       free(env->term_buf);
225       free(env->ioerr_msg);
226       free(env);
227       /* reset a pointer to the environment block */
228       tls_set_ptr(NULL);
229       /* termination successful */
230       return 0;
231 }
232 
233 /* eof */
234