1 /****************************************************************
2 Copyright (C) 1997, 1999,2000 Lucent Technologies
3 All Rights Reserved
4 
5 Permission to use, copy, modify, and distribute this software and
6 its documentation for any purpose and without fee is hereby
7 granted, provided that the above copyright notice appear in all
8 copies and that both that the copyright notice and this
9 permission notice and warranty disclaimer appear in supporting
10 documentation, and that the name of Lucent or any of its entities
11 not be used in advertising or publicity pertaining to
12 distribution of the software without specific, written prior
13 permission.
14 
15 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22 THIS SOFTWARE.
23 ****************************************************************/
24 
25 #include "nlp.h"
26 
27 #define MSGGULP 1024
28 
29  typedef struct
30 msginfo {
31 	char *msg;
32 	char *msg0;
33 	char *msgend;
34 	ftnlen msglen;
35 	} msginfo;
36 
37  static void
38 #ifdef KR_headers
msgput(m,b,n)39 msgput(m, b, n) msginfo *m; char *b; int n;
40 #else
41 msgput(msginfo *m, char *b, int n)
42 #endif
43 {
44 	char *be, *msg, *msg0, *msgend;
45 	ftnlen msglen0;
46 
47 	msg = m->msg;
48 	msgend = m->msgend;
49 	be = b + n;
50 	while(b < be) {
51 		if (msg >= msgend) {
52 			msglen0 = m->msglen;
53 			msg0 = m->msg0 = (char*)
54 				Realloc(m->msg0, m->msglen += MSGGULP);
55 			msg = msg0 + msglen0;
56 			m->msgend = msg0 + m->msglen;
57 			}
58 		*msg++ = *b++;
59 		}
60 	m->msg = msg;
61 	}
62 
63  static void
64 #ifdef KR_headers
badnumber(asl,a,b,what)65 badnumber(asl, a, b, what) ASL *asl; fint a, b; char *what;
66 #else
67 badnumber(ASL *asl, fint a, fint b, char *what)
68 #endif
69 {
70 	fprintf(Stderr, "%s indicates %ld rather than %ld %s\n",
71 		filename, (long)a, (long)b, what);
72 	fflush(Stderr);
73 	}
74 
75  static int
76 #ifdef KR_headers
decstring(buf,val)77 decstring(buf, val) char *buf; real *val;
78 #else
79 decstring(char *buf, real *val)
80 #endif
81 {
82 	char *be;
83 	register int c;
84 
85 	*val = strtod(buf, &be);
86 	return be <= buf || ((c = be[-1]) < '0' || c > '9') && c != '.';
87 	}
88 
89  char *
90 #ifdef KR_headers
read_sol_ASL(asl,xp,yp)91 read_sol_ASL(asl, xp, yp) ASL *asl; real **xp, **yp;
92 #else
93 read_sol_ASL(ASL *asl, real **xp, real **yp)
94 #endif
95 {
96 	int binary, flag1, i, j, je, n, need_vbtol;
97 	FILE *f;
98 	char buf[512], *s, *se;
99 	real vbtol, *y;
100 	ftnlen L, L1, L2;
101 	fint Objno[2], nOpts, *z;
102 	msginfo mi;
103 
104 	if (!asl || asl->i.ASLtype < 1 || asl->i.ASLtype > 5)
105 		badasl_ASL(asl,0,"read_soln");
106 	strcpy(stub_end, ".sol");
107 	f = fopen(filename, "rb");
108 	if (!f) {
109 		fprintf(Stderr, "Can't open %s\n", filename);
110 		fflush(Stderr);
111 		return 0;
112 		}
113 	if (fread(&L, sizeof(ftnlen), 1, f) && L == 6) {
114 		/* binary files may be written by Fortran unformatted writes */
115 		binary = 1;
116 		if (!fread(buf, 6, 1, f)
117 		 || strncmp(buf,"binary",6)
118 		 || !fread(&L, sizeof(ftnlen), 1, f)
119 		 || L != 6) {
120  badbinary:
121 			fprintf(Stderr, "bad binary file %s\n", filename);
122 			fflush(Stderr);
123 			goto done;
124 			}
125 		}
126 	else {
127 		binary = 0;
128 		rewind(f);
129 		}
130 
131 	/* Read termination msg */
132 	nOpts = i = need_vbtol = 0;
133 	mi.msg = mi.msg0 = (char *)Malloc(mi.msglen = MSGGULP);
134 	mi.msgend = mi.msg0 + MSGGULP;
135 	if (binary) {
136 		for(;; i++) {
137 			if (!fread(&L,sizeof(ftnlen),1,f))
138 				goto early_eof;
139 			if (L1 = L) {
140 				do {
141 					n = L < sizeof(buf) ? (int)L : (int)sizeof(buf);
142 					L -= n;
143 					if (!fread(buf, n, 1, f))
144 						goto early_eof;
145 					if (!L) {
146 						while(--n >= 0 && buf[n] == ' ');
147 						n++;
148 						}
149 					msgput(&mi, buf, n);
150 					}
151 					while(L);
152 				msgput(&mi, "\n", 1);
153 				}
154 			if (!fread(&L, sizeof(ftnlen), 1, f))
155 				goto early_eof;
156 			if (L != L1)
157 				goto badbinary;
158 			if (!L)
159 				break;
160 			}
161 		L1 = n_con * sizeof(real);
162 		if (!fread(&L, sizeof(ftnlen), 1, f))
163 			goto badbinary;
164 		if (L == 8*sizeof(fint) + 7
165 		 || L == 9*sizeof(fint) + 7
166 		 || L == 8*sizeof(fint) + 7 + sizeof(real)
167 		 || L == 9*sizeof(fint) + 7 + sizeof(real)) {
168 			/* check for Options */
169 			if (!fread(buf, 7, 1, f))
170 				goto badbinary;
171 			if (strncmp(buf, "Options", 7))
172 				goto badbinary;
173 			if (!fread(&nOpts, sizeof(fint), 1, f))
174 				goto badbinary;
175 			if (nOpts < 3 || nOpts > 6) {
176  bad_nOpts:
177 				fprintf(Stderr,
178 				"expected nOpts between 3 and 6; got %ld: ",
179 					(long)nOpts);
180 				goto badbinary;
181 				}
182 			if (nOpts > 4) {
183 				nOpts -= 2;
184 				need_vbtol = 1;
185 				}
186 			if (!fread((ampl_options+1), sizeof(fint),
187 					(size_t)(nOpts+4), f))
188 				goto badbinary;
189 			if (need_vbtol
190 			 && !fread(&vbtol, sizeof(real), 1, f))
191 				goto badbinary;
192 			if (!fread(&L2, sizeof(ftnlen), 1, f)
193 				|| L != L2)
194 				goto badbinary;
195 			}
196 		else if (L != L1)
197 			goto badbinary;
198 		}
199 	else {
200 		for(;; i++) {
201 			if (!fgets(buf, sizeof(buf), f)) {
202  early_eof:
203 				fprintf(Stderr,
204 					"early end of file reading %s\n",
205 					filename);
206 				fflush(Stderr);
207  done:
208 				fclose(f);
209 				return 0;
210 				}
211 			if (*buf == '\n' || *buf == '\r' && buf[1] == '\n')
212 				break;
213 			msgput(&mi, buf, strlen(buf));
214 			}
215 		while((j = getc(f)) == '\n');
216 		if (j != 'O')
217 			ungetc(j,f);
218 		else {
219 			if (!fgets(buf, sizeof(buf), f))
220 				goto early_eof;
221 			if (!strncmp(buf, "ptions", 6)) {
222 				if (!fgets(buf, sizeof(buf), f))
223 					goto early_eof;
224 				nOpts = strtol(buf,&se,10);
225 				if (se == buf)
226 					goto badline;
227 				if (nOpts < 3 || nOpts > 6)
228 					goto bad_nOpts;
229 				if (nOpts > 4) {
230 					nOpts -= 2;
231 					need_vbtol = 1;
232 					}
233 				je = (int)nOpts + 4;
234 				for(j = 1; j <= je; j++) {
235 					if (!fgets(buf, sizeof(buf), f))
236 						goto early_eof;
237 					ampl_options[j] = strtol(buf,&se,10);
238 					if (se == buf)
239 						goto badline;
240 					}
241 				if (need_vbtol && !fgets(buf, sizeof(buf), f))
242 					goto early_eof;
243 				/* We don't do anything here with vbtol, */
244 				/* so we don't bother converting it. */
245 				}
246 			}
247 		}
248 	msgput(&mi, "", 1);	/* add null to end */
249 
250 	if (i)
251 		fflush(stdout);
252 
253 	if (ampl_options[0] = nOpts) {
254 		z = ampl_options + nOpts + 1;
255 		j = (int)z[3];
256 		if (j > n_var || j < 0) {
257 			badnumber(asl, j, n_var, "variables");
258 			goto done;
259 			}
260 		j = (int)z[1];
261 		if (j > n_con || j < 0) {
262 			badnumber(asl, j, n_con, "constraints");
263 			goto done;
264 			}
265 		if (binary) {
266 			L1 = j * sizeof(real);
267 			if (!fread(&L, sizeof(ftnlen), 1, f))
268 				goto badbinary;
269 			if (L != L1)
270 				goto badbinary;
271 			}
272 		}
273 	else
274 		j = n_con;
275 	if (!j) {
276 		*yp = 0;
277 		goto get_x;
278 		}
279 	y = *yp = (real *)Malloc(n_con * sizeof(real));
280 	if (binary) {
281 		if (fread(y, sizeof(real), j, f) != j)
282 			goto early_eof;
283 		if (!fread(&L, sizeof(ftnlen), 1, f) || L != L1)
284 			goto badbinary;
285 		y += j;
286 		}
287 	else for(i = 0; i < j; i++) {
288 		if (!fgets(buf, sizeof(buf), f))
289 			goto early_eof;
290 		if (!decstring(buf, y++))
291 			continue;
292  badline:
293 		fprintf(Stderr, "bad line in %s: %s", filename, buf);
294 		fflush(Stderr);
295 		goto done;
296 		}
297 	y = *yp;
298 	while(j < n_con)
299 		y[j++] = 0;
300  get_x:
301 	Objno[0] = 0;
302 	Objno[1] = -1;
303 	flag1 = asl->i.flags & ~1;;
304 	if (!(j = nOpts ? (int)z[3] : n_var)) {
305 		*xp = 0;
306 		goto ret;
307 		}
308 	y = *xp = (real *)Malloc(n_var*sizeof(real));
309 
310 	if (binary) {
311 		L1 = j * sizeof(real);
312 		if (!fread(&L, sizeof(ftnlen), 1, f) || L != L1)
313 			goto badbinary;
314 		if (fread(y, sizeof(real), j, f) != j)
315 			goto early_eof;
316 		y += j;
317 		/* do we have an obj_no ? */
318 		if (!fread(&L, sizeof(ftnlen), 1, f) || L != L1)
319 			goto badbinary;
320 		if (fread(&L, sizeof(ftnlen), 1, f)) {
321 			i = 1;
322 			if (L == 2*sizeof(fint)) {
323 				i = 2;
324 				flag1 |= 1;
325 				}
326 			else if (L != sizeof(fint))
327 				goto badbinary;
328 			if (!fread(Objno, i*sizeof(fint), 1, f))
329 				goto badbinary;
330 			}
331 		}
332 	else {
333 		for(i = j; i > 0; i--) {
334 			if (!fgets(buf, sizeof(buf), f))
335 				goto early_eof;
336 			if (decstring(buf, y++))
337 				goto badline;
338 			}
339 		if (fgets(buf,sizeof(buf), f)) {
340 			if (strncmp(buf,"objno ",6)) {
341  extra_line:
342 				fprintf(Stderr, "Bug: extra line in %s:\n%s",
343 					filename, buf);
344 				fflush(Stderr);
345 				}
346 			else {
347 				Objno[0] = strtol(buf+6, &se, 10);
348 				if (se == buf+6 || *se > ' ')
349 					goto extra_line;
350 				if (*se == ' ') {
351 					Objno[1] = strtol(se,&s,10);
352 					if (s == se || *s > ' ')
353 						goto extra_line;
354 					flag1 |= 1;
355 					}
356 				}
357 			}
358 		}
359 	asl->i.flags = flag1;
360 	obj_no = (int)Objno[0];
361 	solve_result_num = (int)Objno[1];
362 	y = *xp;
363 	while(j < n_var)
364 		y[j++] = 0;
365  ret:
366 	fclose(f);
367 	return (char*)Realloc(mi.msg0, mi.msglen);
368 	}
369