COIN-OR::LEMON - Graph Library

source: lemon-project-template-glpk/deps/glpk/src/glpenv07.c @ 9:33de93886c88

subpack-glpk
Last change on this file since 9:33de93886c88 was 9:33de93886c88, checked in by Alpar Juttner <alpar@…>, 13 years ago

Import GLPK 4.47

File size: 15.6 KB
Line 
1/* glpenv07.c (stream input/output) */
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, 2011 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#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include "glpenv.h"
30
31/***********************************************************************
32*  NAME
33*
34*  lib_err_msg - save error message string
35*
36*  SYNOPSIS
37*
38*  #include "glpenv.h"
39*  void lib_err_msg(const char *msg);
40*
41*  DESCRIPTION
42*
43*  The routine lib_err_msg saves an error message string specified by
44*  the parameter msg. The message is obtained by some library routines
45*  with a call to strerror(errno). */
46
47void lib_err_msg(const char *msg)
48{     ENV *env = get_env_ptr();
49      int len = strlen(msg);
50      if (len >= IOERR_MSG_SIZE)
51         len = IOERR_MSG_SIZE - 1;
52      memcpy(env->ioerr_msg, msg, len);
53      if (len > 0 && env->ioerr_msg[len-1] == '\n') len--;
54      env->ioerr_msg[len] = '\0';
55      return;
56}
57
58/***********************************************************************
59*  NAME
60*
61*  xerrmsg - retrieve error message string
62*
63*  SYNOPSIS
64*
65*  #include "glpenv.h"
66*  const char *xerrmsg(void);
67*
68*  RETURNS
69*
70*  The routine xerrmsg returns a pointer to an error message string
71*  previously set by some library routine to indicate an error. */
72
73const char *xerrmsg(void)
74{     ENV *env = get_env_ptr();
75      return env->ioerr_msg;
76}
77
78/***********************************************************************
79*  NAME
80*
81*  xfopen - open a stream
82*
83*  SYNOPSIS
84*
85*  #include "glpenv.h"
86*  XFILE *xfopen(const char *fname, const char *mode);
87*
88*  DESCRIPTION
89*
90*  The routine xfopen opens the file whose name is a string pointed to
91*  by fname and associates a stream with it.
92*
93*  The parameter mode points to a string, which indicates the open mode
94*  and should be one of the following:
95*
96*  "r"   open text file for reading;
97*  "w"   truncate to zero length or create text file for writing;
98*  "rb"  open binary file for reading;
99*  "wb"  truncate to zero length or create binary file for writing.
100*
101*  RETURNS
102*
103*  The routine xfopen returns a pointer to the object controlling the
104*  stream. If the open operation fails, xfopen returns NULL. */
105
106static void *c_fopen(const char *fname, const char *mode);
107static void *z_fopen(const char *fname, const char *mode);
108
109static int is_gz_file(const char *fname)
110{     char *ext = strrchr(fname, '.');
111      return ext != NULL && strcmp(ext, ".gz") == 0;
112}
113
114XFILE *xfopen(const char *fname, const char *mode)
115{     ENV *env = get_env_ptr();
116      XFILE *fp;
117      int type;
118      void *fh;
119      if (!is_gz_file(fname))
120      {  type = FH_FILE;
121         fh = c_fopen(fname, mode);
122      }
123      else
124      {  type = FH_ZLIB;
125         fh = z_fopen(fname, mode);
126      }
127      if (fh == NULL)
128      {  fp = NULL;
129         goto done;
130      }
131      fp = xmalloc(sizeof(XFILE));
132      fp->type = type;
133      fp->fh = fh;
134      fp->prev = NULL;
135      fp->next = env->file_ptr;
136      if (fp->next != NULL) fp->next->prev = fp;
137      env->file_ptr = fp;
138done: return fp;
139}
140
141/***********************************************************************
142*  NAME
143*
144*  xfgetc - read character from the stream
145*
146*  SYNOPSIS
147*
148*  #include "glpenv.h"
149*  int xfgetc(XFILE *fp);
150*
151*  DESCRIPTION
152*
153*  If the end-of-file indicator for the input stream pointed to by fp
154*  is not set and a next character is present, the routine xfgetc
155*  obtains that character as an unsigned char converted to an int and
156*  advances the associated file position indicator for the stream (if
157*  defined).
158*
159*  RETURNS
160*
161*  If the end-of-file indicator for the stream is set, or if the
162*  stream is at end-of-file, the end-of-file indicator for the stream
163*  is set and the routine xfgetc returns XEOF. Otherwise, the routine
164*  xfgetc returns the next character from the input stream pointed to
165*  by fp. If a read error occurs, the error indicator for the stream is
166*  set and the xfgetc routine returns XEOF.
167*
168*  Note: An end-of-file and a read error can be distinguished by use of
169*  the routines xfeof and xferror. */
170
171static int c_fgetc(void *fh);
172static int z_fgetc(void *fh);
173
174int xfgetc(XFILE *fp)
175{     int c;
176      switch (fp->type)
177      {  case FH_FILE:
178            c = c_fgetc(fp->fh);
179            break;
180         case FH_ZLIB:
181            c = z_fgetc(fp->fh);
182            break;
183         default:
184            xassert(fp != fp);
185      }
186      return c;
187}
188
189/***********************************************************************
190*  NAME
191*
192*  xfputc - write character to the stream
193*
194*  SYNOPSIS
195*
196*  #include "glpenv.h"
197*  int xfputc(int c, XFILE *fp);
198*
199*  DESCRIPTION
200*
201*  The routine xfputc writes the character specified by c (converted
202*  to an unsigned char) to the output stream pointed to by fp, at the
203*  position indicated by the associated file position indicator (if
204*  defined), and advances the indicator appropriately.
205*
206*  RETURNS
207*
208*  The routine xfputc returns the character written. If a write error
209*  occurs, the error indicator for the stream is set and xfputc returns
210*  XEOF. */
211
212static int c_fputc(int c, void *fh);
213static int z_fputc(int c, void *fh);
214
215int xfputc(int c, XFILE *fp)
216{     switch (fp->type)
217      {  case FH_FILE:
218            c = c_fputc(c, fp->fh);
219            break;
220         case FH_ZLIB:
221            c = z_fputc(c, fp->fh);
222            break;
223         default:
224            xassert(fp != fp);
225      }
226      return c;
227}
228
229/***********************************************************************
230*  NAME
231*
232*  xferror - test error indicator for the stream
233*
234*  SYNOPSIS
235*
236*  #include "glpenv.h"
237*  int xferror(XFILE *fp);
238*
239*  DESCRIPTION
240*
241*  The routine xferror tests the error indicator for the stream
242*  pointed to by fp.
243*
244*  RETURNS
245*
246*  The routine xferror returns non-zero if and only if the error
247*  indicator is set for the stream. */
248
249static int c_ferror(void *fh);
250static int z_ferror(void *fh);
251
252int xferror(XFILE *fp)
253{     int ret;
254      switch (fp->type)
255      {  case FH_FILE:
256            ret = c_ferror(fp->fh);
257            break;
258         case FH_ZLIB:
259            ret = z_ferror(fp->fh);
260            break;
261         default:
262            xassert(fp != fp);
263      }
264      return ret;
265}
266
267/***********************************************************************
268*  NAME
269*
270*  xfeof - test end-of-file indicator for the stream
271*
272*  SYNOPSIS
273*
274*  #include "glpenv.h"
275*  int xfeof(XFILE *fp);
276*
277*  DESCRIPTION
278*
279*  The routine xfeof tests the end-of-file indicator for the stream
280*  pointed to by fp.
281*
282*  RETURNS
283*
284*  The routine xfeof returns non-zero if and only if the end-of-file
285*  indicator is set for the stream. */
286
287static int c_feof(void *fh);
288static int z_feof(void *fh);
289
290int xfeof(XFILE *fp)
291{     int ret;
292      switch (fp->type)
293      {  case FH_FILE:
294            ret = c_feof(fp->fh);
295            break;
296         case FH_ZLIB:
297            ret = z_feof(fp->fh);
298            break;
299         default:
300            xassert(fp != fp);
301      }
302      return ret;
303}
304
305int xfprintf(XFILE *file, const char *fmt, ...)
306{     ENV *env = get_env_ptr();
307      int cnt, j;
308      va_list arg;
309      va_start(arg, fmt);
310      cnt = vsprintf(env->term_buf, fmt, arg);
311      va_end(arg);
312      for (j = 0; j < cnt; j++)
313      {  if (xfputc(env->term_buf[j], file) < 0)
314         {  cnt = -1;
315            break;
316         }
317      }
318      return cnt;
319}
320
321/***********************************************************************
322*  NAME
323*
324*  xfflush - flush the stream
325*
326*  SYNOPSIS
327*
328*  #include "glpenv.h"
329*  int xfflush(XFILE *fp);
330*
331*  DESCRIPTION
332*
333*  The routine xfflush causes any unwritten data for the output stream
334*  pointed to by fp to be written to the associated file.
335*
336*  RETURNS
337*
338*  The routine xfflush returns zero if the stream was successfully
339*  flushed. Otherwise, xfflush sets the error indicator for the stream
340*  and returns XEOF. */
341
342static int c_fflush(void *fh);
343static int z_fflush(void *fh);
344
345int xfflush(XFILE *fp)
346{     int ret;
347      switch (fp->type)
348      {  case FH_FILE:
349            ret = c_fflush(fp->fh);
350            break;
351         case FH_ZLIB:
352            ret = z_fflush(fp->fh);
353            break;
354         default:
355            xassert(fp != fp);
356      }
357      return ret;
358}
359
360/***********************************************************************
361*  NAME
362*
363*  xfclose - close the stream
364*
365*  SYNOPSIS
366*
367*  #include "glpenv.h"
368*  int xfclose(XFILE *fp);
369*
370*  DESCRIPTION
371*
372*  A successful call to the routine xfclose causes the stream pointed
373*  to by fp to be flushed and the associated file to be closed. Whether
374*  or not the call succeeds, the stream is disassociated from the file.
375*
376*  RETURNS
377*
378*  The routine xfclose returns zero if the stream was successfully
379*  closed, or XEOF if any errors were detected. */
380
381static int c_fclose(void *fh);
382static int z_fclose(void *fh);
383
384int xfclose(XFILE *fp)
385{     ENV *env = get_env_ptr();
386      int ret;
387      switch (fp->type)
388      {  case FH_FILE:
389            ret = c_fclose(fp->fh);
390            break;
391         case FH_ZLIB:
392            ret = z_fclose(fp->fh);
393            break;
394         default:
395            xassert(fp != fp);
396      }
397      fp->type = 0xF00BAD;
398      if (fp->prev == NULL)
399         env->file_ptr = fp->next;
400      else
401         fp->prev->next = fp->next;
402      if (fp->next == NULL)
403         ;
404      else
405         fp->next->prev = fp->prev;
406      xfree(fp);
407      return ret;
408}
409
410/***********************************************************************
411*  The following routines implement stream input/output based on the
412*  standard C streams. */
413
414static void *c_fopen(const char *fname, const char *mode)
415{     FILE *fh;
416      if (strcmp(fname, "/dev/stdin") == 0)
417         fh = stdin;
418      else if (strcmp(fname, "/dev/stdout") == 0)
419         fh = stdout;
420      else if (strcmp(fname, "/dev/stderr") == 0)
421         fh = stderr;
422      else
423         fh = fopen(fname, mode);
424      if (fh == NULL)
425         lib_err_msg(strerror(errno));
426      return fh;
427}
428
429static int c_fgetc(void *_fh)
430{     FILE *fh = _fh;
431      int c;
432      if (ferror(fh) || feof(fh))
433      {  c = XEOF;
434         goto done;
435      }
436      c = fgetc(fh);
437      if (ferror(fh))
438      {  lib_err_msg(strerror(errno));
439         c = XEOF;
440      }
441      else if (feof(fh))
442         c = XEOF;
443      else
444         xassert(0x00 <= c && c <= 0xFF);
445done: return c;
446}
447
448static int c_fputc(int c, void *_fh)
449{     FILE *fh = _fh;
450      if (ferror(fh))
451      {  c = XEOF;
452         goto done;
453      }
454      c = (unsigned char)c;
455      fputc(c, fh);
456      if (ferror(fh))
457      {  lib_err_msg(strerror(errno));
458         c = XEOF;
459      }
460done: return c;
461}
462
463static int c_ferror(void *_fh)
464{     FILE *fh = _fh;
465      return ferror(fh);
466}
467
468static int c_feof(void *_fh)
469{     FILE *fh = _fh;
470      return feof(fh);
471}
472
473static int c_fflush(void *_fh)
474{     FILE *fh = _fh;
475      int ret;
476      ret = fflush(fh);
477      if (ret != 0)
478      {  lib_err_msg(strerror(errno));
479         ret = XEOF;
480      }
481      return ret;
482}
483
484static int c_fclose(void *_fh)
485{     FILE *fh = _fh;
486      int ret;
487      if (fh == stdin)
488         ret = 0;
489      else if (fh == stdout || fh == stderr)
490         fflush(fh), ret = 0;
491      else
492         ret = fclose(fh);
493      if (ret != 0)
494      {  lib_err_msg(strerror(errno));
495         ret = XEOF;
496      }
497      return ret;
498}
499
500/***********************************************************************
501*  The following routines implement stream input/output based on the
502*  zlib library, which provides processing .gz files "on the fly". */
503
504/*#ifndef HAVE_ZLIB*/
505#if 0 /* 27/IV-2011 */
506
507static void *z_fopen(const char *fname, const char *mode)
508{     xassert(fname == fname);
509      xassert(mode == mode);
510      lib_err_msg("Compressed files not supported");
511      return NULL;
512}
513
514static int z_fgetc(void *fh)
515{     xassert(fh != fh);
516      return 0;
517}
518
519static int z_fputc(int c, void *fh)
520{     xassert(c != c);
521      xassert(fh != fh);
522      return 0;
523}
524
525static int z_ferror(void *fh)
526{     xassert(fh != fh);
527      return 0;
528}
529
530static int z_feof(void *fh)
531{     xassert(fh != fh);
532      return 0;
533}
534
535static int z_fflush(void *fh)
536{     xassert(fh != fh);
537      return 0;
538}
539
540static int z_fclose(void *fh)
541{     xassert(fh != fh);
542      return 0;
543}
544
545#else
546
547#include "zlib/zlib.h"
548
549struct z_file
550{     /* .gz file handle */
551      gzFile file;
552      /* pointer to .gz stream */
553      int err;
554      /* i/o error indicator */
555      int eof;
556      /* end-of-file indicator */
557};
558
559static void *z_fopen(const char *fname, const char *mode)
560{     struct z_file *fh;
561      gzFile file;
562      if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0)
563         mode = "rb";
564      else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0)
565         mode = "wb";
566      else
567      {  lib_err_msg("Invalid open mode");
568         fh = NULL;
569         goto done;
570      }
571      file = gzopen(fname, mode);
572      if (file == NULL)
573      {  lib_err_msg(strerror(errno));
574         fh = NULL;
575         goto done;
576      }
577      fh = xmalloc(sizeof(struct z_file));
578      fh->file = file;
579      fh->err = fh->eof = 0;
580done: return fh;
581}
582
583static int z_fgetc(void *_fh)
584{     struct z_file *fh = _fh;
585      int c;
586      if (fh->err || fh->eof)
587      {  c = XEOF;
588         goto done;
589      }
590      c = gzgetc(fh->file);
591      if (c < 0)
592      {  int errnum;
593         const char *msg;
594         msg = gzerror(fh->file, &errnum);
595         if (errnum == Z_STREAM_END)
596            fh->eof = 1;
597         else if (errnum == Z_ERRNO)
598         {  fh->err = 1;
599            lib_err_msg(strerror(errno));
600         }
601         else
602         {  fh->err = 1;
603            lib_err_msg(msg);
604         }
605         c = XEOF;
606      }
607      else
608         xassert(0x00 <= c && c <= 0xFF);
609done: return c;
610}
611
612static int z_fputc(int c, void *_fh)
613{     struct z_file *fh = _fh;
614      if (fh->err)
615      {  c = XEOF;
616         goto done;
617      }
618      c = (unsigned char)c;
619      if (gzputc(fh->file, c) < 0)
620      {  int errnum;
621         const char *msg;
622         fh->err = 1;
623         msg = gzerror(fh->file, &errnum);
624         if (errnum == Z_ERRNO)
625            lib_err_msg(strerror(errno));
626         else
627            lib_err_msg(msg);
628         c = XEOF;
629      }
630done: return c;
631}
632
633static int z_ferror(void *_fh)
634{     struct z_file *fh = _fh;
635      return fh->err;
636}
637
638static int z_feof(void *_fh)
639{     struct z_file *fh = _fh;
640      return fh->eof;
641}
642
643static int z_fflush(void *_fh)
644{     struct z_file *fh = _fh;
645      int ret;
646      ret = gzflush(fh->file, Z_FINISH);
647      if (ret == Z_OK)
648         ret = 0;
649      else
650      {  int errnum;
651         const char *msg;
652         fh->err = 1;
653         msg = gzerror(fh->file, &errnum);
654         if (errnum == Z_ERRNO)
655            lib_err_msg(strerror(errno));
656         else
657            lib_err_msg(msg);
658         ret = XEOF;
659      }
660      return ret;
661}
662
663static int z_fclose(void *_fh)
664{     struct z_file *fh = _fh;
665      gzclose(fh->file);
666      xfree(fh);
667      return 0;
668}
669
670#endif
671
672/* eof */
Note: See TracBrowser for help on using the repository browser.