Fix memory error in asc format IO
[alexxy/gromacs.git] / src / gmxlib / gmxfio_asc.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team,
6  * check out http://www.gromacs.org for more information.
7  * Copyright (c) 2012,2013, by the GROMACS development team, led by
8  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9  * others, as listed in the AUTHORS file in the top-level source
10  * directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43
44 #include <ctype.h>
45 #include <stdio.h>
46 #include <errno.h>
47 #ifdef HAVE_IO_H
48 #include <io.h>
49 #endif
50
51 #include "gmx_fatal.h"
52 #include "macros.h"
53 #include "smalloc.h"
54 #include "futil.h"
55 #include "filenm.h"
56 #include "string2.h"
57 #include "gmxfio.h"
58 #include "md5.h"
59
60 #ifdef GMX_THREAD_MPI
61 #include "thread_mpi.h"
62 #endif
63
64 #include "gmxfio_int.h"
65
66
67 /* This is the part that reads dummy and ascii files.  */
68
69
70
71
72 /* file type functions */
73 static gmx_bool do_ascread(t_fileio *fio, void *item, int nitem, int eio,
74                            const char *desc, const char *srcfile, int line);
75 static gmx_bool do_ascwrite(t_fileio *fio, const void *item, int nitem, int eio,
76                             const char *desc, const char *srcfile, int line);
77 static gmx_bool do_dummyread(t_fileio *fio, void *item, int nitem, int eio,
78                              const char *desc, const char *srcfile, int line);
79 static gmx_bool do_dummywrite(t_fileio *fio, const void *item, int nitem, int eio,
80                               const char *desc, const char *srcfile, int line);
81
82
83 const t_iotype asc_iotype = {do_ascread, do_ascwrite};
84 const t_iotype dummy_iotype = {do_dummyread, do_dummywrite};
85
86
87
88
89
90
91 static gmx_bool do_dummyread(t_fileio *fio, void *item, int nitem, int eio,
92                              const char *desc, const char *srcfile, int line)
93 {
94     gmx_fatal(FARGS, "File type not set!");
95     return FALSE;
96 }
97
98 static gmx_bool do_dummywrite(t_fileio *fio, const void *item, int nitem, int eio,
99                               const char *desc, const char *srcfile, int line)
100 {
101     gmx_fatal(FARGS, "File type not set!");
102     return FALSE;
103 }
104
105
106
107 static void encode_string(int maxlen, char dst[], const char src[])
108 {
109     int i;
110
111     for (i = 0; (i < maxlen - 1) && (src[i] != '\0'); i++)
112     {
113         if ((src[i] == ' ') || (src[i] == '\t'))
114         {
115             dst[i] = '_';
116         }
117         else
118         {
119             dst[i] = src[i];
120         }
121     }
122     dst[i] = '\0';
123
124     if (i == maxlen)
125     {
126         fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
127     }
128 }
129
130 static void decode_string(int maxlen, char dst[], const char src[])
131 {
132     int i;
133
134     for (i = 0; (i < maxlen - 1) && (src[i] != '\0'); i++)
135     {
136         if (src[i] == '_')
137         {
138             dst[i] = ' ';
139         }
140         else
141         {
142             dst[i] = src[i];
143         }
144     }
145     dst[i] = '\0';
146
147     if (i == maxlen)
148     {
149         fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
150     }
151 }
152
153 static gmx_bool do_ascwrite(t_fileio *fio, const void *item, int nitem, int eio,
154                             const char *desc, const char *srcfile, int line)
155 {
156     int            i;
157     int            res = 0, *iptr;
158     real          *ptr;
159     char           strbuf[256];
160     char           buf[GMX_FIO_BUFLEN];
161     unsigned char *ucptr;
162     FILE          *fp = fio->fp;
163
164     gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
165     switch (eio)
166     {
167         case eioREAL:
168         case eioFLOAT:
169         case eioDOUBLE:
170             res = fprintf(fp, "%18.10e%s\n", *((real *) item),
171                           gmx_fio_dbgstr(fio, desc, buf));
172             break;
173         case eioINT:
174             res = fprintf(fp, "%18d%s\n", *((int *) item), gmx_fio_dbgstr(fio,
175                                                                           desc,
176                                                                           buf));
177             break;
178         case eioGMX_LARGE_INT:
179             sprintf(strbuf, "%s%s%s", "%", gmx_large_int_fmt, "\n");
180             res = fprintf(fp, strbuf, *((gmx_large_int_t *) item),
181                           gmx_fio_dbgstr(fio, desc, buf));
182             break;
183         case eioUCHAR:
184             res = fprintf(fp, "%4d%s\n", *((unsigned char *) item),
185                           gmx_fio_dbgstr(fio, desc, buf));
186             break;
187         case eioNUCHAR:
188             ucptr = (unsigned char *) item;
189             for (i = 0; (i < nitem); i++)
190             {
191                 res = fprintf(fp, "%4d", (int) ucptr[i]);
192             }
193             fprintf(fio->fp, "%s\n", gmx_fio_dbgstr(fio, desc, buf));
194             break;
195         case eioUSHORT:
196             res = fprintf(fp, "%18d%s\n", *((unsigned short *) item),
197                           gmx_fio_dbgstr(fio, desc, buf));
198             break;
199         case eioRVEC:
200             ptr = (real *) item;
201             res = fprintf(fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
202                           ptr[YY], ptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
203             break;
204         case eioNRVEC:
205             for (i = 0; (i < nitem); i++)
206             {
207                 ptr = ((rvec *) item)[i];
208                 res = fprintf(fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
209                               ptr[YY], ptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
210             }
211             break;
212         case eioIVEC:
213             iptr = (int *) item;
214             res  = fprintf(fp, "%18d%18d%18d%s\n", iptr[XX], iptr[YY],
215                            iptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
216             break;
217         case eioSTRING:
218             encode_string(256, strbuf, (char *) item);
219             res = fprintf(fp, "%-18s%s\n", strbuf, gmx_fio_dbgstr(fio, desc, buf));
220             break;
221         default:
222             gmx_fio_fe(fio, eio, desc, srcfile, line);
223     }
224     if ((res <= 0) && fio->bDebug)
225     {
226         fprintf(stderr,
227                 "Error writing %s %s to file %s (source %s, line %d)\n",
228                 eioNames[eio], desc, fio->fn, srcfile, line);
229     }
230
231     return (res > 0);
232 }
233
234
235 static char *next_item(FILE *fp, char *buf, int buflen)
236 {
237     int      rd;
238     gmx_bool in_comment = FALSE;
239     gmx_bool in_token   = FALSE;
240     int      i          = 0;
241     /* This routine reads strings from the file fp, strips comment
242      * and buffers. For thread-safety reasons, It reads through getc()  */
243
244     rd = getc(fp);
245     if (rd == EOF)
246     {
247         gmx_file("End of file");
248     }
249     do
250     {
251         if (in_comment)
252         {
253             if (rd == '\n')
254             {
255                 in_comment = FALSE;
256             }
257         }
258         else if (in_token)
259         {
260             if (isspace(rd) || rd == ';')
261             {
262                 break;
263             }
264             buf[i++] = (char) rd;
265         }
266         else
267         {
268             if (!isspace(rd))
269             {
270                 if (rd == ';')
271                 {
272                     in_comment = TRUE;
273                 }
274                 else
275                 {
276                     in_token = TRUE;
277                     buf[i++] = (char) (rd);
278                 }
279             }
280         }
281         if (i >= buflen - 2)
282         {
283             break;
284         }
285     }
286     while ((rd = getc(fp)) != EOF);
287
288     fprintf(stderr, "WARNING, ftpASC file type not tested!\n");
289
290     buf[i] = 0;
291
292     return buf;
293 }
294
295 static gmx_bool do_ascread(t_fileio *fio, void *item, int nitem, int eio,
296                            const char *desc, const char *srcfile, int line)
297 {
298     FILE           *fp = fio->fp;
299     int             i, m, res = 0, *iptr, ix;
300     gmx_large_int_t s;
301     double          d, x;
302     real           *ptr;
303     unsigned char   uc, *ucptr;
304     char           *cptr;
305 #define NEXT_ITEM_BUF_LEN 128
306     char            ni_buf[NEXT_ITEM_BUF_LEN];
307
308     gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
309     switch (eio)
310     {
311         case eioREAL:
312         case eioFLOAT:
313         case eioDOUBLE:
314             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf", &d);
315             if (item)
316             {
317                 *((real *) item) = d;
318             }
319             break;
320         case eioINT:
321             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
322             if (item)
323             {
324                 *((int *) item) = i;
325             }
326             break;
327         case eioGMX_LARGE_INT:
328             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN),
329                          gmx_large_int_pfmt, &s);
330             if (item)
331             {
332                 *((gmx_large_int_t *) item) = s;
333             }
334             break;
335         case eioUCHAR:
336             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%c", &uc);
337             if (item)
338             {
339                 *((unsigned char *) item) = uc;
340             }
341             break;
342         case eioNUCHAR:
343             ucptr = (unsigned char *) item;
344             for (i = 0; (i < nitem); i++)
345             {
346                 res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &ix);
347                 if (item)
348                 {
349                     ucptr[i] = ix;
350                 }
351             }
352             break;
353         case eioUSHORT:
354             res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
355             if (item)
356             {
357                 *((unsigned short *) item) = i;
358             }
359             break;
360         case eioRVEC:
361             ptr = (real *) item;
362             for (m = 0; (m < DIM); m++)
363             {
364                 res    = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n", &x);
365                 ptr[m] = x;
366             }
367             break;
368         case eioNRVEC:
369             for (i = 0; (i < nitem); i++)
370             {
371                 ptr = ((rvec *) item)[i];
372                 for (m = 0; (m < DIM); m++)
373                 {
374                     res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n",
375                                  &x);
376                     if (item)
377                     {
378                         ptr[m] = x;
379                     }
380                 }
381             }
382             break;
383         case eioIVEC:
384             iptr = (int *) item;
385             for (m = 0; (m < DIM); m++)
386             {
387                 res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d\n", &ix);
388                 if (item)
389                 {
390                     iptr[m] = ix;
391                 }
392             }
393             break;
394         case eioSTRING:
395             cptr = next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN);
396             if (item)
397             {
398                 decode_string(strlen(cptr) + 1, (char *) item, cptr);
399                 /* res = sscanf(cptr,"%s",(char *)item);*/
400                 res = 1;
401             }
402             break;
403         default:
404             gmx_fio_fe(fio, eio, desc, srcfile, line);
405     }
406
407     if ((res <= 0) && fio->bDebug)
408     {
409         fprintf(stderr,
410                 "Error reading %s %s from file %s (source %s, line %d)\n",
411                 eioNames[eio], desc, fio->fn, srcfile, line);
412     }
413     return (res > 0);
414 }