1 /* dimacs.c (reading data in DIMACS format) */
2 
3 /***********************************************************************
4 *  This code is part of GLPK (GNU Linear Programming Kit).
5 *  Copyright (C) 2009-2015 Free Software Foundation, Inc.
6 *  Written by Andrew Makhorin <mao@gnu.org>.
7 *
8 *  GLPK is free software: you can redistribute it and/or modify it
9 *  under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation, either version 3 of the License, or
11 *  (at your option) any later version.
12 *
13 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
14 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 *  License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
20 ***********************************************************************/
21 
22 #include "dimacs.h"
23 
dmx_error(DMX * csa,const char * fmt,...)24 void dmx_error(DMX *csa, const char *fmt, ...)
25 {     /* print error message and terminate processing */
26       va_list arg;
27       xprintf("%s:%d: error: ", csa->fname, csa->count);
28       va_start(arg, fmt);
29       xvprintf(fmt, arg);
30       va_end(arg);
31       xprintf("\n");
32       longjmp(csa->jump, 1);
33       /* no return */
34 }
35 
dmx_warning(DMX * csa,const char * fmt,...)36 void dmx_warning(DMX *csa, const char *fmt, ...)
37 {     /* print warning message and continue processing */
38       va_list arg;
39       xprintf("%s:%d: warning: ", csa->fname, csa->count);
40       va_start(arg, fmt);
41       xvprintf(fmt, arg);
42       va_end(arg);
43       xprintf("\n");
44       return;
45 }
46 
dmx_read_char(DMX * csa)47 void dmx_read_char(DMX *csa)
48 {     /* read character from input text file */
49       int c;
50       if (csa->c == '\n') csa->count++;
51       c = glp_getc(csa->fp);
52       if (c < 0)
53       {  if (glp_ioerr(csa->fp))
54             dmx_error(csa, "read error - %s", get_err_msg());
55          else if (csa->c == '\n')
56             dmx_error(csa, "unexpected end of file");
57          else
58          {  dmx_warning(csa, "missing final end of line");
59             c = '\n';
60          }
61       }
62       else if (c == '\n')
63          ;
64       else if (isspace(c))
65          c = ' ';
66       else if (iscntrl(c))
67          dmx_error(csa, "invalid control character 0x%02X", c);
68       csa->c = c;
69       return;
70 }
71 
dmx_read_designator(DMX * csa)72 void dmx_read_designator(DMX *csa)
73 {     /* read one-character line designator */
74       xassert(csa->c == '\n');
75       dmx_read_char(csa);
76       for (;;)
77       {  /* skip preceding white-space characters */
78          while (csa->c == ' ')
79             dmx_read_char(csa);
80          if (csa->c == '\n')
81          {  /* ignore empty line */
82             if (!csa->empty)
83             {  dmx_warning(csa, "empty line ignored");
84                csa->empty = 1;
85             }
86             dmx_read_char(csa);
87          }
88          else if (csa->c == 'c')
89          {  /* skip comment line */
90             while (csa->c != '\n')
91                dmx_read_char(csa);
92             dmx_read_char(csa);
93          }
94          else
95          {  /* hmm... looks like a line designator */
96             csa->field[0] = (char)csa->c, csa->field[1] = '\0';
97             /* check that it is followed by a white-space character */
98             dmx_read_char(csa);
99             if (!(csa->c == ' ' || csa->c == '\n'))
100                dmx_error(csa, "line designator missing or invalid");
101             break;
102          }
103       }
104       return;
105 }
106 
dmx_read_field(DMX * csa)107 void dmx_read_field(DMX *csa)
108 {     /* read data field */
109       int len = 0;
110       /* skip preceding white-space characters */
111       while (csa->c == ' ')
112          dmx_read_char(csa);
113       /* scan data field */
114       if (csa->c == '\n')
115          dmx_error(csa, "unexpected end of line");
116       while (!(csa->c == ' ' || csa->c == '\n'))
117       {  if (len == sizeof(csa->field)-1)
118             dmx_error(csa, "data field '%.15s...' too long",
119                csa->field);
120          csa->field[len++] = (char)csa->c;
121          dmx_read_char(csa);
122       }
123       csa->field[len] = '\0';
124       return;
125 }
126 
dmx_end_of_line(DMX * csa)127 void dmx_end_of_line(DMX *csa)
128 {     /* skip white-space characters until end of line */
129       while (csa->c == ' ')
130          dmx_read_char(csa);
131       if (csa->c != '\n')
132          dmx_error(csa, "too many data fields specified");
133       return;
134 }
135 
dmx_check_int(DMX * csa,double num)136 void dmx_check_int(DMX *csa, double num)
137 {     /* print a warning if non-integer data are detected */
138       if (!csa->nonint && num != floor(num))
139       {  dmx_warning(csa, "non-integer data detected");
140          csa->nonint = 1;
141       }
142       return;
143 }
144 
145 /* eof */
146