src/glpsdf.c
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

- Generated files and doc/notes are removed
alpar@1
     1
/* glpsdf.c (plain data file reading routines) */
alpar@1
     2
alpar@1
     3
/***********************************************************************
alpar@1
     4
*  This code is part of GLPK (GNU Linear Programming Kit).
alpar@1
     5
*
alpar@1
     6
*  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
alpar@1
     7
*  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
alpar@1
     8
*  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
alpar@1
     9
*  E-mail: <mao@gnu.org>.
alpar@1
    10
*
alpar@1
    11
*  GLPK is free software: you can redistribute it and/or modify it
alpar@1
    12
*  under the terms of the GNU General Public License as published by
alpar@1
    13
*  the Free Software Foundation, either version 3 of the License, or
alpar@1
    14
*  (at your option) any later version.
alpar@1
    15
*
alpar@1
    16
*  GLPK is distributed in the hope that it will be useful, but WITHOUT
alpar@1
    17
*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
alpar@1
    18
*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
alpar@1
    19
*  License for more details.
alpar@1
    20
*
alpar@1
    21
*  You should have received a copy of the GNU General Public License
alpar@1
    22
*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
alpar@1
    23
***********************************************************************/
alpar@1
    24
alpar@1
    25
#define GLPSDF_H
alpar@1
    26
alpar@1
    27
#define GLP_DATA_DEFINED
alpar@1
    28
typedef struct glp_data glp_data;
alpar@1
    29
alpar@1
    30
#include "glpapi.h"
alpar@1
    31
alpar@1
    32
struct glp_data
alpar@1
    33
{     /* plain data file */
alpar@1
    34
      char *fname;
alpar@1
    35
      /* name of data file */
alpar@1
    36
      XFILE *fp;
alpar@1
    37
      /* stream assigned to data file */
alpar@1
    38
      void *jump; /* jmp_buf jump; */
alpar@1
    39
      /* label for go to in case of error */
alpar@1
    40
      int count;
alpar@1
    41
      /* line count */
alpar@1
    42
      int c;
alpar@1
    43
      /* current character of XEOF */
alpar@1
    44
      char item[255+1];
alpar@1
    45
      /* current data item */
alpar@1
    46
};
alpar@1
    47
alpar@1
    48
static void next_char(glp_data *data);
alpar@1
    49
alpar@1
    50
glp_data *glp_sdf_open_file(const char *fname)
alpar@1
    51
{     /* open plain data file */
alpar@1
    52
      glp_data *data = NULL;
alpar@1
    53
      XFILE *fp;
alpar@1
    54
      jmp_buf jump;
alpar@1
    55
      fp = xfopen(fname, "r");
alpar@1
    56
      if (fp == NULL)
alpar@1
    57
      {  xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
alpar@1
    58
         goto done;
alpar@1
    59
      }
alpar@1
    60
      data = xmalloc(sizeof(glp_data));
alpar@1
    61
      data->fname = xmalloc(strlen(fname)+1);
alpar@1
    62
      strcpy(data->fname, fname);
alpar@1
    63
      data->fp = fp;
alpar@1
    64
      data->jump = NULL;
alpar@1
    65
      data->count = 0;
alpar@1
    66
      data->c = '\n';
alpar@1
    67
      data->item[0] = '\0';
alpar@1
    68
      /* read the very first character */
alpar@1
    69
      if (setjmp(jump))
alpar@1
    70
      {  glp_sdf_close_file(data);
alpar@1
    71
         data = NULL;
alpar@1
    72
         goto done;
alpar@1
    73
      }
alpar@1
    74
      data->jump = jump;
alpar@1
    75
      next_char(data);
alpar@1
    76
      data->jump = NULL;
alpar@1
    77
done: return data;
alpar@1
    78
}
alpar@1
    79
alpar@1
    80
void glp_sdf_set_jump(glp_data *data, void *jump)
alpar@1
    81
{     /* set up error handling */
alpar@1
    82
      data->jump = jump;
alpar@1
    83
      return;
alpar@1
    84
}
alpar@1
    85
alpar@1
    86
void glp_sdf_error(glp_data *data, const char *fmt, ...)
alpar@1
    87
{     /* print error message */
alpar@1
    88
      va_list arg;
alpar@1
    89
      xprintf("%s:%d: ", data->fname, data->count);
alpar@1
    90
      va_start(arg, fmt);
alpar@1
    91
      xvprintf(fmt, arg);
alpar@1
    92
      va_end(arg);
alpar@1
    93
      if (data->jump == NULL)
alpar@1
    94
         xerror("");
alpar@1
    95
      else
alpar@1
    96
         longjmp(data->jump, 1);
alpar@1
    97
      /* no return */
alpar@1
    98
}
alpar@1
    99
alpar@1
   100
void glp_sdf_warning(glp_data *data, const char *fmt, ...)
alpar@1
   101
{     /* print warning message */
alpar@1
   102
      va_list arg;
alpar@1
   103
      xprintf("%s:%d: warning: ", data->fname, data->count);
alpar@1
   104
      va_start(arg, fmt);
alpar@1
   105
      xvprintf(fmt, arg);
alpar@1
   106
      va_end(arg);
alpar@1
   107
      return;
alpar@1
   108
}
alpar@1
   109
alpar@1
   110
static void next_char(glp_data *data)
alpar@1
   111
{     /* read next character */
alpar@1
   112
      int c;
alpar@1
   113
      if (data->c == XEOF)
alpar@1
   114
         glp_sdf_error(data, "unexpected end of file\n");
alpar@1
   115
      else if (data->c == '\n')
alpar@1
   116
         data->count++;
alpar@1
   117
      c = xfgetc(data->fp);
alpar@1
   118
      if (c < 0)
alpar@1
   119
      {  if (xferror(data->fp))
alpar@1
   120
            glp_sdf_error(data, "read error - %s\n", xerrmsg());
alpar@1
   121
         else if (data->c == '\n')
alpar@1
   122
            c = XEOF;
alpar@1
   123
         else
alpar@1
   124
         {  glp_sdf_warning(data, "missing final end of line\n");
alpar@1
   125
            c = '\n';
alpar@1
   126
         }
alpar@1
   127
      }
alpar@1
   128
      else if (c == '\n')
alpar@1
   129
         ;
alpar@1
   130
      else if (isspace(c))
alpar@1
   131
         c = ' ';
alpar@1
   132
      else if (iscntrl(c))
alpar@1
   133
         glp_sdf_error(data, "invalid control character 0x%02X\n", c);
alpar@1
   134
      data->c = c;
alpar@1
   135
      return;
alpar@1
   136
}
alpar@1
   137
alpar@1
   138
static void skip_pad(glp_data *data)
alpar@1
   139
{     /* skip uninteresting characters and comments */
alpar@1
   140
loop: while (data->c == ' ' || data->c == '\n')
alpar@1
   141
         next_char(data);
alpar@1
   142
      if (data->c == '/')
alpar@1
   143
      {  next_char(data);
alpar@1
   144
         if (data->c != '*')
alpar@1
   145
            glp_sdf_error(data, "invalid use of slash\n");
alpar@1
   146
         next_char(data);
alpar@1
   147
         for (;;)
alpar@1
   148
         {  if (data->c == '*')
alpar@1
   149
            {  next_char(data);
alpar@1
   150
               if (data->c == '/')
alpar@1
   151
               {  next_char(data);
alpar@1
   152
                  break;
alpar@1
   153
               }
alpar@1
   154
            }
alpar@1
   155
            next_char(data);
alpar@1
   156
         }
alpar@1
   157
         goto loop;
alpar@1
   158
      }
alpar@1
   159
      return;
alpar@1
   160
}
alpar@1
   161
alpar@1
   162
static void next_item(glp_data *data)
alpar@1
   163
{     /* read next item */
alpar@1
   164
      int len;
alpar@1
   165
      skip_pad(data);
alpar@1
   166
      len = 0;
alpar@1
   167
      while (!(data->c == ' ' || data->c == '\n'))
alpar@1
   168
      {  data->item[len++] = (char)data->c;
alpar@1
   169
         if (len == sizeof(data->item))
alpar@1
   170
            glp_sdf_error(data, "data item `%.31s...' too long\n",
alpar@1
   171
               data->item);
alpar@1
   172
         next_char(data);
alpar@1
   173
      }
alpar@1
   174
      data->item[len] = '\0';
alpar@1
   175
      return;
alpar@1
   176
}
alpar@1
   177
alpar@1
   178
int glp_sdf_read_int(glp_data *data)
alpar@1
   179
{     /* read integer number */
alpar@1
   180
      int x;
alpar@1
   181
      next_item(data);
alpar@1
   182
      switch (str2int(data->item, &x))
alpar@1
   183
      {  case 0:
alpar@1
   184
            break;
alpar@1
   185
         case 1:
alpar@1
   186
            glp_sdf_error(data, "integer `%s' out of range\n",
alpar@1
   187
               data->item);
alpar@1
   188
         case 2:
alpar@1
   189
            glp_sdf_error(data, "cannot convert `%s' to integer\n",
alpar@1
   190
               data->item);
alpar@1
   191
         default:
alpar@1
   192
            xassert(data != data);
alpar@1
   193
      }
alpar@1
   194
      return x;
alpar@1
   195
}
alpar@1
   196
alpar@1
   197
double glp_sdf_read_num(glp_data *data)
alpar@1
   198
{     /* read floating-point number */
alpar@1
   199
      double x;
alpar@1
   200
      next_item(data);
alpar@1
   201
      switch (str2num(data->item, &x))
alpar@1
   202
      {  case 0:
alpar@1
   203
            break;
alpar@1
   204
         case 1:
alpar@1
   205
            glp_sdf_error(data, "number `%s' out of range\n",
alpar@1
   206
               data->item);
alpar@1
   207
         case 2:
alpar@1
   208
            glp_sdf_error(data, "cannot convert `%s' to number\n",
alpar@1
   209
               data->item);
alpar@1
   210
         default:
alpar@1
   211
            xassert(data != data);
alpar@1
   212
      }
alpar@1
   213
      return x;
alpar@1
   214
}
alpar@1
   215
alpar@1
   216
const char *glp_sdf_read_item(glp_data *data)
alpar@1
   217
{     /* read data item */
alpar@1
   218
      next_item(data);
alpar@1
   219
      return data->item;
alpar@1
   220
}
alpar@1
   221
alpar@1
   222
const char *glp_sdf_read_text(glp_data *data)
alpar@1
   223
{     /* read text until end of line */
alpar@1
   224
      int c, len = 0;
alpar@1
   225
      for (;;)
alpar@1
   226
      {  c = data->c;
alpar@1
   227
         next_char(data);
alpar@1
   228
         if (c == ' ')
alpar@1
   229
         {  /* ignore initial spaces */
alpar@1
   230
            if (len == 0) continue;
alpar@1
   231
            /* and multiple ones */
alpar@1
   232
            if (data->item[len-1] == ' ') continue;
alpar@1
   233
         }
alpar@1
   234
         else if (c == '\n')
alpar@1
   235
         {  /* remove trailing space */
alpar@1
   236
            if (len > 0 && data->item[len-1] == ' ') len--;
alpar@1
   237
            /* and stop reading */
alpar@1
   238
            break;
alpar@1
   239
         }
alpar@1
   240
         /* add current character to the buffer */
alpar@1
   241
         data->item[len++] = (char)c;
alpar@1
   242
         if (len == sizeof(data->item))
alpar@1
   243
            glp_sdf_error(data, "line too long\n", data->item);
alpar@1
   244
      }
alpar@1
   245
      data->item[len] = '\0';
alpar@1
   246
      return data->item;
alpar@1
   247
}
alpar@1
   248
alpar@1
   249
int glp_sdf_line(glp_data *data)
alpar@1
   250
{     /* determine current line number */
alpar@1
   251
      return data->count;
alpar@1
   252
}
alpar@1
   253
alpar@1
   254
void glp_sdf_close_file(glp_data *data)
alpar@1
   255
{     /* close plain data file */
alpar@1
   256
      xfclose(data->fp);
alpar@1
   257
      xfree(data->fname);
alpar@1
   258
      xfree(data);
alpar@1
   259
      return;
alpar@1
   260
}
alpar@1
   261
alpar@1
   262
/* eof */