00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "qs_config.h"
00032 #include "mpf_iqsutil.h"
00033 #include "mpf_rawlp.h"
00034 #include "mpf_read_mps.h"
00035 #include "mpf_read_lp.h"
00036 #include "mpf_format.h"
00037 #ifdef USEDMALLOC
00038 #include "dmalloc.h"
00039 #endif
00040 static int TRACE = 0;
00041
00042 #define mpf_END_LINE(p) (((*(p)) == '$' || (*(p)) == '\n' || (*(p)) == '\0') ? 1 : 0)
00043
00044 static int mpf_mps_skip_comment (
00045 mpf_ILLread_mps_state * state);
00046 static char mpf_ILLmps_next_field_is_number (
00047 mpf_ILLread_mps_state * state);
00048
00049 int mpf_ILLmps_state_init (
00050 mpf_ILLread_mps_state * state,
00051 mpf_qsline_reader * file,
00052 const char *mpf_fname)
00053 {
00054 int i, rval = 0;
00055
00056 ILL_FAILtrue (file == 0, "need file");
00057 state->p = 0;
00058 state->file_name = mpf_fname;
00059 state->file = file;
00060
00061 for (i = 0; i < ILL_MPS_N_SECTIONS; i++)
00062 {
00063 state->section[i] = 0;
00064 }
00065 state->active = ILL_MPS_NONE;
00066 state->intvar = 0;
00067 state->sosvar = 0;
00068 state->line_num = 0;
00069 state->p = 0;
00070
00071 state->obj = 0;
00072 state->line[0] = '\0';
00073 state->key[0] = '\0';
00074 state->field[0] = '\0';
00075
00076 CLEANUP:
00077 ILL_RESULT (rval, "mpf_ILLmps_state_init");
00078 }
00079
00080 int mpf_ILLmps_next_line (
00081 mpf_ILLread_mps_state * state)
00082 {
00083 int rval = 0;
00084
00085
00086 state->line[0] = '\0';
00087 state->p = 0;
00088 while (mpf_ILLline_reader_get (state->line, ILL_namebufsize - 2, state->file)
00089 != 0)
00090 {
00091 state->line_num++;
00092 state->key[0] = '\0';
00093 state->field[0] = '\0';
00094 state->field_num = 1;
00095 state->p = state->line;
00096 if (!mpf_ILL_ISBLANK ((state->line)))
00097 {
00098 if (state->line[0] == '*' || state->line[0] == '\n')
00099 {
00100 continue;
00101 }
00102 else
00103 {
00104 if (sscanf (state->p, "%s", state->key) == 1)
00105 {
00106 state->p += strlen (state->key);
00107 while (mpf_ILL_ISBLANK (state->p))
00108 {
00109 state->p++;
00110 }
00111 if (sscanf (state->p, "%s", state->field) == 1)
00112 {
00113 state->p += strlen (state->field);
00114 }
00115 else
00116 {
00117 ILL_FAILfalse (state->field[0] == '\0', "sscanf problem?");
00118 }
00119 }
00120 else
00121 {
00122 ILL_FAILfalse (0, "should almost never happen");
00123 }
00124 }
00125 }
00126 else
00127 {
00128 while (mpf_ILL_ISBLANK (state->p))
00129 {
00130 state->p++;
00131 }
00132 if (sscanf (state->p, "%s", state->field) < 1)
00133 {
00134 continue;
00135 }
00136 else
00137 {
00138 if (state->field[0] == '\0')
00139 {
00140 continue;
00141 }
00142 state->p += strlen (state->field);
00143 }
00144 }
00145 return 0;
00146 }
00147 CLEANUP:
00148 return 1;
00149 }
00150
00151
00152
00153
00154
00155
00156 static int mpf_mps_skip_comment (
00157 mpf_ILLread_mps_state * state)
00158 {
00159 int rval;
00160
00161 while (mpf_ILL_ISBLANK (state->p))
00162 {
00163 state->p++;
00164 }
00165 rval = ((*state->p == '$') && (state->field_num >= 2) &&
00166 (state->field_num % 2 == 0));
00167 return rval;
00168 }
00169
00170 int mpf_ILLmps_next_field (
00171 mpf_ILLread_mps_state * state)
00172 {
00173 state->field[0] = '\0';
00174 if (!mpf_mps_skip_comment (state))
00175 {
00176 if (sscanf (state->p, "%s", state->field) == 1)
00177 {
00178 state->p += strlen (state->field) + 1;
00179 state->field_num++;
00180 return 0;
00181 }
00182 }
00183 return 1;
00184 }
00185
00186 static char mpf_get_double (
00187 mpf_ILLread_mps_state * state,
00188 int peek,
00189 mpf_t * coef)
00190 {
00191 char ok = 0;
00192 int len, rval = 0;
00193
00194 ILL_FAILfalse (state != 0, "must have state");
00195 if (mpf_mps_skip_comment (state))
00196 return 0;
00197 len = mpf_ILLget_value (state->p, coef);
00198 if (len > 0)
00199 {
00200 if (!peek)
00201 {
00202 state->p += len;
00203 state->field_num++;
00204 }
00205 ok = 1;
00206 }
00207 CLEANUP:
00208 ILL_RESULT (ok, "mpf_get_double");
00209 }
00210
00211 int mpf_ILLmps_next_coef (
00212 mpf_ILLread_mps_state * state,
00213 mpf_t * coef)
00214 {
00215 int len = 0;
00216
00217 if (!mpf_mps_skip_comment (state))
00218 {
00219 len = mpf_get_double (state, 0, coef);
00220 }
00221 ILL_RESULT (!(len > 0), "mpf_ILLmps_next_coef");
00222 }
00223
00224 int mpf_ILLmps_next_bound (
00225 mpf_ILLread_mps_state * state,
00226 mpf_t * coef)
00227 {
00228 int len = 0, sign = 1;
00229 char c, *p;
00230
00231 if (!mpf_mps_skip_comment (state))
00232 {
00233 c = *state->p;
00234 if (c == '-')
00235 {
00236 sign = -1;
00237 len = 1;
00238 }
00239 else
00240 {
00241 if (c == '+')
00242 {
00243 len = 1;
00244 }
00245 }
00246 if (!strncasecmp (state->p + len, "INFINITY", (size_t) 8))
00247 {
00248 len += 8;
00249 }
00250 else
00251 {
00252 if (!strncasecmp (state->p + len, "INF", (size_t) 3))
00253 {
00254 len += 3;
00255 }
00256 }
00257 if (len > 1)
00258 {
00259 state->p += len;
00260 p = state->p;
00261 mpf_mps_skip_comment (state);
00262 if (!mpf_END_LINE (state->p) && p == state->p)
00263 {
00264
00265
00266 state->p -= len;
00267 return 1;
00268 }
00269 else
00270 {
00271 if (sign == 1)
00272 mpf_EGlpNumCopy (*coef, mpf_ILL_MAXDOUBLE);
00273 else
00274 mpf_EGlpNumCopy (*coef, mpf_ILL_MINDOUBLE);
00275 state->field_num++;
00276 ILL_RESULT (0, "mpf_ILLmps_next_bound");
00277 }
00278 }
00279 if (mpf_get_double (state, 0, coef))
00280 {
00281 ILL_RESULT (0, "mpf_ILLmps_next_bound");
00282 }
00283 else
00284 {
00285 ILL_RESULT (1, "mpf_ILLmps_next_bound");
00286 }
00287 }
00288 ILL_RETURN (1, "mpf_ILLmps_next_bound");
00289 }
00290
00291 static char mpf_ILLmps_next_field_is_number (
00292 mpf_ILLread_mps_state * state)
00293 {
00294 mpf_t d;
00295 int len = 0;
00296
00297 if (!mpf_mps_skip_comment (state))
00298 {
00299 mpf_EGlpNumInitVar (d);
00300 len = mpf_get_double (state, 1, &d);
00301 mpf_EGlpNumClearVar (d);
00302 }
00303 return (len > 0);
00304 }
00305
00306 void mpf_ILLmps_check_end_of_line (
00307 mpf_ILLread_mps_state * state)
00308 {
00309 if (!mpf_mps_skip_comment (state))
00310 {
00311 if (!mpf_END_LINE (state->p))
00312 {
00313 mpf_ILLmps_warn (state, "Extra fields on line.");
00314 }
00315 }
00316 }
00317
00318 void mpf_ILLmps_set_end_of_line (
00319 mpf_ILLread_mps_state * state)
00320 {
00321 *state->p = '\n';
00322 }
00323
00324 int mpf_ILLmps_set_section (
00325 mpf_ILLread_mps_state * state,
00326 const ILLmps_section sec)
00327 {
00328 int rval = 0;
00329
00330 ILL_FAILfalse (sec != ILL_MPS_NONE, "must be in a proper section");
00331 if (state->section[sec])
00332 {
00333 rval = mpf_ILLmps_error (state, "Two %s sections.\n", mpf_ILLmps_section_name[sec]);
00334 }
00335 state->section[sec]++;
00336 state->active = sec;
00337 CLEANUP:
00338 ILL_RESULT (rval, "mpf_ILLmps_set_section");
00339 }
00340
00341 int mpf_ILLmps_int_sos_mode (
00342 mpf_ILLread_mps_state * state)
00343 {
00344 if (!strcmp (state->field, "'INTORG'"))
00345 {
00346 if (state->intvar)
00347 {
00348 return !mpf_ILLmps_error (state, "'INTEND' expected.\n");
00349 }
00350 else
00351 {
00352 state->intvar = 1;
00353 ILL_RESULT (0, "mpf_ILLmps_int_sos_mode");
00354 }
00355 }
00356 if (!strcmp (state->field, "'INTEND'"))
00357 {
00358 if (state->intvar)
00359 {
00360 state->intvar = 0;
00361 ILL_RESULT (0, "mpf_ILLmps_int_sos_mode");
00362 }
00363 else
00364 {
00365 return !mpf_ILLmps_error (state, "'INTORG' expected.\n");
00366 }
00367 }
00368 if (!strcmp (state->field, "'SOSORG'"))
00369 {
00370 if (state->sosvar)
00371 {
00372 return !mpf_ILLmps_error (state, "'SOSEND' expected.\n");
00373 }
00374 else
00375 {
00376 state->sosvar = 1;
00377 ILL_RESULT (0, "mpf_ILLmps_int_sos_mode");
00378 }
00379 }
00380 if (!strcmp (state->field, "'SOSEND'"))
00381 {
00382 if (state->sosvar)
00383 {
00384 state->sosvar = 0;
00385 ILL_RESULT (0, "mpf_ILLmps_int_sos_mode");
00386 }
00387 else
00388 {
00389 return !mpf_ILLmps_error (state, "'SOSORG' expected.\n");
00390 }
00391 }
00392 return mpf_ILLmps_error (state, "%s is not a MARKER field.\n", state->field);
00393 }
00394
00395 const char *mpf_ILLmps_possibly_blank_name (
00396 const char *field,
00397 mpf_ILLread_mps_state * state,
00398 ILLsymboltab * tab)
00399 {
00400 int ind;
00401
00402 if (ILLsymboltab_lookup (tab, field, &ind) == 0)
00403 {
00404
00405 if (mpf_ILLmps_next_field_is_number (state))
00406 {
00407
00408 return " ";
00409 }
00410 else
00411 {
00412 return field;
00413 }
00414 }
00415 else
00416 {
00417 return field;
00418 }
00419 }
00420
00421 int mpf_ILLmps_empty_key (
00422 mpf_ILLread_mps_state * state)
00423 {
00424 return state->key[0] == '\0';
00425 }
00426
00427 int mpf_ILLmps_empty_field (
00428 mpf_ILLread_mps_state * state)
00429 {
00430 return state->field[0] == '\0';
00431 }
00432
00433 static void mpf_mps_err (
00434 mpf_ILLread_mps_state * state,
00435 int isError,
00436 const char *format,
00437 va_list args)
00438 {
00439 int rval = 0;
00440 const char *type = (isError) ? "MPS Error" : "MPS Warning";
00441 int errtype, slen, at;
00442 mpf_qsformat_error error;
00443 char error_desc[256];
00444
00445 ILL_FAILfalse_no_rval (format != 0, "format != 0");
00446 ILL_FAILfalse_no_rval (format[0] != '\0', "format[0] != '0'");
00447 ILL_FAILfalse_no_rval (state != 0, "state != 0");
00448 ILL_FAILfalse_no_rval (state->file != 0, "state->file != 0");
00449
00450 if (state->p == 0)
00451 {
00452 at = -1;
00453 }
00454 else
00455 {
00456 ILL_FAILfalse (state->p >= state->line, "state->p >= state->line");
00457 at = state->p - state->line;
00458 }
00459 vsprintf (error_desc, format, args);
00460 slen = strlen (error_desc);
00461 if ((slen > 0) && error_desc[slen - 1] != '\n')
00462 {
00463 error_desc[slen] = '\n';
00464 error_desc[slen + 1] = '\0';
00465 }
00466
00467 if (state->file->error_collector != 0)
00468 {
00469 errtype = (isError) ? QS_MPS_FORMAT_ERROR : QS_MPS_FORMAT_WARN;
00470 mpf_ILLformat_error_create (&error, errtype, error_desc,
00471 (int) (state->line_num), state->line, at);
00472 mpf_ILLformat_error (state->file->error_collector, &error);
00473 mpf_ILLformat_error_delete (&error);
00474 }
00475 else
00476 {
00477 fprintf (stderr, "%s %d: %s\t", state->file_name, state->line_num,
00478 state->line);
00479 fprintf (stderr, "%s: ", type);
00480 vfprintf (stderr, format, args);
00481 if (format[strlen (format) - 1] != '\n')
00482 {
00483 fprintf (stderr, "\n");
00484 }
00485 fflush (stderr);
00486 }
00487 CLEANUP:
00488 ;
00489 }
00490
00491 int mpf_ILLmps_error (
00492 mpf_ILLread_mps_state * state,
00493 const char *format,
00494 ...)
00495 {
00496 va_list args;
00497
00498 va_start (args, format);
00499 mpf_mps_err (state, mpf_TRUE, format, args);
00500
00501 return 1;
00502 }
00503
00504 void mpf_ILLmps_warn (
00505 mpf_ILLread_mps_state * state,
00506 const char *format,
00507 ...)
00508 {
00509 va_list args;
00510
00511 va_start (args, format);
00512 if (format != 0)
00513 {
00514 mpf_mps_err (state, mpf_FALSE, format, args);
00515 }
00516 }