1 /*****************************************************************************
2  *
3  *  Elmer, A Finite Element Software for Multiphysical Problems
4  *
5  *  Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library (in file ../LGPL-2.1); if not, write
19  * to the Free Software Foundation, Inc., 51 Franklin Street,
20  * Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  *****************************************************************************/
23 
24 /*******************************************************************************
25  *
26  *     IO handling for MATC.
27  *
28  *******************************************************************************
29  *
30  *                     Author:       Juha Ruokolainen
31  *
32  *                    Address: CSC - IT Center for Science Ltd.
33  *                                Keilaranta 14, P.O. BOX 405
34  *                                  02101 Espoo, Finland
35  *                                  Tel. +358 0 457 2723
36  *                                Telefax: +358 0 457 2302
37  *                              EMail: Juha.Ruokolainen@csc.fi
38  *
39  *                       Date: 30 May 1996
40  *
41  *                Modified by:
42  *
43  *       Date of modification:
44  *
45  ******************************************************************************/
46 
47 /*
48  * $Id: files.c,v 1.1.1.1 2005/04/14 13:29:14 vierinen Exp $
49  *
50  * $Log: files.c,v $
51  * Revision 1.1.1.1  2005/04/14 13:29:14  vierinen
52  * initial matc automake package
53  *
54  * Revision 1.2  1998/08/01 12:34:36  jpr
55  *
56  * Added Id, started Log.
57  *
58  *
59  */
60 
61 #include "elmer/matc.h"
62 #include "str.h"
63 
64 /***********************************************************************
65 |
66 |  FILES.C - Last Edited 10. 8. 1988
67 |
68 ***********************************************************************/
69 
70 /*======================================================================
71 |Syntax of the manual pages:
72 |
73 |FUNCTION NAME(...) params ...
74 |
75 $  usage of the function and type of the parameters
76 ?  explane the effects of the function
77 =  return value and the type of value if not of type int
78 @  globals effected directly by this routine
79 !  current known bugs or limitations
80 &  functions called by this function
81 ~  these functions may interest you as an alternative function or
82 |  because they control this function somehow
83 ^=====================================================================*/
84 
85 #define FILE_BINARY 0
86 #define FILE_ASCII 1
87 
88 #define MAXFILES 32
89 static FILE *fil_fps[MAXFILES];
90 static FILE *fil_fps_save[3];
91 #pragma omp threadprivate(fil_fps, fil_fps_save)
92 
fil_fread(var)93 VARIABLE *fil_fread(var) VARIABLE *var;
94 {
95   VARIABLE *res;
96   FILE *fp;
97 
98   int i, ind, len;
99   size_t iosize;
100 
101 
102   ind = *MATR(var);
103   if (ind < 0 || ind >= MAXFILES)
104   {
105     error("fread: Invalid file number.\n");
106   }
107   else if (fil_fps[ind] == NULL)
108   {
109     error("fread: File not open.\n");
110   }
111   fp = fil_fps[ind];
112 
113   if (feof(fp))
114   {
115     clearerr(fp);
116     error("fread: end of file detected.\n");
117   }
118 
119   len = *MATR(NEXT(var));
120   if (len <= 0)
121   {
122     error("fread: invalid length specified.\n");
123   }
124   res = var_temp_new(TYPE_DOUBLE, 1, (len+sizeof(double)-1)>>3);
125   iosize = fread(MATR(res), 1, len, fp);
126 
127   if (feof(fp))
128   {
129     clearerr(fp);
130     error("fread: end of file detected.\n");
131   }
132 
133   if (ferror(fp))
134   {
135     clearerr(fp);
136     error("fread: error reading file.\n");
137   }
138 
139   return res;
140 }
141 
fil_fwrite(var)142 VARIABLE *fil_fwrite(var) VARIABLE *var;
143 {
144   int i, ind, len;
145   FILE *fp;
146 
147   ind = *MATR(var);
148   if (ind < 0 || ind >= MAXFILES)
149   {
150     error("fwrite: Invalid file number.\n");
151   }
152   else if (fil_fps[ind] == NULL)
153   {
154     error("fwrite: File not open.\n");
155   }
156   fp = fil_fps[ind];
157 
158   if (NEXT(NEXT(var)) != NULL)
159   {
160     len = *MATR(NEXT(NEXT(var)));
161     if (len > MATSIZE(NEXT(var)))
162     {
163       error("fwrite: attempt to write more data than provided.\n");
164     }
165   }
166   else
167   {
168     len = MATSIZE(NEXT(var));
169   }
170   fwrite(MATR(NEXT(var)), 1, len, fp);
171 
172   if (ferror(fp))
173   {
174     clearerr(fp);
175     error("fwrite: error writing file.\n");
176   }
177 
178   return (VARIABLE *)NULL;
179 }
180 
fil_fscanf(var)181 VARIABLE *fil_fscanf(var) VARIABLE *var;
182 {
183   VARIABLE *res;
184   FILE *fp;
185 
186   char *fmt = var_to_string(NEXT(var));
187   int i, ind, got;
188 
189   ind = *MATR(var);
190   if (ind < 0 || ind >= MAXFILES)
191   {
192     error("fscanf: Invalid file number.\n");
193   }
194   else if (fil_fps[ind] == NULL)
195   {
196     error("fscanf: File not open.\n");
197   }
198   fp = fil_fps[ind];
199 
200   if (feof(fp))
201   {
202     clearerr(fp);
203     error("fscanf: end of file detected.\n");
204   }
205 
206   got = fscanf(fp, fmt,
207       &str_p[0],  &str_p[1],  &str_p[2],  &str_p[3],  &str_p[4],  &str_p[5],
208       &str_p[6],  &str_p[7],  &str_p[8],  &str_p[9],  &str_p[10], &str_p[11],
209       &str_p[12], &str_p[13], &str_p[14], &str_p[15], &str_p[16], &str_p[17],
210       &str_p[18], &str_p[19], &str_p[20], &str_p[21], &str_p[22], &str_p[23],
211       &str_p[24], &str_p[25], &str_p[26], &str_p[27], &str_p[28], &str_p[29]);
212 
213   res = NULL;
214   if (got > 0) {
215     res = var_temp_new(TYPE_DOUBLE,1,got);
216     for(i = 0; i < got; i++)
217     {
218       M(res,0,i) = str_p[i];
219     }
220   }
221   FREEMEM(fmt);
222 
223   if (feof(fp))
224   {
225     clearerr(fp);
226     error("fscanf: end of file detected.\n");
227   }
228 
229   if (ferror(fp))
230   {
231     clearerr(fp);
232     error("fscanf: error reading file.\n");
233   }
234 
235   return res;
236 }
237 
fil_fgets(var)238 VARIABLE *fil_fgets(var) VARIABLE *var;
239 {
240   VARIABLE *res;
241   FILE *fp;
242 
243   int i, ind;
244   char *ioptr;
245 
246   ind = *MATR(var);
247   if (ind < 0 || ind >= MAXFILES)
248   {
249     error("fgets: Invalid file number.\n");
250   }
251   else if (fil_fps[ind] == NULL)
252   {
253     error("fgets: File not open.\n");
254   }
255   fp = fil_fps[ind];
256 
257   if (feof(fp))
258   {
259     clearerr(fp);
260     error("fgets: end of file detected.\n");
261   }
262 
263   ioptr = fgets(str_pstr, STR_MAXLEN, fp);
264 
265   if (feof(fp))
266   {
267     clearerr(fp);
268     error("fgets: end of file detected.\n");
269   }
270 
271   if (ferror(fp))
272   {
273     clearerr(fp);
274     error("fgets: error reading file.\n");
275   }
276 
277   res = var_temp_new(TYPE_STRING, 1, strlen(str_pstr)-1);
278   for(i = 0; i < strlen(str_pstr)-1; i++)
279     M(res,0,i) = str_pstr[i];
280 
281   return res;
282 }
283 
fil_fprintf(var)284 VARIABLE *fil_fprintf(var) VARIABLE *var;
285 {
286   int i, ind;
287   char *str;
288   FILE *fp;
289 
290   ind = *MATR(var);
291   if (ind < 0 || ind >= MAXFILES)
292   {
293     error("fprintf: Invalid file number.\n");
294   }
295   else if (fil_fps[ind] == NULL)
296   {
297     error("fprintf: File not open.\n");
298   }
299   fp = fil_fps[ind];
300 
301   var = str_sprintf(NEXT(var));
302   str = var_to_string(var);
303   fprintf(fp, "%s",str);
304 
305   var_delete_temp(var);
306   FREEMEM(str);
307 
308   if (ferror(fp))
309   {
310     clearerr(fp);
311     error("fprintf: error writing file.\n");
312   }
313 
314   return (VARIABLE *)NULL;
315 }
316 
fil_fputs(var)317 VARIABLE *fil_fputs(var) VARIABLE *var;
318 {
319   char *str = var_to_string(NEXT(var));
320   int ind = *MATR(var);
321   FILE *fp;
322 
323   if (ind < 0 || ind >= MAXFILES)
324   {
325     error("fputs: Invalid file number.\n");
326   }
327   else if (fil_fps[ind] == NULL)
328   {
329     error("fputs: File not open.\n");
330   }
331   fp = fil_fps[ind];
332 
333   fprintf(fp, "%s", str);
334 
335   FREEMEM(str);
336 
337   if (ferror(fp))
338   {
339     clearerr(fp);
340     error("fprintf: error writing file.\n");
341   }
342 
343   return (VARIABLE *)NULL;
344 }
345 
fil_fopen(var)346 VARIABLE *fil_fopen(var) VARIABLE *var;
347 {
348   VARIABLE *res;
349 
350   char *name, *mode;
351   int file;
352 
353   mode = var_to_string(NEXT(var));
354   name = var_to_string(var);
355 
356   for(file = 0; file < MAXFILES; file++)
357   {
358     if (fil_fps[file] == NULL) break;
359   }
360 
361   if (file >= MAXFILES)
362   {
363     error("fopen: maximum number of files already open.\n");
364   }
365 
366   if ((fil_fps[file] = fopen(name, mode)) == (FILE *)NULL)
367   {
368     error("fopen: can't open file: %s.\n", name);
369   }
370 
371   switch(file)
372   {
373     case 0:
374       fil_fps_save[0] = math_in;
375       math_in = fil_fps[0];
376     break;
377 
378     case 1:
379       fil_fps_save[1] = math_out;
380       math_out = fil_fps[1];
381     break;
382 
383     case 2:
384       fil_fps_save[2] = math_err;
385       math_err = fil_fps[2];
386     break;
387   }
388 
389   res = var_temp_new(TYPE_DOUBLE, 1, 1);
390   M(res,0,0) = file;
391 
392   FREEMEM(name);
393   FREEMEM(mode);
394 
395   return res;
396 }
397 
fil_fclose(var)398 VARIABLE *fil_fclose(var) VARIABLE *var;
399 {
400   int file = *MATR(var);
401 
402   if (file < 0 || file >= MAXFILES)
403   {
404     error("fclose: Invalid file number.\n");
405   }
406 
407   switch(file)
408   {
409     case 0:
410       math_in = fil_fps_save[0];
411       if (
412            fil_fps[0] != math_out && fil_fps[0] != NULL
413          ) fclose(fil_fps[0]);
414       fil_fps[0] = math_in;
415     break;
416 
417     case 1:
418       math_out = fil_fps_save[1];
419       if (
420            fil_fps[1] != math_out && fil_fps[1] != NULL
421          ) fclose(fil_fps[1]);
422       fil_fps[1] = math_out;
423     break;
424 
425     case 2:
426       math_err = fil_fps_save[2];
427       if (
428            fil_fps[2] != math_err && fil_fps[2] != NULL
429          ) fclose(fil_fps[2]);
430       fil_fps[2] = math_err;
431     break;
432 
433     default:
434       if (fil_fps[file] != NULL)
435         fclose(fil_fps[file]);
436       fil_fps[file] = NULL;
437     break;
438   }
439 
440   return (VARIABLE *)NULL;
441 }
442 
fil_freopen(var)443 VARIABLE *fil_freopen(var) VARIABLE *var;
444 {
445   int file = *MATR(var);
446 
447   fil_fclose(var);
448   fil_fps[file] = NULL;
449   var = fil_fopen(NEXT(var));
450   var_delete_temp(var);
451 
452   return (VARIABLE *)NULL;
453 }
454 
fil_save(ptr)455 VARIABLE *fil_save(ptr) VARIABLE *ptr;
456 {
457   VARIABLE *tmp;
458   char *file;
459   FILE *fp;
460 
461   int i, j, ascflg = FALSE;
462 
463   file = var_to_string(ptr);
464 
465   if ((fp = fopen(file, "w")) == (FILE *)NULL)
466   {
467     error( "save: can't open file: %s.\n", file );
468   }
469 
470   tmp = NEXT(ptr);
471 
472   if (NEXT(NEXT(ptr)) != (VARIABLE *)NULL)
473     ascflg = M(NEXT(NEXT(ptr)), 0, 0);
474 
475   if (ascflg)
476   {
477 
478     fprintf(fp, "%d %d %d %d\n", FILE_ASCII, TYPE(tmp), NROW(tmp), NCOL(tmp));
479     if (ferror(fp))
480     {
481        fclose(fp); error("save: error writing file.\n");
482     }
483 
484     for(i = 0; i < NROW(tmp); i++)
485       for(j = 0; j < NCOL(tmp); j++)
486       {
487         fprintf(fp, "%e\n", M(tmp, i, j));
488         if (ferror(fp))
489         {
490            fclose(fp); error("save: error writing file.\n");
491         }
492       }
493   }
494 
495   else
496   {
497 
498     fprintf(fp, "%d %d %d %d\n", FILE_BINARY, TYPE(tmp), NROW(tmp), NCOL(tmp));
499     if (ferror(fp))
500     {
501        fclose(fp); error("save: error writing file.\n");
502     }
503 
504     fwrite(MATR(tmp), 1, MATSIZE(tmp), fp);
505     if (ferror(fp))
506     {
507        fclose(fp); error("save: error writing file.\n");
508     }
509   }
510 
511   fclose(fp); FREEMEM(file);
512 
513   return NULL;
514 }
515 
fil_load(ptr)516 VARIABLE *fil_load(ptr) VARIABLE *ptr;
517 {
518   int i, j, ftype, type, ncol, nrow;
519 
520   VARIABLE *res;
521 
522   char *file;
523   FILE *fp;
524   size_t iosize;
525   int iostat;
526 
527   file = var_to_string(ptr);
528 
529   if ((fp = fopen(file, "r")) == (FILE *)NULL)
530   {
531     error( "load: can't open file: %s.\n", file );
532   }
533 
534   iostat = fscanf(fp, "%d %d %d %d", &ftype, &type, &nrow, &ncol);
535 
536   if (ferror(fp)) {
537     fclose(fp); error("load: error reading file.n");
538   }
539 
540   res = var_temp_new(type, nrow, ncol);
541 
542   if (ftype == FILE_ASCII)
543   {
544     for(i = 0; i < nrow; i++)
545       for(j = 0; j < ncol; j++)
546       {
547         iostat = fscanf(fp, "%lf", &M(res, i, j));
548         if (ferror(fp))
549         {
550            fclose(fp); error("load: error reading file.\n");
551          }
552       }
553   }
554   else
555   {
556     fgetc(fp);
557     iosize = fread(MATR(res), 1, MATSIZE(res), fp);
558     if (ferror(fp))
559     {
560         fclose(fp); error("load: error reading file.\n");
561      }
562   }
563 
564   fclose(fp); FREEMEM(file);
565 
566   return res;
567 }
568 
fil_com_init()569 void fil_com_init()
570 {
571   static char *freadHelp =
572   {
573       "str = fread( fp,len )\n\n"
574       "Read len character  from file fp.  File pointer fp shoud have been\n"
575       "obtained from a call to fopen or freopen, or be the standard input\n"
576       "file stdin. Characters are returned as function value.\n"
577       "\n"
578       "SEE ALSO: fopen,freopen,fgets,fscanf,matcvt,cvtmat.\n"
579   };
580 
581   static char *fscanfHelp =
582   {
583       "vec = fscanf( fp,format )\n\n"
584       "Read file fp as given in format. Format is equal to C-language format\n"
585       "File pointer fp shoud have been obtained from a call to fopen or freopen,\n"
586       "or be the standard input.\n"
587       "\n"
588       "SEE ALSO: fopen,freopen,fgets,fread,matcvt,cvtmat.\n"
589   };
590 
591   static char *fgetsHelp =
592   {
593       "str = fgets( fp )\n\n"
594       "Read next line from fp. File pointer fp shoud have been obtained from a call\n"
595       "to fopen or freopen or be the standard input.\n"
596       "\n"
597       "SEE ALSO: fopen,freopen,fread,fscanf,matcvt,cvtmat.\n"
598   };
599 
600   static char *fwriteHelp =
601   {
602       "n = fwrite( fp, buf,len )\n\n"
603       "Write len bytes form buf to file fp. File pointer fp shoud have been obtained\n"
604       "from a call to fopen or freopen or be the standard output (stdout) or standard\n"
605       "error (stderr). Return value is number of characters actually written.\n"
606       "\n"
607       "SEE ALSO: fopen,freopen,fputs,fprintf,matcvt,cvtmat.\n"
608   };
609 
610   static char *fprintfHelp =
611   {
612       "n = fprintf( fp, format[, vec] )\n\n"
613       "Write formatted string to file fp. File pointer fp shoud have been obtained\n"
614       "from a call to fopen or freopen or be the standard output (stdout) or standard\n"
615       "error (stderr). The format is equal to C-language format.\n"
616       "\n"
617       "SEE ALSO: fopen,freopen,fputs,fwrite,matcvt,cvtmat.\n"
618   };
619 
620   static char *fputsHelp =
621   {
622       "fputs( fp, str )\n\n"
623       "Write line to file fp. File pointer fp should have been obtained from a call\n"
624       "to fopen or freopen or be the standard input (stdin).\n"
625       "\n"
626       "SEE ALSO: fopen,freopen,fwrite,matcvt,cvtmat.\n"
627   };
628 
629   static char *fopenHelp =
630   {
631       "fp = fopen( name, mode )\n\n"
632       "Open file given name and access mode. The most usual modes are \"r\" for reading\n"
633       "and \"w\" for writing. Return value fp is used in functions reading and writing\n"
634       "the file.\n"
635       "\n"
636       "SEE ALSO: freopen.\n"
637   };
638 
639   static char *freopenHelp =
640   {
641       "fp = freopen( fp, name, mode )\n\n"
642       "Reopen file given previous file pointer, name and access mode. The most usual modes\n"
643       "are \"r\" for reading and \"w\" for writing. Return value fp is used in functions  \n"
644       "reading and writing the file.\n"
645       "\n"
646       "SEE ALSO: fopen.\n"
647   };
648 
649   static char *fcloseHelp =
650   {
651       "fclose( fp )\n\n"
652       "Close file previously opened with fopen or freopen.\n"
653       "\n"
654       "SEE ALSO: fopen, freopen.\n"
655   };
656 
657   static char *saveHelp =
658   {
659       "save( name, matrix[, ascii_flag] )\n\n"
660       "Save matrix in file with name given as first parameter. If ascii_flag is\n"
661       "given and is not zero the file will be in ascii format, otherwise matrix\n"
662       "is saved in double precsision binary format. In either case the first line\n"
663       "of the file contains four digits (in ascii):\n\n"
664       "ascii_flag 0 NROW(matrix) NCOL(matrix).\n"
665       "\n"
666       "SEE ALSO: load.\n"
667   };
668 
669   static char *loadHelp =
670   {
671       "matrix = load( name )\n\n"
672       "Load matrix from a file given name and in format used by save-command.\n"
673       "\n"
674       "SEE ALSO: save.\n"
675   };
676 
677   com_init( "fread",   FALSE, FALSE, fil_fread,   2, 2, freadHelp   );
678   com_init( "fscanf",  FALSE, FALSE, fil_fscanf,  2, 2, fscanfHelp  );
679   com_init( "fgets",   FALSE, FALSE, fil_fgets,   1, 1, fgetsHelp   );
680   com_init( "fwrite",  FALSE, FALSE, fil_fwrite,  2, 3, fwriteHelp  );
681   com_init( "fprintf", FALSE, FALSE, fil_fprintf, 2, 3, fprintfHelp );
682   com_init( "fputs",   FALSE, FALSE, fil_fputs,   2, 2, fputsHelp   );
683   com_init( "fopen",   FALSE, FALSE, fil_fopen,   2, 2, fopenHelp   );
684   com_init( "freopen", FALSE, FALSE, fil_freopen, 3, 3, freopenHelp );
685   com_init( "fclose",  FALSE, FALSE, fil_fclose,  1, 1, fcloseHelp  );
686   com_init( "save",    FALSE, FALSE, fil_save,    2, 3, saveHelp    );
687   com_init( "load",    FALSE, FALSE, fil_load,    1, 1, loadHelp    );
688 
689   fil_fps[0] = fil_fps_save[0] = stdin;
690   fil_fps[1] = fil_fps_save[1] = stdout;
691   fil_fps[2] = fil_fps_save[2] = stderr;
692 }
693