mpq_read_lp.c

Go to the documentation of this file.
00001 /****************************************************************************/
00002 /*                                                                          */
00003 /*  This file is part of QSopt_ex.                                          */
00004 /*                                                                          */
00005 /*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
00006 /*  and Daniel Espinoza                                                     */
00007 /*                                                                          */
00008 /*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
00009 /*  copyright in QSopt.                                                     */
00010 /*                                                                          */
00011 /*  This code may be used under the terms of the GNU General Public License */
00012 /*  (Version 2.1 or later) as published by the Free Software Foundation.    */
00013 /*                                                                          */
00014 /*  Alternatively, use is granted for research purposes only.               */
00015 /*                                                                          */
00016 /*  It is your choice of which of these two licenses you are operating      */
00017 /*  under.                                                                  */
00018 /*                                                                          */
00019 /*  We make no guarantees about the correctness or usefulness of this code. */
00020 /*                                                                          */
00021 /****************************************************************************/
00022 
00023 /* RCS_INFO = "$RCSfile: read_lp_state.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
00024 
00025 /****************************************************************************/
00026 /*                                                                          */
00027 /*               Routines to support Reading LP Files                       */
00028 /*                                                                          */
00029 /****************************************************************************/
00030 
00031 /* 
00032  * -) anything after '\' is comment 
00033  * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~ 
00034  *    don't start with a digit or '.'
00035  */
00036 
00037 #include "qs_config.h"
00038 #include "mpq_iqsutil.h"
00039 #include "mpq_read_lp.h"
00040 #include "mpq_lp.h"
00041 #include "mpq_rawlp.h"
00042 #include "mpq_lpdefs.h"
00043 #include "mpq_format.h"
00044 #ifdef USEDMALLOC
00045 #include "dmalloc.h"
00046 #endif
00047 static int TRACE = 0;
00048 
00049 #define mpq_END_LINE(p)  (((*p) == '\\' || (*p) == '\n' || (*p) == '\0') ? 1 : 0)
00050 
00051 static const char *mpq_all_keyword[] = {
00052   "MIN", "MINIMUM", "MINIMIZE",
00053   "MAX", "MAXIMUM", "MAXIMIZE",
00054   "SUBJECT", "ST", "PROBLEM", "PROB",
00055   "BOUNDS", "BOUND", "INTEGER", "END", NULL
00056 };
00057 static int mpq_all_keyword_len[] = {
00058   3, 7, 8,
00059   3, 7, 8,
00060   7, 2, 7, 4,
00061   6, 5, 7, 3, -1
00062 };
00063 
00064 int mpq_ILLread_lp_state_init (
00065   mpq_ILLread_lp_state * state,
00066   mpq_qsline_reader * file,
00067   const char *mpq_fname,
00068   int inter)
00069 {
00070   int rval = 0;
00071 
00072   ILL_FAILtrue (file == NULL, "need a file");
00073   state->eof = 0;
00074   state->file_name = mpq_fname;
00075   state->mpq_interactive = inter;
00076   state->file = file;
00077   state->line_num = 0;
00078   state->p = state->line;
00079   state->line[0] = '\0';
00080   state->realline[0] = '\0';
00081   state->field[0] = '\0';
00082   state->fieldOnFirstCol = 0;
00083   mpq_EGlpNumInitVar (state->bound_val);
00084   mpq_ILLread_lp_state_skip_blanks (state, 1);
00085 CLEANUP:
00086   ILL_RETURN (rval, "mpq_ILLread_lp_state_init");
00087 }
00088 
00089 int mpq_ILLread_lp_state_next_line (
00090   mpq_ILLread_lp_state * state)
00091 {
00092   char *slash;
00093 
00094   if (state->eof)
00095   {
00096     return 1;
00097   }
00098   state->line[0] = '\0';
00099   if (state->mpq_interactive)
00100   {
00101     fprintf (stdout, "> ");
00102     fflush (stdout);
00103   }
00104   while (mpq_ILLline_reader_get (state->realline, ILL_namebufsize - 2, state->file)
00105          != (char *) NULL)
00106   {
00107     state->p = state->line;
00108     state->line_num++;
00109     strcpy (state->line, state->realline);
00110     slash = strchr (state->line, '\\');
00111     if (slash != NULL)
00112     {
00113       *slash = '\0';
00114     }
00115     while (mpq_ILL_ISBLANK (state->p))
00116     {
00117       state->p++;
00118     }
00119     if (!mpq_END_LINE (state->p))
00120     {
00121       ILL_IFTRACE ("NEWLINE %s %d: %s",
00122                    state->file_name, state->line_num, state->line);
00123       return 0;
00124     }
00125     if (state->mpq_interactive)
00126     {
00127       fprintf (stdout, "> ");
00128       fflush (stdout);
00129     }
00130   }
00131   state->eof = 1;
00132   state->line_num++;
00133   state->field[0] = '\0';
00134   state->line[0] = '\0';
00135   strcpy (state->realline, "\n");
00136   state->p = state->line;
00137   state->fieldOnFirstCol = 0;
00138   return 1;
00139 }
00140 
00141 int mpq_ILLread_lp_state_skip_blanks (
00142   mpq_ILLread_lp_state * state,
00143   int wrapLines)
00144 {
00145   while (1)
00146   {
00147     while (mpq_ILL_ISBLANK (state->p))
00148     {
00149       state->p++;
00150     }
00151     if (mpq_END_LINE (state->p))
00152     {
00153       if (wrapLines)
00154       {
00155         if (mpq_ILLread_lp_state_next_line (state) != 0)
00156         {
00157           return 1;
00158         }
00159       }
00160       else
00161       {
00162         return 0;               /* done */
00163       }
00164     }
00165     else
00166     {
00167       return 0;                 /* foud non blank */
00168     }
00169   }
00170 }
00171 
00172 static int mpq_next_field (
00173   mpq_ILLread_lp_state * state,
00174   int acrossLines)
00175 {
00176   (void) mpq_ILLread_lp_state_skip_blanks (state, (char) acrossLines);
00177   if (state->eof)
00178   {
00179     return 1;
00180   }
00181   state->fieldOnFirstCol = (state->line == state->p);
00182   if (sscanf (state->p, "%s", state->field) != EOF)
00183   {
00184     state->p += strlen (state->field);
00185     return 0;
00186   }
00187   return 1;
00188 }
00189 
00190 int mpq_ILLread_lp_state_next_field_on_line (
00191   mpq_ILLread_lp_state * state)
00192 {
00193   return mpq_next_field (state, 0);
00194 }
00195 
00196 int mpq_ILLread_lp_state_next_field (
00197   mpq_ILLread_lp_state * state)
00198 {
00199   return mpq_next_field (state, 1);
00200 }
00201 
00202 void mpq_ILLread_lp_state_prev_field (
00203   mpq_ILLread_lp_state * state)
00204 {
00205   if (state->p > state->line)
00206   {
00207     state->p--;
00208   }
00209   while (mpq_ILL_ISBLANK (state->p) && (state->p > state->line))
00210   {
00211     state->p--;
00212   }
00213   while (!mpq_ILL_ISBLANK (state->p) && (state->p > state->line))
00214   {
00215     state->p--;
00216   }
00217   state->fieldOnFirstCol = (state->line == state->p);
00218 }
00219 
00220 int mpq_ILLread_lp_state_next_var (
00221   mpq_ILLread_lp_state * state)
00222 {
00223   char *p;
00224   int var_len, i;
00225 
00226   if (mpq_ILLread_lp_state_skip_blanks (state, 1))
00227   {
00228     return 1;
00229   }
00230   state->fieldOnFirstCol = (state->line == state->p);
00231   var_len = 0;
00232   p = state->p;
00233   while (1)
00234   {
00235     if (mpq_ILLis_lp_name_char (*p, var_len))
00236     {
00237       p++;
00238       var_len++;
00239     }
00240     else
00241     {
00242       break;
00243     }
00244   }
00245   if (var_len == 0)
00246   {
00247     return 1;
00248   }
00249   if (state->fieldOnFirstCol)
00250   {
00251     /* see whether we founbd a reserved keyword */
00252     for (i = 0; mpq_all_keyword[i] != NULL; i++)
00253     {
00254       if ((var_len == mpq_all_keyword_len[i]) &&
00255           (strncasecmp (mpq_all_keyword[i], state->p, (size_t) (mpq_all_keyword_len[i]))
00256            == 0))
00257       {
00258         return -1;              /* yes we did */
00259       }
00260     }
00261   }
00262   strncpy (state->field, state->p, (size_t) var_len);
00263   state->field[var_len] = '\0';
00264   state->p = p;
00265   return 0;
00266 }
00267 
00268 int mpq_ILLread_lp_state_bad_keyword (
00269   mpq_ILLread_lp_state * state)
00270 {
00271   if (!state->fieldOnFirstCol)
00272   {
00273     return mpq_ILLlp_error (state,
00274                         "Keyword \"%s\" not at beginning of line.\n",
00275                         state->field);
00276   }
00277   return 0;
00278 }
00279 
00280 int mpq_ILLtest_lp_state_keyword (
00281   mpq_ILLread_lp_state * state,
00282   const char *kwd[])
00283 {
00284   int i = 0;
00285 
00286   if (!state->eof && state->fieldOnFirstCol)
00287   {
00288     for (i = 0; kwd[i] != NULL; i++)
00289     {
00290       if (strcasecmp (state->field, kwd[i]) == 0)
00291       {
00292         return 0;
00293       }
00294     }
00295   }
00296   return 1;
00297 }
00298 
00299 int mpq_ILLread_lp_state_keyword (
00300   mpq_ILLread_lp_state * state,
00301   const char *kwd[])
00302 {
00303   if (state->eof || mpq_ILLread_lp_state_bad_keyword (state))
00304   {
00305     return 1;
00306   }
00307   return mpq_ILLtest_lp_state_keyword (state, kwd);
00308 }
00309 
00310 
00311 int mpq_ILLread_lp_state_colon (
00312   mpq_ILLread_lp_state * state)
00313 {
00314   if ((mpq_ILLread_lp_state_skip_blanks (state, 1) == 0) && (*state->p == ':'))
00315   {
00316     state->p++;
00317     return 0;
00318   }
00319   return 1;
00320 }
00321 
00322 int mpq_ILLread_lp_state_has_colon (
00323   mpq_ILLread_lp_state * state)
00324 {
00325   char *pp;
00326 
00327   mpq_ILLread_lp_state_skip_blanks (state, 0);
00328   for (pp = state->p; *pp != '\n'; pp++)
00329   {
00330     if (*pp == ':')
00331     {
00332       return 1;
00333     }
00334   }
00335   return 0;
00336 }
00337 
00338 int mpq_ILLread_lp_state_next_constraint (
00339   mpq_ILLread_lp_state * state)
00340 {
00341   int rval;
00342   int ln = state->line_num;
00343 
00344   mpq_ILLread_lp_state_skip_blanks (state, 1);
00345   if (state->eof)
00346   {
00347     return 1;
00348   }
00349   if (ln == state->line_num)
00350   {
00351     return mpq_ILLlp_error (state, "Constraints must start on a new line.\n");
00352   }
00353   if (mpq_ILLread_lp_state_next_field (state) == 0)
00354   {
00355     rval = mpq_ILLtest_lp_state_keyword (state, mpq_all_keyword);
00356     mpq_ILLread_lp_state_prev_field (state);
00357     return !rval;
00358   }
00359   return 0;
00360 }
00361 
00362 /* return 0 if there is a sign */
00363 int mpq_ILLread_lp_state_sign (
00364   mpq_ILLread_lp_state * state,
00365   mpq_t * sign)
00366 {
00367   char found = 0;
00368 
00369   mpq_EGlpNumOne (*sign);
00370   if (mpq_ILLread_lp_state_skip_blanks (state, 1) == 0)
00371   {
00372     if ((*state->p == '+') || (*state->p == '-'))
00373     {
00374       if (*state->p != '+')
00375         mpq_EGlpNumSign (*sign);
00376       state->p++;
00377       found = 1;
00378     }
00379   }
00380   return 1 - found;
00381 }
00382 
00383 int mpq_ILLtest_lp_state_next_is (
00384   mpq_ILLread_lp_state * state,
00385   const char *str)
00386 {
00387   mpq_ILLread_lp_state_skip_blanks (state, 0);
00388   if (strncasecmp (state->p, str, strlen (str)) == 0)
00389   {
00390     state->p += strlen (str);
00391     return 1;
00392   }
00393   return 0;
00394 }
00395 
00396 int mpq_ILLread_lp_state_value (
00397   mpq_ILLread_lp_state * state,
00398   mpq_t * coef)
00399 {
00400   int len = 0;
00401 
00402   if (mpq_ILLread_lp_state_skip_blanks (state, 1) != 0)
00403   {
00404     ILL_RESULT (1, "mpq_ILLread_lp_state_value");
00405   }
00406   else
00407   {
00408     state->fieldOnFirstCol = (state->line == state->p);
00409     len = mpq_ILLget_value (state->p, coef);
00410     if (len > 0)
00411     {
00412       state->p += len;
00413       ILL_RESULT (0, "mpq_ILLread_lp_state_value");
00414     }
00415     ILL_RESULT (1, "mpq_ILLread_lp_state_value");
00416   }
00417 }
00418 
00419 int mpq_ILLread_lp_state_possible_coef (
00420   mpq_ILLread_lp_state * state,
00421   mpq_t * coef,
00422   const mpq_t defValue)
00423 {
00424   mpq_EGlpNumCopy (*coef, defValue);
00425   return mpq_ILLread_lp_state_value (state, coef);
00426 }
00427 
00428 
00429 int mpq_ILLread_lp_state_possible_bound_value (
00430   mpq_ILLread_lp_state * state)
00431 {
00432   mpq_t sign;
00433   int len = 0;
00434   char *p = NULL;
00435   int rval = 0;
00436 
00437   mpq_EGlpNumInitVar (sign);
00438   (void) mpq_ILLread_lp_state_sign (state, &sign);
00439 
00440   if (!strncasecmp (state->p, "INFINITY", (size_t) 8))
00441   {
00442     len = 8;
00443   }
00444   else
00445   {
00446     if (!strncasecmp (state->p, "INF", (size_t) 3))
00447     {
00448       len = 3;
00449     }
00450   }
00451   if (len > 0)
00452   {
00453     state->p += len;
00454     p = state->p;
00455     mpq_ILLread_lp_state_skip_blanks (state, 0);
00456     if (!mpq_END_LINE (p) && p == state->p)
00457     {
00458       /* found no blanks so this INF/INFINITY is the prefix 
00459        * of something else */
00460       state->p -= len;
00461       goto CLEANUP;
00462       return 0;                 /* no coef found */
00463     }
00464     else
00465     {
00466       if (mpq_EGlpNumIsLessZero (sign))
00467         mpq_EGlpNumCopy (state->bound_val, mpq_ILL_MINDOUBLE);
00468       else if (mpq_EGlpNumIsGreatZero (sign))
00469         mpq_EGlpNumCopy (state->bound_val, mpq_ILL_MAXDOUBLE);
00470       else
00471         mpq_EGlpNumZero (state->bound_val);
00472       rval = 1;
00473       goto CLEANUP;
00474     }
00475   }
00476   if (mpq_ILLread_lp_state_value (state, &(state->bound_val)) == 0)
00477   {
00478     mpq_EGlpNumMultTo (state->bound_val, sign);
00479     rval = 1;
00480     goto CLEANUP;
00481   }
00482 CLEANUP:
00483   mpq_EGlpNumClearVar (sign);
00484   return rval;                  /* no coef found */
00485 }
00486 
00487 int mpq_ILLtest_lp_state_sense (
00488   mpq_ILLread_lp_state * state,
00489   int all)
00490 {
00491   char c;
00492 
00493   state->sense_val = ' ';
00494   if (mpq_ILLread_lp_state_skip_blanks (state, 1) == 0)
00495   {
00496     c = *state->p;
00497     if (!all)
00498     {                           /* look for '=' and '<=' */
00499       if (c == '=')
00500       {
00501         state->p++;
00502         state->sense_val = 'E';
00503       }
00504       else
00505       {
00506         if ((c == '<') && (*(state->p + 1) == '='))
00507         {
00508           state->p += 2;
00509           state->sense_val = 'L';
00510         }
00511       }
00512     }
00513     else
00514     {
00515       c = *state->p;
00516       if ((c == '<') || (c == '>'))
00517       {
00518         state->sense_val = (c == '<') ? 'L' : 'G';
00519         state->p++;
00520         c = *state->p;
00521         if (*state->p == '=')
00522         {
00523           state->p++;
00524         }
00525       }
00526       else
00527       {
00528         if (c == '=')
00529         {
00530           state->p++;
00531           c = *state->p;
00532           if ((c == '<') || (c == '>'))
00533           {
00534             state->sense_val = (c == '<') ? 'L' : 'G';
00535             state->p++;
00536           }
00537           else
00538           {
00539             state->sense_val = 'E';
00540           }
00541         }
00542       }
00543     }
00544   }
00545   return (state->sense_val != ' ');
00546 }
00547 
00548 void mpq_ILLtest_lp_state_bound_sense (
00549   mpq_ILLread_lp_state * state)
00550 {
00551   (void) mpq_ILLtest_lp_state_sense (state, 0);
00552 }
00553 
00554 int mpq_ILLread_lp_state_sense (
00555   mpq_ILLread_lp_state * state)
00556 {
00557   if (!mpq_ILLtest_lp_state_sense (state, 1))
00558   {
00559     if (mpq_END_LINE (state->p))
00560     {
00561       return mpq_ILLlp_error (state, "Missing row sense at end of line.\n");
00562     }
00563     else
00564     {
00565       if (*state->p != '\0')
00566       {
00567         return mpq_ILLlp_error (state, "\"%c\" is not a row sense.\n", *state->p);
00568       }
00569       else
00570       {
00571         return mpq_ILLlp_error (state, "Missing row sense at end of line.\n");
00572       }
00573     }
00574   }
00575   return 0;
00576 }
00577 
00578 /* ------------------------------------------------------------------------- */
00579 /*  error printing 
00580  */
00581 
00582 static void mpq_ILLread_lp_state_print_at (
00583   mpq_ILLread_lp_state * state)
00584 {
00585   char *p;
00586 
00587   if (state->eof)
00588   {
00589     fprintf (stderr, "end of file");
00590   }
00591   else
00592   {
00593     if (*state->p == '\n')
00594     {
00595       fprintf (stderr, "end of line");
00596     }
00597     else
00598     {
00599       p = state->p;
00600       while (mpq_ILL_ISBLANK (p))
00601       {
00602         p++;
00603       }
00604       fprintf (stderr, "%c", '"');
00605       for (; !mpq_ILL_ISBLANK (p) && !mpq_END_LINE (p); p++)
00606       {
00607         fprintf (stderr, "%c", *p);
00608       }
00609       fprintf (stderr, "\"");
00610     }
00611   }
00612 }
00613 
00614 static void mpq_lp_err (
00615   mpq_ILLread_lp_state * state,
00616   int isError,
00617   const char *format,
00618   va_list args)
00619 {
00620   int rval = 0;
00621   int errtype, slen, at;
00622   mpq_qsformat_error error;
00623   char error_desc[256];
00624 
00625   ILL_FAILfalse (state != NULL, "state != NULL");
00626   ILL_FAILfalse (state->file != NULL, "state->file != NULL");
00627   ILL_FAILfalse (format != NULL, "format != NULL");
00628   ILL_FAILfalse (format[0] != '\0', "format[0] != '0'");
00629 
00630   mpq_ILLread_lp_state_skip_blanks (state, 0);
00631   at = state->p - state->line;
00632   vsprintf (error_desc, format, args);
00633   slen = strlen (error_desc);
00634   if ((slen > 0) && error_desc[slen - 1] != '\n')
00635   {
00636     error_desc[slen] = '\n';
00637     error_desc[slen + 1] = '\0';
00638   }
00639 
00640   if (state->file->error_collector != NULL)
00641   {
00642     errtype = (isError) ? QS_LP_FORMAT_ERROR : QS_LP_FORMAT_WARN;
00643     mpq_ILLformat_error_create (&error, errtype, error_desc,
00644                             state->line_num, state->realline, at);
00645     mpq_ILLformat_error (state->file->error_collector, &error);
00646     mpq_ILLformat_error_delete (&error);
00647   }
00648   else
00649   {
00650     if (!state->mpq_interactive)
00651     {
00652       fprintf (stderr, "%s %d: %s\t", state->file_name, state->line_num,
00653                state->realline);
00654       fprintf (stderr, "%s at ", (isError) ? "LP Error" : "LP Warning");
00655       mpq_ILLread_lp_state_print_at (state);
00656       fprintf (stderr, ": ");
00657     }
00658     else
00659     {
00660       fprintf (stderr, "%s : ", (isError) ? "LP Error" : "LP Warning");
00661     }
00662     fprintf (stderr, error_desc);
00663     fflush (stderr);
00664   }
00665 CLEANUP:;
00666 }
00667 
00668 int mpq_ILLlp_error (
00669   mpq_ILLread_lp_state * state,
00670   const char *format,
00671   ...)
00672 {
00673   va_list args;
00674 
00675   va_start (args, format);
00676   mpq_lp_err (state, mpq_TRUE, format, args);
00677   return 1;
00678 }
00679 
00680 void mpq_ILLlp_warn (
00681   mpq_ILLread_lp_state * state,
00682   const char *format,
00683   ...)
00684 {
00685   va_list args;
00686 
00687   va_start (args, format);
00688   if (format != NULL)
00689   {
00690     mpq_lp_err (state, mpq_FALSE, format, args);
00691   }
00692 }
00693 
00694 /* shared with read_mps_state.c */
00695 int mpq_ILLget_value (
00696   char *line,
00697   mpq_t * coef)
00698 {
00699 #ifdef mpq_READ_LP_STATE_H
00700   mpq_t res;
00701   int rval = 0;
00702 
00703   mpq_init (res);
00704   rval = mpq_EGlpNumReadStrXc (res, line);
00705   if (rval == 0)
00706     mpq_set_ui (*coef, 1UL, 1UL);
00707   else
00708     mpq_set (*coef, res);
00709   mpq_clear (res);
00710   return rval;
00711   //return mpq_EGlpNumReadStrXc (*coef, line);
00712 #else
00713   char field[ILL_namebufsize];
00714   int rval = 0, i;
00715   char c, lastC, *p;
00716   int allowDot, allowExp, allowSign;
00717   double dtmp;
00718 
00719   p = line;
00720   c = *p;
00721   i = 0;
00722   lastC = ' ';
00723   allowSign = 1;
00724   allowExp = 0;
00725   allowDot = 1;
00726   while ((('0' <= c) && (c <= '9')) ||
00727          (allowDot && (c == '.')) ||
00728          ((allowExp == 1) && ((c == 'e') || (c == 'E'))) ||
00729          ((allowSign || lastC == 'e' || lastC == 'E') &&
00730           ((c == '+') || (c == '-'))))
00731   {
00732     if (c == '.')
00733       allowDot = 0;
00734     allowSign = 0;
00735 
00736     if ((allowExp == 0) && (c >= '0') && (c <= '9'))
00737     {
00738       allowExp = 1;
00739     }
00740     if ((c == 'e') || (c == 'E'))
00741     {
00742       allowExp++;
00743       allowDot = 0;
00744     }
00745     p++;
00746     lastC = c;
00747     c = *p;
00748     i++;
00749   }
00750   if ((lastC == '+') || (lastC == '-'))
00751   {
00752     p--;
00753     i--;
00754     if (p > line)
00755       lastC = *(p - 1);
00756     else
00757       lastC = ' ';
00758   }
00759   if ((lastC == 'e') || (lastC == 'E'))
00760   {
00761     p--;
00762     i--;
00763   }
00764   if (i > 0)
00765   {
00766     strncpy (field, line, (size_t) i);
00767     field[i] = '\0';
00768     rval = !sscanf (field, "%lf%n", &dtmp, &i);
00769     mpq_EGlpNumSet (*coef, dtmp);
00770     ILL_IFTRACE ("%la\n", mpq_EGlpNumToLf (*coef));
00771     if (rval != 0)
00772     {
00773       ILL_RESULT (0, "mpq_ILLget_value");
00774     }
00775   }
00776   //ILL_RESULT (i, "mpq_ILLget_value");
00777   return i;
00778 #endif
00779 }
00780 
00781 int mpq_ILLcheck_subject_to (
00782   mpq_ILLread_lp_state * state)
00783 {
00784   int rval;
00785   char *p;
00786 
00787   if ((rval = mpq_ILLread_lp_state_next_field (state)) == 0)
00788   {
00789     if (strcasecmp (state->field, "ST") == 0)
00790     {
00791       rval = mpq_ILLread_lp_state_bad_keyword (state);
00792     }
00793     else
00794     {
00795       if (strcasecmp (state->field, "SUBJECT") == 0)
00796       {
00797         p = state->p;
00798         while (mpq_ILL_ISBLANK (p))
00799         {
00800           p++;
00801         }
00802         if (!strncasecmp (p, "TO", (size_t) 2))
00803         {
00804           rval = mpq_ILLread_lp_state_bad_keyword (state);
00805           if (rval == 0)
00806           {
00807             state->p = p + 2;
00808           }
00809         }
00810       }
00811       else
00812       {
00813         rval = 1;
00814       }
00815     }
00816     if (rval != 0)
00817     {
00818       mpq_ILLread_lp_state_prev_field (state);
00819     }
00820     else
00821     {
00822       mpq_ILLread_lp_state_skip_blanks (state, 1);
00823     }
00824   }
00825   ILL_RESULT (rval, "check_subject_to");
00826 }

Generated on Thu Mar 29 09:32:32 2012 for QSopt_ex by  doxygen 1.4.7