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