COIN-OR::LEMON - Graph Library

source: glpk-cmake/src/glpenv07.c

Last change on this file was 1:c445c931472f, checked in by Alpar Juttner <alpar@…>, 13 years ago

Import glpk-4.45

  • Generated files and doc/notes are removed
File size: 15.5 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 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
506static void *z_fopen(const char *fname, const char *mode)
507{     xassert(fname == fname);
508      xassert(mode == mode);
509      lib_err_msg("Compressed files not supported");
510      return NULL;
511}
512
513static int z_fgetc(void *fh)
514{     xassert(fh != fh);
515      return 0;
516}
517
518static int z_fputc(int c, void *fh)
519{     xassert(c != c);
520      xassert(fh != fh);
521      return 0;
522}
523
524static int z_ferror(void *fh)
525{     xassert(fh != fh);
526      return 0;
527}
528
529static int z_feof(void *fh)
530{     xassert(fh != fh);
531      return 0;
532}
533
534static int z_fflush(void *fh)
535{     xassert(fh != fh);
536      return 0;
537}
538
539static int z_fclose(void *fh)
540{     xassert(fh != fh);
541      return 0;
542}
543
544#else
545
546#include <zlib.h>
547
548struct z_file
549{     /* .gz file handle */
550      gzFile file;
551      /* pointer to .gz stream */
552      int err;
553      /* i/o error indicator */
554      int eof;
555      /* end-of-file indicator */
556};
557
558static void *z_fopen(const char *fname, const char *mode)
559{     struct z_file *fh;
560      gzFile file;
561      if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0)
562         mode = "rb";
563      else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0)
564         mode = "wb";
565      else
566      {  lib_err_msg("Invalid open mode");
567         fh = NULL;
568         goto done;
569      }
570      file = gzopen(fname, mode);
571      if (file == NULL)
572      {  lib_err_msg(strerror(errno));
573         fh = NULL;
574         goto done;
575      }
576      fh = xmalloc(sizeof(struct z_file));
577      fh->file = file;
578      fh->err = fh->eof = 0;
579done: return fh;
580}
581
582static int z_fgetc(void *_fh)
583{     struct z_file *fh = _fh;
584      int c;
585      if (fh->err || fh->eof)
586      {  c = XEOF;
587         goto done;
588      }
589      c = gzgetc(fh->file);
590      if (c < 0)
591      {  int errnum;
592         const char *msg;
593         msg = gzerror(fh->file, &errnum);
594         if (errnum == Z_STREAM_END)
595            fh->eof = 1;
596         else if (errnum == Z_ERRNO)
597         {  fh->err = 1;
598            lib_err_msg(strerror(errno));
599         }
600         else
601         {  fh->err = 1;
602            lib_err_msg(msg);
603         }
604         c = XEOF;
605      }
606      else
607         xassert(0x00 <= c && c <= 0xFF);
608done: return c;
609}
610
611static int z_fputc(int c, void *_fh)
612{     struct z_file *fh = _fh;
613      if (fh->err)
614      {  c = XEOF;
615         goto done;
616      }
617      c = (unsigned char)c;
618      if (gzputc(fh->file, c) < 0)
619      {  int errnum;
620         const char *msg;
621         fh->err = 1;
622         msg = gzerror(fh->file, &errnum);
623         if (errnum == Z_ERRNO)
624            lib_err_msg(strerror(errno));
625         else
626            lib_err_msg(msg);
627         c = XEOF;
628      }
629done: return c;
630}
631
632static int z_ferror(void *_fh)
633{     struct z_file *fh = _fh;
634      return fh->err;
635}
636
637static int z_feof(void *_fh)
638{     struct z_file *fh = _fh;
639      return fh->eof;
640}
641
642static int z_fflush(void *_fh)
643{     struct z_file *fh = _fh;
644      int ret;
645      ret = gzflush(fh->file, Z_FINISH);
646      if (ret == Z_OK)
647         ret = 0;
648      else
649      {  int errnum;
650         const char *msg;
651         fh->err = 1;
652         msg = gzerror(fh->file, &errnum);
653         if (errnum == Z_ERRNO)
654            lib_err_msg(strerror(errno));
655         else
656            lib_err_msg(msg);
657         ret = XEOF;
658      }
659      return ret;
660}
661
662static int z_fclose(void *_fh)
663{     struct z_file *fh = _fh;
664      gzclose(fh->file);
665      xfree(fh);
666      return 0;
667}
668
669#endif
670
671/* eof */
Note: See TracBrowser for help on using the repository browser.