lemon-project-template-glpk
view deps/glpk/src/glpenv07.c @ 9:33de93886c88
Import GLPK 4.47
author | Alpar Juttner <alpar@cs.elte.hu> |
---|---|
date | Sun, 06 Nov 2011 20:59:10 +0100 |
parents | |
children |
line source
1 /* glpenv07.c (stream input/output) */
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 ***********************************************************************/
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
29 #include "glpenv.h"
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). */
47 void 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 }
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. */
73 const char *xerrmsg(void)
74 { ENV *env = get_env_ptr();
75 return env->ioerr_msg;
76 }
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. */
106 static void *c_fopen(const char *fname, const char *mode);
107 static void *z_fopen(const char *fname, const char *mode);
109 static int is_gz_file(const char *fname)
110 { char *ext = strrchr(fname, '.');
111 return ext != NULL && strcmp(ext, ".gz") == 0;
112 }
114 XFILE *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;
138 done: return fp;
139 }
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. */
171 static int c_fgetc(void *fh);
172 static int z_fgetc(void *fh);
174 int 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 }
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. */
212 static int c_fputc(int c, void *fh);
213 static int z_fputc(int c, void *fh);
215 int 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 }
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. */
249 static int c_ferror(void *fh);
250 static int z_ferror(void *fh);
252 int 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 }
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. */
287 static int c_feof(void *fh);
288 static int z_feof(void *fh);
290 int 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 }
305 int 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 }
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. */
342 static int c_fflush(void *fh);
343 static int z_fflush(void *fh);
345 int 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 }
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. */
381 static int c_fclose(void *fh);
382 static int z_fclose(void *fh);
384 int 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 }
410 /***********************************************************************
411 * The following routines implement stream input/output based on the
412 * standard C streams. */
414 static 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 }
429 static 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);
445 done: return c;
446 }
448 static 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 }
460 done: return c;
461 }
463 static int c_ferror(void *_fh)
464 { FILE *fh = _fh;
465 return ferror(fh);
466 }
468 static int c_feof(void *_fh)
469 { FILE *fh = _fh;
470 return feof(fh);
471 }
473 static 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 }
484 static 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 }
500 /***********************************************************************
501 * The following routines implement stream input/output based on the
502 * zlib library, which provides processing .gz files "on the fly". */
504 /*#ifndef HAVE_ZLIB*/
505 #if 0 /* 27/IV-2011 */
507 static 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 }
514 static int z_fgetc(void *fh)
515 { xassert(fh != fh);
516 return 0;
517 }
519 static int z_fputc(int c, void *fh)
520 { xassert(c != c);
521 xassert(fh != fh);
522 return 0;
523 }
525 static int z_ferror(void *fh)
526 { xassert(fh != fh);
527 return 0;
528 }
530 static int z_feof(void *fh)
531 { xassert(fh != fh);
532 return 0;
533 }
535 static int z_fflush(void *fh)
536 { xassert(fh != fh);
537 return 0;
538 }
540 static int z_fclose(void *fh)
541 { xassert(fh != fh);
542 return 0;
543 }
545 #else
547 #include "zlib/zlib.h"
549 struct 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 };
559 static 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;
580 done: return fh;
581 }
583 static 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);
609 done: return c;
610 }
612 static 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 }
630 done: return c;
631 }
633 static int z_ferror(void *_fh)
634 { struct z_file *fh = _fh;
635 return fh->err;
636 }
638 static int z_feof(void *_fh)
639 { struct z_file *fh = _fh;
640 return fh->eof;
641 }
643 static 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 }
663 static int z_fclose(void *_fh)
664 { struct z_file *fh = _fh;
665 gzclose(fh->file);
666 xfree(fh);
667 return 0;
668 }
670 #endif
672 /* eof */