1 
2 
3 /*----------------------------------------------------------*/
4 /*                                                          */
5 /*                        LIBMESH V 7.12                    */
6 /*                                                          */
7 /*----------------------------------------------------------*/
8 /*                                                          */
9 /*    Description:        handle .meshb file format I/O     */
10 /*    Author:             Loic MARECHAL                     */
11 /*    Creation date:      dec 08 2015                       */
12 /*    Last modification:  may 30 2016                       */
13 /*                                                          */
14 /*----------------------------------------------------------*/
15 
16 /*----------------------------------------------------------*/
17 /* Headers' macros                                          */
18 /*----------------------------------------------------------*/
19 
20 #ifdef F77API
21 
22 #ifdef F77_NO_UNDER_SCORE
23 #define NAMF77(c,f) f
24 #define APIF77(x) x
25 #else
26 #define NAMF77(c,f) f ## _
27 #define APIF77(x) x ## _
28 #endif
29 
30 #define VALF77(v) *v
31 #define TYPF77(t) t*
32 #define PRCF77(p) *((int *)p)
33 
34 #else
35 
36 #define NAMF77(c,f) c
37 #define VALF77(v) v
38 #define TYPF77(t) t
39 #define PRCF77(p) p
40 
41 #endif
42 
43 
44 /*----------------------------------------------------------*/
45 /* Includes                                                 */
46 /*----------------------------------------------------------*/
47 
48 #define _XOPEN_SOURCE 500
49 
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <stdarg.h>
53 #include <string.h>
54 #include <float.h>
55 #include <math.h>
56 #include <ctype.h>
57 #include <setjmp.h>
58 #include <fcntl.h>
59 
60 
61 /*
62  * [Bruno] include the headers with the prototypes for
63  *  open()/close()/write()/lseek()
64  *  and define the constants to be used to open() a file.
65  *    Under Windows,
66  *  1)   _O_BINARY should be set in the flags.
67  *  2) 'mode' has a completely different meaning
68  */
69 
70 #if defined(__unix__) || defined(__linux__) || defined(__APPLE__) || defined(__EMSCRIPTEN__)
71 
72 #include <unistd.h>
73 
74 #define OPEN_READ_FLAGS    O_RDONLY
75 #define OPEN_WRITE_FLAGS   O_CREAT | O_WRONLY | O_TRUNC
76 #define OPEN_READ_MODE     0666
77 #define OPEN_WRITE_MODE    0666
78 
79 #elif defined(WIN32) || defined(_WIN64)
80 
81 #define GMF_WINDOWS
82 
83 #include <windows.h>
84 #include <io.h>
85 #include <sys/stat.h>
86 
87 #define OPEN_READ_FLAGS   O_RDONLY | _O_BINARY
88 #define OPEN_WRITE_FLAGS  O_CREAT | O_WRONLY | O_TRUNC | _O_BINARY
89 #define OPEN_READ_MODE    _S_IREAD
90 #define OPEN_WRITE_MODE   _S_IREAD | S_IWRITE
91 
92 #endif
93 
94 #include <errno.h>
95 #include <geogram/third_party/LM7/libmeshb7.h>
96 
97 /* [Bruno] Using portable printf modifier from pstdint.h        */
98 /* (alternative: use "%zd" under Linux and "%Id" under Windows) */
99 
100 #ifdef PRINTF_INT64_MODIFIER
101 #define INT64_T_FMT "%" PRINTF_INT64_MODIFIER "d"
102 #else
103 #   ifdef GMF_WINDOWS
104 #     define INT64_T_FMT "%Id"
105 #   else
106 #     define INT64_T_FMT "%zd"
107 #   endif
108 #endif
109 
110 /* [Bruno] Made asynchronous I/O optional */
111 #ifdef WITH_AIO
112 #include <aio.h>
113 #endif
114 
115 
116 
117 /*----------------------------------------------------------*/
118 /* Defines                                                  */
119 /*----------------------------------------------------------*/
120 
121 #define Asc 1
122 #define Bin 2
123 #define MshFil 4
124 #define SolFil 8
125 #define InfKwd 1
126 #define RegKwd 2
127 #define SolKwd 3
128 #define CmtKwd 4
129 #define WrdSiz 4
130 #define FilStrSiz 64
131 #define BufSiz 10000
132 #define MaxArg 20
133 
134 
135 /*----------------------------------------------------------*/
136 /* Structures                                               */
137 /*----------------------------------------------------------*/
138 
139 typedef struct
140 {
141     int typ, SolSiz, NmbWrd, NmbTyp, TypTab[ GmfMaxTyp ];
142     int64_t NmbLin, pos;
143     char fmt[ GmfMaxTyp*9 ];
144 }KwdSct;
145 
146 typedef struct
147 {
148     int dim, ver, mod, typ, cod, FilDes;
149     int64_t NexKwdPos, siz, pos;
150     jmp_buf err;
151     KwdSct KwdTab[ GmfMaxKwd + 1 ];
152     FILE *hdl;
153     int *IntBuf;
154     float *FltBuf;
155     char *buf;
156     char FilNam[ GmfStrSiz ];
157     double DblBuf[1000/8];
158     unsigned char blk[ BufSiz + 1000 ];
159 }GmfMshSct;
160 
161 
162 /*----------------------------------------------------------*/
163 /* Global variables                                         */
164 /*----------------------------------------------------------*/
165 
166 const char *GmfKwdFmt[ GmfMaxKwd + 1 ][4] =
167 {    {"Reserved", "", "", ""},
168     {"MeshVersionFormatted", "", "", "i"},
169     {"Reserved", "", "", ""},
170     {"Dimension", "", "", "i"},
171     {"Vertices", "Vertex", "i", "dri"},
172     {"Edges", "Edge", "i", "iii"},
173     {"Triangles", "Triangle", "i", "iiii"},
174     {"Quadrilaterals", "Quadrilateral", "i", "iiiii"},
175     {"Tetrahedra", "Tetrahedron", "i", "iiiii"},
176     {"Prisms", "Prism", "i", "iiiiiii"},
177     {"Hexahedra", "Hexahedron", "i", "iiiiiiiii"},
178     {"IterationsAll", "IterationAll","","i"},
179     {"TimesAll", "TimeAll","","r"},
180     {"Corners", "Corner", "i", "i"},
181     {"Ridges", "Ridge", "i", "i"},
182     {"RequiredVertices", "RequiredVertex", "i", "i"},
183     {"RequiredEdges", "RequiredEdge", "i", "i"},
184     {"RequiredTriangles", "RequiredTriangle", "i", "i"},
185     {"RequiredQuadrilaterals", "RequiredQuadrilateral", "i", "i"},
186     {"TangentAtEdgeVertices", "TangentAtEdgeVertex", "i", "iii"},
187     {"NormalAtVertices", "NormalAtVertex", "i", "ii"},
188     {"NormalAtTriangleVertices", "NormalAtTriangleVertex", "i", "iii"},
189     {"NormalAtQuadrilateralVertices", "NormalAtQuadrilateralVertex", "i", "iiii"},
190     {"AngleOfCornerBound", "", "", "r"},
191     {"TrianglesP2", "TriangleP2", "i", "iiiiiii"},
192     {"EdgesP2", "EdgeP2", "i", "iiii"},
193     {"SolAtPyramids", "SolAtPyramid", "i", "sr"},
194     {"QuadrilateralsQ2", "QuadrilateralQ2", "i", "iiiiiiiiii"},
195     {"ISolAtPyramids", "ISolAtPyramid", "i", "iiiii"},
196     {"SubDomainFromGeom", "SubDomainFromGeom", "i", "iii"},
197     {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"},
198     {"Fault_NearTri", "Fault_NearTri", "i", "i"},
199     {"Fault_Inter", "Fault_Inter", "i", "i"},
200     {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"},
201     {"ExtraVerticesAtEdges", "ExtraVerticesAtEdge", "i", "in"},
202     {"ExtraVerticesAtTriangles", "ExtraVerticesAtTriangle", "i", "in"},
203     {"ExtraVerticesAtQuadrilaterals", "ExtraVerticesAtQuadrilateral", "i", "in"},
204     {"ExtraVerticesAtTetrahedra", "ExtraVerticesAtTetrahedron", "i", "in"},
205     {"ExtraVerticesAtPrisms", "ExtraVerticesAtPrism", "i", "in"},
206     {"ExtraVerticesAtHexahedra", "ExtraVerticesAtHexahedron", "i", "in"},
207     {"VerticesOnGeometricVertices", "VertexOnGeometricVertex", "i", "iir"},
208     {"VerticesOnGeometricEdges", "VertexOnGeometricEdge", "i", "iirr"},
209     {"VerticesOnGeometricTriangles", "VertexOnGeometricTriangle", "i", "iirrr"},
210     {"VerticesOnGeometricQuadrilaterals", "VertexOnGeometricQuadrilateral", "i", "iirrr"},
211     {"EdgesOnGeometricEdges", "EdgeOnGeometricEdge", "i", "iir"},
212     {"Fault_FreeEdge", "Fault_FreeEdge", "i", "i"},
213     {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"},
214     {"Polygons", "Polygon", "", "iiiiiiiii"},
215     {"Fault_Overlap", "Fault_Overlap", "i", "i"},
216     {"Pyramids", "Pyramid", "i", "iiiiii"},
217     {"BoundingBox", "", "", "drdr"},
218     {"Body","i", "drdrdrdr"},
219     {"PrivateTable", "PrivateTable", "i", "i"},
220     {"Fault_BadShape", "Fault_BadShape", "i", "i"},
221     {"End", "", "", ""},
222     {"TrianglesOnGeometricTriangles", "TriangleOnGeometricTriangle", "i", "iir"},
223     {"TrianglesOnGeometricQuadrilaterals", "TriangleOnGeometricQuadrilateral", "i", "iir"},
224     {"QuadrilateralsOnGeometricTriangles", "QuadrilateralOnGeometricTriangle", "i", "iir"},
225     {"QuadrilateralsOnGeometricQuadrilaterals", "QuadrilateralOnGeometricQuadrilateral", "i", "iir"},
226     {"Tangents", "Tangent", "i", "dr"},
227     {"Normals", "Normal", "i", "dr"},
228     {"TangentAtVertices", "TangentAtVertex", "i", "ii"},
229     {"SolAtVertices", "SolAtVertex", "i", "sr"},
230     {"SolAtEdges", "SolAtEdge", "i", "sr"},
231     {"SolAtTriangles", "SolAtTriangle", "i", "sr"},
232     {"SolAtQuadrilaterals", "SolAtQuadrilateral", "i", "sr"},
233     {"SolAtTetrahedra", "SolAtTetrahedron", "i", "sr"},
234     {"SolAtPrisms", "SolAtPrism", "i", "sr"},
235     {"SolAtHexahedra", "SolAtHexahedron", "i", "sr"},
236     {"DSolAtVertices", "DSolAtVertex", "i", "sr"},
237     {"ISolAtVertices", "ISolAtVertex", "i", "i"},
238     {"ISolAtEdges", "ISolAtEdge", "i", "ii"},
239     {"ISolAtTriangles", "ISolAtTriangle", "i", "iii"},
240     {"ISolAtQuadrilaterals", "ISolAtQuadrilateral", "i", "iiii"},
241     {"ISolAtTetrahedra", "ISolAtTetrahedron", "i", "iiii"},
242     {"ISolAtPrisms", "ISolAtPrism", "i", "iiiiii"},
243     {"ISolAtHexahedra", "ISolAtHexahedron", "i", "iiiiiiii"},
244     {"Iterations", "","","i"},
245     {"Time", "","","r"},
246     {"Fault_SmallTri", "Fault_SmallTri","i","i"},
247     {"CoarseHexahedra", "CoarseHexahedron", "i", "i"},
248     {"Comments", "Comment", "i", "c"},
249     {"PeriodicVertices", "PeriodicVertex", "i", "ii"},
250     {"PeriodicEdges", "PeriodicEdge", "i", "ii"},
251     {"PeriodicTriangles", "PeriodicTriangle", "i", "ii"},
252     {"PeriodicQuadrilaterals", "PeriodicQuadrilateral", "i", "ii"},
253     {"PrismsP2", "PrismP2", "i", "iiiiiiiiiiiiiiiiiii"},
254     {"PyramidsP2", "PyramidP2", "i", "iiiiiiiiiiiiiii"},
255     {"QuadrilateralsQ3", "QuadrilateralQ3", "i", "iiiiiiiiiiiiiiiii"},
256     {"QuadrilateralsQ4", "QuadrilateralQ4", "i", "iiiiiiiiiiiiiiiiiiiiiiiiii"},
257     {"TrianglesP3", "TriangleP3", "i", "iiiiiiiiiii"},
258     {"TrianglesP4", "TriangleP4", "i", "iiiiiiiiiiiiiiii"},
259     {"EdgesP3", "EdgeP3", "i", "iiiii"},
260     {"EdgesP4", "EdgeP4", "i", "iiiiii"},
261     {"IRefGroups", "IRefGroup", "i", "c,i,i,i"},
262     {"DRefGroups", "DRefGroup", "i", "i,i"}
263  };
264 
265 #ifdef TRANSMESH
266 int GmfMaxRefTab[ GmfMaxKwd + 1 ];
267 #endif
268 
269 
270 /*----------------------------------------------------------*/
271 /* Prototypes of local procedures                           */
272 /*----------------------------------------------------------*/
273 
274 static void ScaWrd(GmfMshSct *, void *);
275 static void ScaDblWrd(GmfMshSct *, void *);
276 static int64_t GetPos(GmfMshSct *);
277 static void RecWrd(GmfMshSct *, const void *);
278 static void RecDblWrd(GmfMshSct *, const void *);
279 static void RecBlk(GmfMshSct *, const void *, int);
280 static void SetPos(GmfMshSct *, int64_t);
281 static int ScaKwdTab(GmfMshSct *);
282 static void ExpFmt(GmfMshSct *, int);
283 static void ScaKwdHdr(GmfMshSct *, int);
284 static void SwpWrd(char *, int);
285 static int SetFilPos(GmfMshSct *, int64_t);
286 static int64_t GetFilPos(GmfMshSct *msh);
287 static int64_t GetFilSiz(GmfMshSct *);
288 #ifdef F77API
289 static void CalF77Prc(int64_t, int64_t, void *, int, void **);
290 #endif
291 
292 
293 /*----------------------------------------------------------*/
294 /* Fscanf and fgets checking for errors                     */
295 /*----------------------------------------------------------*/
296 
297 #define safe_fscanf(hdl, format, ptr, JmpErr) \
298     do { \
299         if( fscanf(hdl, format, ptr) != 1 ) \
300             longjmp( JmpErr, -1); \
301     } while(0)
302 
303 
304 #define safe_fgets(ptr, siz, hdl, JmpErr) \
305     do { \
306         if( fgets(ptr, siz, hdl) == NULL ) \
307             longjmp( JmpErr, -1); \
308     } while(0)
309 
310 
311 /*----------------------------------------------------------*/
312 /* Open a mesh file in read or write mod                    */
313 /*----------------------------------------------------------*/
314 
GmfOpenMesh(char * FilNam,int mod,...)315 int64_t GmfOpenMesh(char *FilNam, int mod, ...)
316 {
317     int KwdCod, res, *PtrVer, *PtrDim;
318     int64_t MshIdx;
319     char str[ GmfStrSiz ];
320     va_list VarArg;
321     GmfMshSct *msh;
322 
323     /*---------------------*/
324     /* MESH STRUCTURE INIT */
325     /*---------------------*/
326 
327     if(!(msh = calloc(1, sizeof(GmfMshSct))))
328         return(0);
329 
330     MshIdx = (int64_t)msh;
331 
332     /* Save the current stack environment for longjmp */
333 
334     if(setjmp(msh->err) != 0)
335     {
336         if(msh->hdl != NULL)
337             fclose(msh->hdl);
338 
339         if(msh->FilDes != 0)
340             close(msh->FilDes);
341 
342         free(msh);
343         return(0);
344     }
345 
346     /* Copy the FilNam into the structure */
347 
348     if(strlen(FilNam) + 7 >= GmfStrSiz)
349         longjmp(msh->err, -1);
350 
351     strcpy(msh->FilNam, FilNam);
352 
353     /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */
354 
355     msh->mod = mod;
356     msh->buf = (void *)msh->DblBuf;
357     msh->FltBuf = (void *)msh->DblBuf;
358     msh->IntBuf = (void *)msh->DblBuf;
359 
360     if(strstr(msh->FilNam, ".meshb"))
361         msh->typ |= (Bin | MshFil);
362     else if(strstr(msh->FilNam, ".mesh"))
363         msh->typ |= (Asc | MshFil);
364     else if(strstr(msh->FilNam, ".solb"))
365         msh->typ |= (Bin | SolFil);
366     else if(strstr(msh->FilNam, ".sol"))
367         msh->typ |= (Asc | SolFil);
368     else
369         longjmp(msh->err, -1);
370 
371     /* Open the file in the required mod and initialyse the mesh structure */
372 
373     if(msh->mod == GmfRead)
374     {
375 
376         /*-----------------------*/
377         /* OPEN FILE FOR READING */
378         /*-----------------------*/
379 
380         va_start(VarArg, mod);
381         PtrVer = va_arg(VarArg, int *);
382         PtrDim = va_arg(VarArg, int *);
383         va_end(VarArg);
384 
385         /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */
386 
387         if(msh->typ & Bin)
388         {
389             /* Create the name string and open the file */
390 
391             /* [Bruno] added binary flag (necessary under Windows) */
392             msh->FilDes = open(msh->FilNam, OPEN_READ_FLAGS, OPEN_READ_MODE);
393 
394             if(msh->FilDes <= 0)
395                 longjmp(msh->err, -1);
396 
397             /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */
398 
399             if(read(msh->FilDes, &msh->cod, WrdSiz) != WrdSiz)
400                 longjmp(msh->err, -1);
401 
402             if( (msh->cod != 1) && (msh->cod != 16777216) )
403                 longjmp(msh->err, -1);
404 
405             ScaWrd(msh, (unsigned char *)&msh->ver);
406 
407             if( (msh->ver < 1) || (msh->ver > 4) )
408                 longjmp(msh->err, -1);
409 
410             if( (msh->ver >= 3) && (sizeof(int64_t) != 8) )
411                 longjmp(msh->err, -1);
412 
413             ScaWrd(msh, (unsigned char *)&KwdCod);
414 
415             if(KwdCod != GmfDimension)
416                 longjmp(msh->err, -1);
417 
418             GetPos(msh);
419             ScaWrd(msh, (unsigned char *)&msh->dim);
420         }
421         else
422         {
423             /* Create the name string and open the file */
424 
425             if(!(msh->hdl = fopen(msh->FilNam, "rb")))
426                 longjmp(msh->err, -1);
427 
428             do
429             {
430                 res = fscanf(msh->hdl, "%s", str);
431             }while( (res != EOF) && strcmp(str, "MeshVersionFormatted") );
432 
433             if(res == EOF)
434                 longjmp(msh->err, -1);
435 
436             safe_fscanf(msh->hdl, "%d", &msh->ver, msh->err);
437 
438             if( (msh->ver < 1) || (msh->ver > 4) )
439                 longjmp(msh->err, -1);
440 
441             do
442             {
443                 res = fscanf(msh->hdl, "%s", str);
444             }while( (res != EOF) && strcmp(str, "Dimension") );
445 
446             if(res == EOF)
447                 longjmp(msh->err, -1);
448 
449             safe_fscanf(msh->hdl, "%d", &msh->dim, msh->err);
450         }
451 
452         if( (msh->dim != 2) && (msh->dim != 3) )
453             longjmp(msh->err, -1);
454 
455         (*PtrVer) = msh->ver;
456         (*PtrDim) = msh->dim;
457 
458         /*------------*/
459         /* KW READING */
460         /*------------*/
461 
462         /* Read the list of kw present in the file */
463 
464         if(!ScaKwdTab(msh))
465             return(0);
466 
467         return(MshIdx);
468     }
469     else if(msh->mod == GmfWrite)
470     {
471 
472         /*-----------------------*/
473         /* OPEN FILE FOR WRITING */
474         /*-----------------------*/
475 
476         msh->cod = 1;
477 
478         /* Check if the user provided a valid version number and dimension */
479 
480         va_start(VarArg, mod);
481         msh->ver = va_arg(VarArg, int);
482         msh->dim = va_arg(VarArg, int);
483         va_end(VarArg);
484 
485         if( (msh->ver < 1) || (msh->ver > 4) )
486             longjmp(msh->err, -1);
487 
488         if( (msh->ver >= 3) && (sizeof(int64_t) != 8) )
489             longjmp(msh->err, -1);
490 
491         if( (msh->dim != 2) && (msh->dim != 3) )
492             longjmp(msh->err, -1);
493 
494         /* Create the mesh file */
495 
496         if(msh->typ & Bin)
497         {
498             /*
499              * [Bruno] replaced previous call to creat():
500              * with a call to open(), because Windows needs the
501              * binary flag to be specified.
502              */
503             msh->FilDes = open(msh->FilNam, OPEN_WRITE_FLAGS, OPEN_WRITE_MODE);
504 
505             if(msh->FilDes <= 0)
506                 longjmp(msh->err, -1);
507         }
508         else if(!(msh->hdl = fopen(msh->FilNam, "wb")))
509             longjmp(msh->err, -1);
510 
511 
512         /*------------*/
513         /* KW WRITING */
514         /*------------*/
515 
516         /* Write the mesh version and dimension */
517 
518         if(msh->typ & Asc)
519         {
520             fprintf(msh->hdl, "%s %d\n\n", GmfKwdFmt[ GmfVersionFormatted ][0], msh->ver);
521             fprintf(msh->hdl, "%s %d\n", GmfKwdFmt[ GmfDimension ][0], msh->dim);
522         }
523         else
524         {
525             RecWrd(msh, (unsigned char *)&msh->cod);
526             RecWrd(msh, (unsigned char *)&msh->ver);
527             GmfSetKwd(MshIdx, GmfDimension, 0);
528             RecWrd(msh, (unsigned char *)&msh->dim);
529         }
530 
531         return(MshIdx);
532     }
533     else
534     {
535         free(msh);
536         return(0);
537     }
538 }
539 
540 
541 /*----------------------------------------------------------*/
542 /* Close a meshfile in the right way                        */
543 /*----------------------------------------------------------*/
544 
GmfCloseMesh(int64_t MshIdx)545 int GmfCloseMesh(int64_t MshIdx)
546 {
547     int res = 1;
548     GmfMshSct *msh = (GmfMshSct *)MshIdx;
549 
550     RecBlk(msh, msh->buf, 0);
551 
552     /* In write down the "End" kw in write mode */
553 
554     if(msh->mod == GmfWrite)
555     {
556         if(msh->typ & Asc)
557             fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ GmfEnd ][0]);
558         else
559             GmfSetKwd(MshIdx, GmfEnd, 0);
560     }
561 
562     /* Close the file and free the mesh structure */
563 
564     if(msh->typ & Bin)
565         close(msh->FilDes);
566     else if(fclose(msh->hdl))
567         res = 0;
568 
569     free(msh);
570 
571     return(res);
572 }
573 
574 
575 /*----------------------------------------------------------*/
576 /* Read the number of lines and set the position to this kwd*/
577 /*----------------------------------------------------------*/
578 
GmfStatKwd(int64_t MshIdx,int KwdCod,...)579 int64_t GmfStatKwd(int64_t MshIdx, int KwdCod, ...)
580 {
581     int i, *PtrNmbTyp, *PtrSolSiz, *TypTab;
582     GmfMshSct *msh = (GmfMshSct *)MshIdx;
583     KwdSct *kwd;
584     va_list VarArg;
585 
586     if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
587         return(0);
588 
589     kwd = &msh->KwdTab[ KwdCod ];
590 
591     if(!kwd->NmbLin)
592         return(0);
593 
594     /* Read further arguments if this kw is a sol */
595 
596     if(kwd->typ == SolKwd)
597     {
598         va_start(VarArg, KwdCod);
599 
600         PtrNmbTyp = va_arg(VarArg, int *);
601         *PtrNmbTyp = kwd->NmbTyp;
602 
603         PtrSolSiz = va_arg(VarArg, int *);
604         *PtrSolSiz = kwd->SolSiz;
605 
606         TypTab = va_arg(VarArg, int *);
607 
608         for(i=0;i<kwd->NmbTyp;i++)
609             TypTab[i] = kwd->TypTab[i];
610 
611         va_end(VarArg);
612     }
613 
614     return(kwd->NmbLin);
615 }
616 
617 
618 /*----------------------------------------------------------*/
619 /* Set the current file position to a given kwd              */
620 /*----------------------------------------------------------*/
621 
GmfGotoKwd(int64_t MshIdx,int KwdCod)622 int GmfGotoKwd(int64_t MshIdx, int KwdCod)
623 {
624     GmfMshSct *msh = (GmfMshSct *)MshIdx;
625     KwdSct *kwd = &msh->KwdTab[ KwdCod ];
626 
627     if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) || !kwd->NmbLin )
628         return(0);
629 
630     return(SetFilPos(msh, kwd->pos));
631 }
632 
633 
634 /*----------------------------------------------------------*/
635 /* Write the kwd and set the number of lines                */
636 /*----------------------------------------------------------*/
637 
GmfSetKwd(int64_t MshIdx,int KwdCod,...)638 int GmfSetKwd(int64_t MshIdx, int KwdCod, ...)
639 {
640     int i, *TypTab;
641     int64_t NmbLin=0, CurPos;
642     va_list VarArg;
643     GmfMshSct *msh = (GmfMshSct *)MshIdx;
644     KwdSct *kwd;
645 
646     RecBlk(msh, msh->buf, 0);
647 
648     if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
649         return(0);
650 
651     kwd = &msh->KwdTab[ KwdCod ];
652 
653     /* Read further arguments if this kw has a header */
654 
655     if(strlen(GmfKwdFmt[ KwdCod ][2]))
656     {
657         va_start(VarArg, KwdCod);
658         NmbLin = va_arg(VarArg, int64_t);
659 
660         if(!strcmp(GmfKwdFmt[ KwdCod ][3], "sr"))
661         {
662             kwd->NmbTyp = va_arg(VarArg, int);
663             TypTab = va_arg(VarArg, int *);
664 
665             for(i=0;i<kwd->NmbTyp;i++)
666                 kwd->TypTab[i] = TypTab[i];
667         }
668 
669         va_end(VarArg);
670     }
671 
672     /* Setup the kwd info */
673 
674     ExpFmt(msh, KwdCod);
675 
676     if(!kwd->typ)
677         return(0);
678     else if(kwd->typ == InfKwd)
679         kwd->NmbLin = 1;
680     else
681         kwd->NmbLin = NmbLin;
682 
683     /* Store the next kwd position in binary file */
684 
685     if( (msh->typ & Bin) && msh->NexKwdPos )
686     {
687         CurPos = GetFilPos(msh);
688 
689         if(!SetFilPos(msh, msh->NexKwdPos))
690             return(0);
691 
692         SetPos(msh, CurPos);
693 
694         if(!SetFilPos(msh, CurPos))
695             return(0);
696     }
697 
698     /* Write the header */
699 
700     if(msh->typ & Asc)
701     {
702         fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ KwdCod ][0]);
703 
704         if(kwd->typ != InfKwd)
705             fprintf(msh->hdl, INT64_T_FMT"\n", kwd->NmbLin);
706 
707         /* In case of solution field, write the extended header */
708 
709         if(kwd->typ == SolKwd)
710         {
711             fprintf(msh->hdl, "%d ", kwd->NmbTyp);
712 
713             for(i=0;i<kwd->NmbTyp;i++)
714                 fprintf(msh->hdl, "%d ", kwd->TypTab[i]);
715 
716             fprintf(msh->hdl, "\n\n");
717         }
718     }
719     else
720     {
721         RecWrd(msh, (unsigned char *)&KwdCod);
722         msh->NexKwdPos = GetFilPos(msh);
723         SetPos(msh, 0);
724 
725         if(kwd->typ != InfKwd)
726         {
727             if(msh->ver < 4)
728             {
729                 i = (int)kwd->NmbLin;
730                 RecWrd(msh, (unsigned char *)&i);
731             }
732             else
733                 RecDblWrd(msh, (unsigned char *)&kwd->NmbLin);
734         }
735 
736         /* In case of solution field, write the extended header at once */
737 
738         if(kwd->typ == SolKwd)
739         {
740             RecWrd(msh, (unsigned char *)&kwd->NmbTyp);
741 
742             for(i=0;i<kwd->NmbTyp;i++)
743                 RecWrd(msh, (unsigned char *)&kwd->TypTab[i]);
744         }
745     }
746 
747     /* Reset write buffer position */
748     msh->pos = 0;
749 
750     /* Estimate the total file size and check whether it crosses the 2GB threshold */
751     msh->siz += kwd->NmbLin * kwd->NmbWrd * WrdSiz;
752 
753     return(1);
754 }
755 
756 
757 /*----------------------------------------------------------*/
758 /* Read a full line from the current kwd                    */
759 /*----------------------------------------------------------*/
760 
NAMF77(GmfGetLin,gmfgetlin)761 extern int NAMF77(GmfGetLin, gmfgetlin)(TYPF77(int64_t) MshIdx, TYPF77(int) KwdCod, ...)
762 {
763     int i, j;
764     float *FltSolTab;
765     double *DblSolTab;
766     va_list VarArg;
767     GmfMshSct *msh = (GmfMshSct *) VALF77(MshIdx);
768     KwdSct *kwd = &msh->KwdTab[ VALF77(KwdCod) ];
769 
770     if( (VALF77(KwdCod) < 1) || (VALF77(KwdCod) > GmfMaxKwd) )
771         return(0);
772 
773     /* Save the current stack environment for longjmp */
774 
775     if(setjmp(msh->err) != 0)
776         return(0);
777 
778     /* Start decoding the arguments */
779 
780     va_start(VarArg, KwdCod);
781 
782     switch(kwd->typ)
783     {
784         case InfKwd : case RegKwd : case CmtKwd :
785         {
786             if(msh->typ & Asc)
787             {
788                 for(i=0;i<kwd->SolSiz;i++)
789                     if(kwd->fmt[i] == 'r')
790                         if(msh->ver <= 1)
791                             safe_fscanf(msh->hdl, "%f", va_arg(VarArg, float *), msh->err);
792                         else
793                             safe_fscanf(msh->hdl, "%lf", va_arg(VarArg, double *), msh->err);
794                     else if(kwd->fmt[i] == 'i')
795                         if(msh->ver <= 3)
796                             safe_fscanf(msh->hdl, "%d", va_arg(VarArg, int *), msh->err);
797                         else
798                             /* [Bruno] %ld -> INT64_T_FMT */
799                             safe_fscanf(msh->hdl, INT64_T_FMT, va_arg(VarArg, int64_t *), msh->err);
800                     else if(kwd->fmt[i] == 'c')
801                         safe_fgets(va_arg(VarArg, char *), WrdSiz * FilStrSiz, msh->hdl, msh->err);
802             }
803             else
804             {
805                 for(i=0;i<kwd->SolSiz;i++)
806                     if(kwd->fmt[i] == 'r')
807                         if(msh->ver <= 1)
808                             ScaWrd(msh, (unsigned char *)va_arg(VarArg, float *));
809                         else
810                             ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, double *));
811                     else if(kwd->fmt[i] == 'i')
812                         if(msh->ver <= 3)
813                             ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
814                         else
815                             ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, int64_t *));
816                     else if(kwd->fmt[i] == 'c')
817                         /* [Bruno] added error control */
818                         if(fread(va_arg(VarArg, char *), WrdSiz, FilStrSiz, msh->hdl) != FilStrSiz) {
819                             longjmp(msh->err, -1);
820                         }
821             }
822         }break;
823 
824         case SolKwd :
825         {
826             if(msh->ver == 1)
827             {
828                 FltSolTab = va_arg(VarArg, float *);
829 
830                 if(msh->typ & Asc)
831                     for(j=0;j<kwd->SolSiz;j++)
832                         safe_fscanf(msh->hdl, "%f", &FltSolTab[j], msh->err);
833                 else
834                     for(j=0;j<kwd->SolSiz;j++)
835                         ScaWrd(msh, (unsigned char *)&FltSolTab[j]);
836             }
837             else
838             {
839                 DblSolTab = va_arg(VarArg, double *);
840 
841                 if(msh->typ & Asc)
842                     for(j=0;j<kwd->SolSiz;j++)
843                         safe_fscanf(msh->hdl, "%lf", &DblSolTab[j], msh->err);
844                 else
845                     for(j=0;j<kwd->SolSiz;j++)
846                         ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]);
847             }
848         }break;
849     }
850 
851     va_end(VarArg);
852 
853     return(1);
854 }
855 
856 
857 /*----------------------------------------------------------*/
858 /* Write a full line from the current kwd                   */
859 /*----------------------------------------------------------*/
860 
NAMF77(GmfSetLin,gmfsetlin)861 extern int NAMF77(GmfSetLin, gmfsetlin)(TYPF77(int64_t) MshIdx, TYPF77(int) KwdCod, ...)
862 {
863     int i, j, pos, *IntBuf;
864     int64_t *LngBuf;
865     float *FltSolTab, *FltBuf;
866     double *DblSolTab, *DblBuf;
867     va_list VarArg;
868     GmfMshSct *msh = (GmfMshSct *) VALF77(MshIdx);
869     KwdSct *kwd = &msh->KwdTab[ VALF77(KwdCod) ];
870 
871     if( ( VALF77(KwdCod) < 1) || ( VALF77(KwdCod) > GmfMaxKwd) )
872         return(0);
873 
874     /* Start decoding the arguments */
875 
876     va_start(VarArg, KwdCod);
877 
878     if(kwd->typ != SolKwd)
879     {
880         if(msh->typ & Asc)
881         {
882             for(i=0;i<kwd->SolSiz;i++)
883             {
884                 if(kwd->fmt[i] == 'r')
885                 {
886                     if(msh->ver <= 1)
887                         fprintf(msh->hdl, "%g ", VALF77(va_arg(VarArg, TYPF77(double))));
888                     else
889                         fprintf(msh->hdl, "%.15g ", VALF77(va_arg(VarArg, TYPF77(double))));
890                 }
891                 else if(kwd->fmt[i] == 'i')
892                 {
893                     if(msh->ver <= 3)
894                         fprintf(msh->hdl, "%d ", VALF77(va_arg(VarArg, TYPF77(int))));
895                     else
896                         /* [Bruno] %ld -> INT64_T_FMT */
897                         fprintf(msh->hdl, INT64_T_FMT " ", VALF77(va_arg(VarArg, TYPF77(int64_t))));
898                 }
899                 else if(kwd->fmt[i] == 'c')
900                     fprintf(msh->hdl, "%s ", va_arg(VarArg, char *));
901             }
902         }
903         else
904         {
905             pos = 0;
906 
907             for(i=0;i<kwd->SolSiz;i++)
908             {
909                 if(kwd->fmt[i] == 'r')
910                 {
911                     if(msh->ver <= 1)
912                     {
913                         FltBuf = (void *)&msh->buf[ pos ];
914                         *FltBuf = (float) VALF77(va_arg(VarArg, TYPF77(double)));
915                         pos += 4;
916                     }
917                     else
918                     {
919                         DblBuf = (void *)&msh->buf[ pos ];
920                         *DblBuf = VALF77(va_arg(VarArg, TYPF77(double)));
921                         pos += 8;
922                     }
923                 }
924                 else if(kwd->fmt[i] == 'i')
925                 {
926                     if(msh->ver <= 3)
927                     {
928                         IntBuf = (void *)&msh->buf[ pos ];
929                         *IntBuf = VALF77(va_arg(VarArg, TYPF77(int)));
930                         pos += 4;
931                     }
932                     else
933                     {
934                         LngBuf = (void *)&msh->buf[ pos ];
935                         *LngBuf = VALF77(va_arg(VarArg, TYPF77(int64_t)));
936                         pos += 8;
937                     }
938                 }
939                 else if(kwd->fmt[i] == 'c')
940                 {
941                     memset(&msh->buf[ pos ], 0, FilStrSiz * WrdSiz);
942                     strncpy(&msh->buf[ pos ], va_arg(VarArg, char *), FilStrSiz * WrdSiz);
943                     pos += FilStrSiz;
944                 }
945             }
946 
947             RecBlk(msh, msh->buf, kwd->NmbWrd);
948         }
949     }
950     else
951     {
952         if(msh->ver == 1)
953         {
954             FltSolTab = va_arg(VarArg, float *);
955 
956             if(msh->typ & Asc)
957                 for(j=0;j<kwd->SolSiz;j++)
958                     fprintf(msh->hdl, "%g ", (double)FltSolTab[j]);
959             else
960                 RecBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
961         }
962         else
963         {
964             DblSolTab = va_arg(VarArg, double *);
965 
966             if(msh->typ & Asc)
967                 for(j=0;j<kwd->SolSiz;j++)
968                     fprintf(msh->hdl, "%.15g ", DblSolTab[j]);
969             else
970                 RecBlk(msh, (unsigned char *)DblSolTab, kwd->NmbWrd);
971         }
972     }
973 
974     va_end(VarArg);
975 
976     if(msh->typ & Asc)
977         fprintf(msh->hdl, "\n");
978 
979     return(1);
980 }
981 
982 
983 /*----------------------------------------------------------*/
984 /* Private procedure for transmesh : copy a whole line      */
985 /*----------------------------------------------------------*/
986 
987 #ifdef TRANSMESH
988 
GmfCpyLin(int64_t InpIdx,int64_t OutIdx,int KwdCod)989 int GmfCpyLin(int64_t InpIdx, int64_t OutIdx, int KwdCod)
990 {
991         char s[ WrdSiz * FilStrSiz ];
992         double d;
993         float f;
994         int i, a;
995         int64_t l;
996         GmfMshSct *InpMsh = (GmfMshSct *)InpIdx, *OutMsh = (GmfMshSct *)OutIdx;
997         KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ];
998 
999         /* Save the current stack environment for longjmp */
1000 
1001         if(setjmp(InpMsh->err) != 0)
1002                 return(0);
1003 
1004         for(i=0;i<kwd->SolSiz;i++)
1005         {
1006                 if(kwd->fmt[i] == 'r')
1007                 {
1008                         if(InpMsh->ver == 1)
1009                         {
1010                                 if(InpMsh->typ & Asc)
1011                                         safe_fscanf(InpMsh->hdl, "%f", &f, InpMsh->err);
1012                                 else
1013                                         ScaWrd(InpMsh, (unsigned char *)&f);
1014 
1015                                 d = (double)f;
1016                         }
1017                         else
1018                         {
1019                                 if(InpMsh->typ & Asc)
1020                                         safe_fscanf(InpMsh->hdl, "%lf", &d, InpMsh->err);
1021                                 else
1022                                         ScaDblWrd(InpMsh, (unsigned char *)&d);
1023 
1024                                 f = (float)d;
1025                         }
1026 
1027                         if(OutMsh->ver == 1)
1028                                 if(OutMsh->typ & Asc)
1029                                         fprintf(OutMsh->hdl, "%g ", (double)f);
1030                                 else
1031                                         RecWrd(OutMsh, (unsigned char *)&f);
1032                         else
1033                                 if(OutMsh->typ & Asc)
1034                                         fprintf(OutMsh->hdl, "%.15g ", d);
1035                                 else
1036                                         RecDblWrd(OutMsh, (unsigned char *)&d);
1037                 }
1038                 else if(kwd->fmt[i] == 'i')
1039                 {
1040                         if(InpMsh->ver <= 3)
1041                         {
1042                                 if(InpMsh->typ & Asc)
1043                                         safe_fscanf(InpMsh->hdl, "%d", &a, InpMsh->err);
1044                                 else
1045                                         ScaWrd(InpMsh, (unsigned char *)&a);
1046 
1047                                 l = (int64_t)a;
1048                         }
1049                         else
1050                         {
1051                                 if(InpMsh->typ & Asc)
1052                                         safe_fscanf(InpMsh->hdl, INT64_T_FMT, &l, InpMsh->err);
1053                                 else
1054                                         ScaDblWrd(InpMsh, (unsigned char *)&l);
1055 
1056                                 a = (int)l;
1057                         }
1058 
1059                         if( (i == kwd->SolSiz-1) && (a > GmfMaxRefTab[ KwdCod ]) )
1060                                 GmfMaxRefTab[ KwdCod ] = a;
1061 
1062                         if(OutMsh->ver <= 3)
1063                         {
1064                                 if(OutMsh->typ & Asc)
1065                                         fprintf(OutMsh->hdl, "%d ", a);
1066                                 else
1067                                         RecWrd(OutMsh, (unsigned char *)&a);
1068                         }
1069                         else
1070                         {
1071                                 if(OutMsh->typ & Asc)
1072                                         fprintf(OutMsh->hdl, INT64_T_FMT" ", l);
1073                                 else
1074                                         RecDblWrd(OutMsh, (unsigned char *)&l);
1075                         }
1076                 }
1077                 else if(kwd->fmt[i] == 'c')
1078                 {
1079                         memset(s, 0, FilStrSiz * WrdSiz);
1080 
1081                         if(InpMsh->typ & Asc)
1082                                 safe_fgets(s, WrdSiz * FilStrSiz, InpMsh->hdl, InpMsh->err);
1083                         else
1084                                 read(InpMsh->FilDes, s, WrdSiz * FilStrSiz);
1085 
1086                         if(OutMsh->typ & Asc)
1087                                 fprintf(OutMsh->hdl, "%s ", s);
1088                         else
1089                                 write(OutMsh->FilDes, s, WrdSiz * FilStrSiz);
1090                 }
1091         }
1092 
1093         if(OutMsh->typ & Asc)
1094                 fprintf(OutMsh->hdl, "\n");
1095 
1096         return(1);
1097 }
1098 
1099 #endif
1100 
1101 /* [Bruno] Made asynchronous I/O optional */
1102 #ifdef WITH_AIO
1103 
1104 /*----------------------------------------------------------*/
1105 /* Bufferized asynchronous reading of all keyword's lines   */
1106 /*----------------------------------------------------------*/
1107 
NAMF77(GmfGetBlock,gmfgetblock)1108 extern int NAMF77(GmfGetBlock, gmfgetblock)(TYPF77(int64_t) MshIdx, TYPF77(int) KwdCod, void *prc, ...)
1109 {
1110     char *UsrDat[ GmfMaxTyp ], *FilBuf=NULL, *FrtBuf=NULL, *BckBuf=NULL, *FilPos, **SolTab1, **SolTab2;
1111     /* [Bruno] "%lld" -> INT64_T_FMT */
1112     char *StrTab[5] = { "", "%f", "%lf", "%d", INT64_T_FMT };
1113     int b, i, j, LinSiz, *FilPtrI32, *UsrPtrI32, FilTyp[ GmfMaxTyp ], UsrTyp[ GmfMaxTyp ];
1114     int NmbBlk, NmbArg, SizTab[5] = {0,4,8,4,8}, err, ret, typ, SolTabTyp = 0;
1115     int64_t NmbLin, *FilPtrI64, *UsrPtrI64, BegIdx, EndIdx=0;
1116     float *FilPtrR32, *UsrPtrR32;
1117     double *FilPtrR64, *UsrPtrR64;
1118     void (*UsrPrc)(int64_t, int64_t, void *) = NULL, *UsrArg, *ArgTab[ MaxArg ];
1119     size_t UsrLen[ GmfMaxTyp ], SolTypSiz;
1120     va_list VarArg;
1121     GmfMshSct *msh = (GmfMshSct *) VALF77(MshIdx);
1122     KwdSct *kwd = &msh->KwdTab[ VALF77(KwdCod) ];
1123     struct aiocb aio;
1124 
1125     /* Save the current stack environment for longjmp */
1126     if(setjmp(msh->err) != 0)
1127     {
1128         if(BckBuf)
1129             free(BckBuf);
1130 
1131         if(FrtBuf)
1132             free(FrtBuf);
1133 
1134         return(0);
1135     }
1136 
1137     /* Check mesh and keyword */
1138     if( (VALF77(KwdCod) < 1) || (VALF77(KwdCod) > GmfMaxKwd) || !kwd->NmbLin )
1139         return(0);
1140 
1141     /* Make sure it's not a simple information keyword */
1142     if( (kwd->typ != RegKwd) && (kwd->typ != SolKwd) )
1143         return(0);
1144 
1145     /* Start decoding the arguments */
1146     va_start(VarArg, prc);
1147     LinSiz = 0;
1148 
1149     /* Get the user's preporcessing procedure and argument adresses, if any */
1150 #ifdef F77API
1151     if(PRCF77(prc))
1152     {
1153         UsrPrc = (void (*)(int64_t, int64_t, void *))prc;
1154         NmbArg = *(va_arg(VarArg, int *));
1155 
1156         for(i=0;i<NmbArg;i++)
1157             ArgTab[i] = va_arg(VarArg, void *);
1158     }
1159 #else
1160     if(prc)
1161     {
1162         UsrPrc = (void (*)(int64_t, int64_t, void *))prc;
1163         UsrArg = va_arg(VarArg, void *);
1164     }
1165 #endif
1166     for(i=0;i<kwd->SolSiz;i++)
1167     {
1168         /* Get the user's data type and pointers to first and second adress to compute the stride */
1169 
1170         if(!SolTabTyp)
1171         {
1172             typ = VALF77(va_arg(VarArg, TYPF77(int)));
1173 
1174             if( (typ == GmfFloatTable) || (typ == GmfDoubleTable) )
1175             {
1176                 if(typ == GmfFloatTable)
1177                 {
1178                     SolTabTyp = GmfFloat;
1179                     SolTypSiz = sizeof(float);
1180                 }
1181                 else
1182                 {
1183                     SolTabTyp = GmfDouble;
1184                     SolTypSiz = sizeof(double);
1185                 }
1186 
1187                 SolTab1 = va_arg(VarArg, char **);
1188                 SolTab2 = va_arg(VarArg, char **);
1189             }
1190         }
1191 
1192         if(SolTabTyp)
1193         {
1194             UsrTyp[i] = SolTabTyp;
1195             UsrDat[i] = *(SolTab1 + i);
1196             UsrLen[i] = (size_t)(SolTab2[i] - SolTab1[i]);
1197         }
1198         else
1199         {
1200             UsrTyp[i] = typ;
1201             UsrDat[i] = va_arg(VarArg, char *);
1202             UsrLen[i] = (size_t)(va_arg(VarArg, char *) - UsrDat[i]);
1203         }
1204 
1205         /* Get the file's data type */
1206         if(kwd->fmt[i] == 'r')
1207             if(msh->ver <= 1)
1208                 FilTyp[i] = GmfFloat;
1209             else
1210                 FilTyp[i] = GmfDouble;
1211         else
1212             if(msh->ver <= 3)
1213                 FilTyp[i] = GmfInt;
1214             else
1215                 FilTyp[i] = GmfLong;
1216 
1217         /* Compute the file stride */
1218         LinSiz += SizTab[ FilTyp[i] ];
1219     }
1220 
1221     va_end(VarArg);
1222 
1223     /* Move file pointer to the keyword data */
1224     SetFilPos(msh, kwd->pos);
1225 
1226     /* Read the whole kwd data */
1227 
1228     if(msh->typ & Asc)
1229     {
1230         for(i=0;i<kwd->NmbLin;i++)
1231             for(j=0;j<kwd->SolSiz;j++)
1232             {
1233                 safe_fscanf(msh->hdl, StrTab[ UsrTyp[j] ], UsrDat[j], msh->err);
1234                 UsrDat[j] += UsrLen[j];
1235             }
1236 
1237         /* Call the user's preprocessing procedure */
1238         if(UsrPrc)
1239 #ifdef F77API
1240             CalF77Prc(1, kwd->NmbLin, UsrPrc, NmbArg, ArgTab);
1241 #else
1242             UsrPrc(1, kwd->NmbLin, UsrArg);
1243 #endif
1244     }
1245     else
1246     {
1247         /* Allocate both front and back buffers */
1248         if(!(BckBuf = malloc((size_t)BufSiz * (size_t)LinSiz)))
1249             return(0);
1250 
1251         if(!(FrtBuf = malloc((size_t)BufSiz * (size_t)LinSiz)))
1252             return(0);
1253 
1254         /* Setup the ansynchonous parameters */
1255         memset(&aio, 0, sizeof(struct aiocb));
1256         FilBuf = BckBuf;
1257         aio.aio_buf = BckBuf;
1258         aio.aio_fildes = msh->FilDes;
1259         aio.aio_offset = GetFilPos(msh);
1260 
1261         NmbBlk = kwd->NmbLin / BufSiz;
1262 
1263         /* Loop over N+1 blocks */
1264         for(b=0;b<=NmbBlk+1;b++)
1265         {
1266             /* Wait for the previous block read to complete except for the first loop interation */
1267             if(b)
1268             {
1269                 while(aio_error(&aio) == EINPROGRESS);
1270 
1271                 err = aio_error(&aio);
1272                 ret = aio_return(&aio);
1273 
1274                 if (err != 0) {
1275                   printf (" Error at aio_error() : %s\n", strerror (err));
1276                   exit(1);
1277                 }
1278 
1279                 if (ret != aio.aio_nbytes) {
1280                   printf(" Error at aio_return()\n");
1281                   exit(1);
1282                 }
1283 
1284                 /* Increment the reading position */
1285                 aio.aio_offset += aio.aio_nbytes;
1286 
1287                 /* and swap the buffers */
1288                 if(aio.aio_buf == BckBuf)
1289                 {
1290                     aio.aio_buf = FrtBuf;
1291                     FilBuf = BckBuf;
1292                 }
1293                 else
1294                 {
1295                     aio.aio_buf = BckBuf;
1296                     FilBuf = FrtBuf;
1297                 }
1298             }
1299 
1300             /* Read a chunk of data except for the last loop interarion */
1301             if(b <= NmbBlk)
1302             {
1303                 /* The last block is shorter than the others */
1304                 if(b == NmbBlk)
1305                     NmbLin = kwd->NmbLin - b * BufSiz;
1306                 else
1307                     NmbLin = BufSiz;
1308 
1309                 aio.aio_nbytes = NmbLin * LinSiz;
1310 
1311                 if(aio_read(&aio) == -1)
1312                 {
1313                     printf("aio_fildes = %d\n",aio.aio_fildes);
1314                     printf("aio_buf = %p\n",aio.aio_buf);
1315                     printf("aio_offset = %lld\n",aio.aio_offset);
1316                     printf("aio_nbytes = %ld\n",aio.aio_nbytes);
1317                     printf("errno = %d\n",errno);
1318                     exit(1);
1319                 }
1320             }
1321 
1322             /* Then decode the block and store it in the user's data structure
1323              except for the first loop interation */
1324             if(b)
1325             {
1326                 /* The last block is shorter than the others */
1327                 if(b-1 == NmbBlk)
1328                     NmbLin = kwd->NmbLin - (b-1) * BufSiz;
1329                 else
1330                     NmbLin = BufSiz;
1331 
1332                 BegIdx = EndIdx+1;
1333                 EndIdx += NmbLin;
1334                 FilPos = FilBuf;
1335 
1336                 for(i=0;i<NmbLin;i++)
1337                 {
1338                     for(j=0;j<kwd->SolSiz;j++)
1339                     {
1340                         if(msh->cod != 1)
1341                             SwpWrd(FilPos, SizTab[ FilTyp[j] ]);
1342 
1343                         if(FilTyp[j] == GmfInt)
1344                         {
1345                             FilPtrI32 = (int *)FilPos;
1346 
1347                             if(UsrTyp[j] == GmfInt)
1348                             {
1349                                 UsrPtrI32 = (int *)UsrDat[j];
1350                                 *UsrPtrI32 = *FilPtrI32;
1351                             }
1352                             else
1353                             {
1354                                 UsrPtrI64 = (int64_t *)UsrDat[j];
1355                                 *UsrPtrI64 = (int64_t)*FilPtrI32;
1356                             }
1357                         }
1358                         else if(FilTyp[j] == GmfLong)
1359                         {
1360                             FilPtrI64 = (int64_t *)FilPos;
1361 
1362                             if(UsrTyp[j] == GmfLong)
1363                             {
1364                                 UsrPtrI64 = (int64_t *)UsrDat[j];
1365                                 *UsrPtrI64 = *FilPtrI64;
1366                             }
1367                             else
1368                             {
1369                                 UsrPtrI32 = (int *)UsrDat[j];
1370                                 *UsrPtrI32 = (int)*FilPtrI64;
1371                             }
1372                         }
1373                         else if(FilTyp[j] == GmfFloat)
1374                         {
1375                             FilPtrR32 = (float *)FilPos;
1376 
1377                             if(UsrTyp[j] == GmfFloat)
1378                             {
1379                                 UsrPtrR32 = (float *)UsrDat[j];
1380                                 *UsrPtrR32 = *FilPtrR32;
1381                             }
1382                             else
1383                             {
1384                                 UsrPtrR64 = (double *)UsrDat[j];
1385                                 *UsrPtrR64 = (double)*FilPtrR32;
1386                             }
1387                         }
1388                         else if(FilTyp[j] == GmfDouble)
1389                         {
1390                             FilPtrR64 = (double *)FilPos;
1391 
1392                             if(UsrTyp[j] == GmfDouble)
1393                             {
1394                                 UsrPtrR64 = (double *)UsrDat[j];
1395                                 *UsrPtrR64 = *FilPtrR64;
1396                             }
1397                             else
1398                             {
1399                                 UsrPtrR32 = (float *)UsrDat[j];
1400                                 *UsrPtrR32 = (float)*FilPtrR64;
1401                             }
1402                         }
1403 
1404                         FilPos += SizTab[ FilTyp[j] ];
1405                         UsrDat[j] += UsrLen[j];
1406                     }
1407                 }
1408 
1409                 /* Call the user's preprocessing procedure */
1410                 if(UsrPrc)
1411 #ifdef F77API
1412                     CalF77Prc(BegIdx, EndIdx, UsrPrc, NmbArg, ArgTab);
1413 #else
1414                     UsrPrc(BegIdx, EndIdx, UsrArg);
1415 #endif
1416             }
1417         }
1418 
1419         free(BckBuf);
1420         free(FrtBuf);
1421     }
1422 
1423     return(1);
1424 }
1425 
1426 
1427 /*----------------------------------------------------------*/
1428 /* Bufferized writing of all keyword's lines                */
1429 /*----------------------------------------------------------*/
1430 
NAMF77(GmfSetBlock,gmfsetblock)1431 extern int NAMF77(GmfSetBlock, gmfsetblock)(TYPF77(int64_t) MshIdx, TYPF77(int) KwdCod, void *prc, ...)
1432 {
1433     char *UsrDat[ GmfMaxTyp ], *FilBuf=NULL, *FrtBuf=NULL, *BckBuf=NULL, *FilPos;
1434     char *StrTab[5] = { "", "%g", "%.15g", "%d", "%lld" };
1435     int i, j, LinSiz, *FilPtrI32, *UsrPtrI32, FilTyp[ GmfMaxTyp ], UsrTyp[ GmfMaxTyp ];
1436     int NmbBlk, NmbArg, NmbLin, b, SizTab[5] = {0,4,8,4,8}, err, ret;
1437     int64_t *FilPtrI64, *UsrPtrI64, BegIdx, EndIdx=0;
1438     float *FilPtrR32, *UsrPtrR32;
1439     double *FilPtrR64, *UsrPtrR64;
1440     void (*UsrPrc)(int64_t, int64_t, void *) = NULL, *UsrArg, *ArgTab[ MaxArg ];
1441     size_t UsrLen[ GmfMaxTyp ];
1442     va_list VarArg;
1443     GmfMshSct *msh = (GmfMshSct *) VALF77(MshIdx);
1444     KwdSct *kwd = &msh->KwdTab[ VALF77(KwdCod) ];
1445     struct aiocb aio;
1446 
1447     /* Save the current stack environment for longjmp */
1448     if(setjmp(msh->err) != 0)
1449     {
1450         if(FilBuf)
1451             free(FilBuf);
1452 
1453         return(0);
1454     }
1455 
1456     /* Check mesh and keyword */
1457     if( (VALF77(KwdCod) < 1) || (VALF77(KwdCod) > GmfMaxKwd) || !kwd->NmbLin )
1458         return(0);
1459 
1460     /* Make sure it's not a simple information keyword */
1461     if( (kwd->typ != RegKwd) && (kwd->typ != SolKwd) )
1462         return(0);
1463 
1464     /* Start decoding the arguments */
1465     va_start(VarArg, prc);
1466     LinSiz = 0;
1467 
1468     /* Get the user's postprocessing procedure and argument adresses, if any */
1469 #ifdef F77API
1470     if(PRCF77(prc))
1471     {
1472         UsrPrc = (void (*)(int64_t, int64_t, void *))prc;
1473         NmbArg = *(va_arg(VarArg, int *));
1474 
1475         for(i=0;i<NmbArg;i++)
1476             ArgTab[i] = va_arg(VarArg, void *);
1477     }
1478 #else
1479     if(prc)
1480     {
1481         UsrPrc = (void (*)(int64_t, int64_t, void *))prc;
1482         UsrArg = va_arg(VarArg, void *);
1483     }
1484 #endif
1485     for(i=0;i<kwd->SolSiz;i++)
1486     {
1487         /* Get the user's data type and pointers to first and second adress to compute the stride */
1488         UsrTyp[i] = VALF77(va_arg(VarArg, TYPF77(int)));
1489         UsrDat[i] = va_arg(VarArg, char *);
1490         UsrLen[i] = (size_t)(va_arg(VarArg, char *) - UsrDat[i]);
1491 
1492         /* Get the file's data type */
1493         if(kwd->fmt[i] == 'r')
1494             if(msh->ver <= 1)
1495                 FilTyp[i] = GmfFloat;
1496             else
1497                 FilTyp[i] = GmfDouble;
1498         else
1499             if(msh->ver <= 3)
1500                 FilTyp[i] = GmfInt;
1501             else
1502                 FilTyp[i] = GmfLong;
1503 
1504         /* Compute the file stride */
1505         LinSiz += SizTab[ FilTyp[i] ];
1506     }
1507 
1508     va_end(VarArg);
1509 
1510     /* Write the whole kwd data */
1511     if(msh->typ & Asc)
1512     {
1513         if(UsrPrc)
1514 #ifdef F77API
1515             CalF77Prc(1, kwd->NmbLin, UsrPrc, NmbArg, ArgTab);
1516 #else
1517             UsrPrc(1, kwd->NmbLin, UsrArg);
1518 #endif
1519 
1520         for(i=0;i<kwd->NmbLin;i++)
1521             for(j=0;j<kwd->SolSiz;j++)
1522             {
1523                 if(UsrTyp[j] == GmfFloat)
1524                 {
1525                     UsrPtrR32 = (float *)UsrDat[j];
1526                     fprintf(msh->hdl, StrTab[ UsrTyp[j] ], (double)*UsrPtrR32);
1527                 }
1528                 else if(UsrTyp[j] == GmfDouble)
1529                 {
1530                     UsrPtrR64 = (double *)UsrDat[j];
1531                     fprintf(msh->hdl, StrTab[ UsrTyp[j] ], *UsrPtrR64);
1532                 }
1533                 else if(UsrTyp[j] == GmfInt)
1534                 {
1535                     UsrPtrI32 = (int *)UsrDat[j];
1536                     fprintf(msh->hdl, StrTab[ UsrTyp[j] ], *UsrPtrI32);
1537                 }
1538                 else if(UsrTyp[j] == GmfLong)
1539                 {
1540                     UsrPtrI64 = (int64_t *)UsrDat[j];
1541                     fprintf(msh->hdl, StrTab[ UsrTyp[j] ], *UsrPtrI64);
1542                 }
1543 
1544                 if(j < kwd->SolSiz -1)
1545                     fprintf(msh->hdl, " ");
1546                 else
1547                     fprintf(msh->hdl, "\n");
1548 
1549                 UsrDat[j] += UsrLen[j];
1550             }
1551     }
1552     else
1553     {
1554         /* Allocate the front and back buffers */
1555         if(!(BckBuf = malloc((size_t)BufSiz * (size_t)LinSiz)))
1556             return(0);
1557 
1558         if(!(FrtBuf = malloc((size_t)BufSiz * (size_t)LinSiz)))
1559             return(0);
1560 
1561         /* Setup the asynchronous parameters */
1562         memset(&aio, 0, sizeof(struct aiocb));
1563         FilBuf = BckBuf;
1564         aio.aio_fildes = msh->FilDes;
1565         aio.aio_offset = GetFilPos(msh);
1566 
1567         NmbBlk = kwd->NmbLin / BufSiz;
1568 
1569         /* Loop over N+1 blocks */
1570         for(b=0;b<=NmbBlk+1;b++)
1571         {
1572             /* Launch an asynchronous block write except at the first loop iteration */
1573             if(b)
1574             {
1575                 aio.aio_nbytes = NmbLin * LinSiz;
1576 
1577                 if(aio_write(&aio) == -1)
1578                 {
1579                     printf("aio_fildes = %d\n",aio.aio_fildes);
1580                     printf("aio_buf = %p\n",aio.aio_buf);
1581                     printf("aio_offset = %lld\n",aio.aio_offset);
1582                     printf("aio_nbytes = %ld\n",aio.aio_nbytes);
1583                     printf("errno = %d\n",errno);
1584                     exit(1);
1585                 }
1586             }
1587 
1588             /* Parse the block data except at the last loop iteration */
1589             if(b<=NmbBlk)
1590             {
1591                 /* The last block is shorter */
1592                 if(b == NmbBlk)
1593                     NmbLin = kwd->NmbLin - b * BufSiz;
1594                 else
1595                     NmbLin = BufSiz;
1596 
1597                 FilPos = FilBuf;
1598                 BegIdx = EndIdx+1;
1599                 EndIdx += NmbLin;
1600 
1601                 /* Call user's preprocessing first */
1602                 if(UsrPrc)
1603 #ifdef F77API
1604                     CalF77Prc(BegIdx, EndIdx, UsrPrc, NmbArg, ArgTab);
1605 #else
1606                     UsrPrc(BegIdx, EndIdx, UsrArg);
1607 #endif
1608 
1609                 /* Then copy it's data to the file buffer */
1610                 for(i=0;i<NmbLin;i++)
1611                 {
1612                     for(j=0;j<kwd->SolSiz;j++)
1613                     {
1614                         if(FilTyp[j] == GmfInt)
1615                         {
1616                             FilPtrI32 = (int *)FilPos;
1617 
1618                             if(UsrTyp[j] == GmfInt)
1619                             {
1620                                 UsrPtrI32 = (int *)UsrDat[j];
1621                                 *FilPtrI32 = *UsrPtrI32;
1622                             }
1623                             else
1624                             {
1625                                 UsrPtrI64 = (int64_t *)UsrDat[j];
1626                                 *FilPtrI32 = (int)*UsrPtrI64;
1627                             }
1628                         }
1629                         else if(FilTyp[j] == GmfLong)
1630                         {
1631                             FilPtrI64 = (int64_t *)FilPos;
1632 
1633                             if(UsrTyp[j] == GmfLong)
1634                             {
1635                                 UsrPtrI64 = (int64_t *)UsrDat[j];
1636                                 *FilPtrI64 = *UsrPtrI64;
1637                             }
1638                             else
1639                             {
1640                                 UsrPtrI32 = (int *)UsrDat[j];
1641                                 *FilPtrI64 = (int64_t)*UsrPtrI32;
1642                             }
1643                         }
1644                         else if(FilTyp[j] == GmfFloat)
1645                         {
1646                             FilPtrR32 = (float *)FilPos;
1647 
1648                             if(UsrTyp[j] == GmfFloat)
1649                             {
1650                                 UsrPtrR32 = (float *)UsrDat[j];
1651                                 *FilPtrR32 = *UsrPtrR32;
1652                             }
1653                             else
1654                             {
1655                                 UsrPtrR64 = (double *)UsrDat[j];
1656                                 *FilPtrR32 = (float)*UsrPtrR64;
1657                             }
1658                         }
1659                         else if(FilTyp[j] == GmfDouble)
1660                         {
1661                             FilPtrR64 = (double *)FilPos;
1662 
1663                             if(UsrTyp[j] == GmfDouble)
1664                             {
1665                                 UsrPtrR64 = (double *)UsrDat[j];
1666                                 *FilPtrR64 = *UsrPtrR64;
1667                             }
1668                             else
1669                             {
1670                                 UsrPtrR32 = (float *)UsrDat[j];
1671                                 *FilPtrR64 = (double)*UsrPtrR32;
1672                             }
1673                         }
1674 
1675                         FilPos += SizTab[ FilTyp[j] ];
1676                         UsrDat[j] += UsrLen[j];
1677                     }
1678                 }
1679             }
1680 
1681             /* Wait for write completion execpt at the first loop iteration */
1682             if(b)
1683             {
1684                 while(aio_error(&aio) == EINPROGRESS);
1685 
1686                 err = aio_error(&aio);
1687                 ret = aio_return(&aio);
1688 
1689                 if (err != 0) {
1690                   printf (" Error at aio_error() : %s\n", strerror (err));
1691                   exit(1);
1692                 }
1693 
1694                 if (ret != aio.aio_nbytes) {
1695                   printf(" Error at aio_return()\n");
1696                   exit(1);
1697                 }
1698 
1699                 /* Move the write position */
1700                 aio.aio_offset += aio.aio_nbytes;
1701             }
1702 
1703             /* Swap the buffers */
1704             if(FilBuf == BckBuf)
1705             {
1706                 aio.aio_buf = BckBuf;
1707                 FilBuf = FrtBuf;
1708             }
1709             else
1710             {
1711                 aio.aio_buf = FrtBuf;
1712                 FilBuf = BckBuf;
1713             }
1714         }
1715 
1716         SetFilPos(msh, aio.aio_offset);
1717         free(BckBuf);
1718         free(FrtBuf);
1719     }
1720 
1721     return(1);
1722 }
1723 
1724 #endif
1725 
1726 /*----------------------------------------------------------*/
1727 /* Find every kw present in a meshfile                      */
1728 /*----------------------------------------------------------*/
1729 
ScaKwdTab(GmfMshSct * msh)1730 static int ScaKwdTab(GmfMshSct *msh)
1731 {
1732     int KwdCod, c;
1733     int64_t  NexPos, EndPos;
1734     char str[ GmfStrSiz ];
1735 
1736     if(msh->typ & Asc)
1737     {
1738         /* Scan each string in the file until the end */
1739 
1740         while(fscanf(msh->hdl, "%s", str) != EOF)
1741         {
1742             /* Fast test in order to reject quickly the numeric values */
1743 
1744             if(isalpha(str[0]))
1745             {
1746                 /* Search which kwd code this string is associated with,
1747                     then get its header and save the curent position in file (just before the data) */
1748 
1749                 for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++)
1750                     if(!strcmp(str, GmfKwdFmt[ KwdCod ][0]))
1751                     {
1752                         ScaKwdHdr(msh, KwdCod);
1753                         break;
1754                     }
1755             }
1756             else if(str[0] == '#')
1757                 while((c = fgetc(msh->hdl)) != '\n' && c != EOF);
1758         }
1759     }
1760     else
1761     {
1762         /* Get file size */
1763 
1764         EndPos = GetFilSiz(msh);
1765 
1766         /* Jump through kwd positions in the file */
1767 
1768         do
1769         {
1770             /* Get the kwd code and the next kwd position */
1771 
1772             ScaWrd(msh, ( char *)&KwdCod);
1773             NexPos = GetPos(msh);
1774 
1775             if(NexPos > EndPos)
1776                 longjmp(msh->err, -1);
1777 
1778             /* Check if this kwd belongs to this mesh version */
1779 
1780             if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) )
1781                 ScaKwdHdr(msh, KwdCod);
1782 
1783             /* Go to the next kwd */
1784 
1785             if(NexPos && !(SetFilPos(msh, NexPos)))
1786                 longjmp(msh->err, -1);
1787         }while(NexPos && (KwdCod != GmfEnd));
1788     }
1789 
1790     return(1);
1791 }
1792 
1793 
1794 /*----------------------------------------------------------*/
1795 /* Read and setup the keyword's header                      */
1796 /*----------------------------------------------------------*/
1797 
ScaKwdHdr(GmfMshSct * msh,int KwdCod)1798 static void ScaKwdHdr(GmfMshSct *msh, int KwdCod)
1799 {
1800     int i;
1801     KwdSct *kwd = &msh->KwdTab[ KwdCod ];
1802 
1803     if(!strcmp("i", GmfKwdFmt[ KwdCod ][2]))
1804         if(msh->typ & Asc)
1805             safe_fscanf(msh->hdl, INT64_T_FMT, &kwd->NmbLin, msh->err);
1806         else
1807             if(msh->ver <= 3)
1808             {
1809                 ScaWrd(msh, (unsigned char *)&i);
1810                 kwd->NmbLin = i;
1811             }
1812             else
1813                 ScaDblWrd(msh, (unsigned char *)&kwd->NmbLin);
1814     else
1815         kwd->NmbLin = 1;
1816 
1817     if(!strcmp("sr", GmfKwdFmt[ KwdCod ][3]))
1818     {
1819         if(msh->typ & Asc)
1820         {
1821             safe_fscanf(msh->hdl, "%d", &kwd->NmbTyp, msh->err);
1822 
1823             for(i=0;i<kwd->NmbTyp;i++)
1824                 safe_fscanf(msh->hdl, "%d", &kwd->TypTab[i], msh->err);
1825         }
1826         else
1827         {
1828             ScaWrd(msh, (unsigned char *)&kwd->NmbTyp);
1829 
1830             for(i=0;i<kwd->NmbTyp;i++)
1831                 ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]);
1832         }
1833     }
1834 
1835     ExpFmt(msh, KwdCod);
1836     kwd->pos = GetFilPos(msh);
1837 }
1838 
1839 
1840 /*----------------------------------------------------------*/
1841 /* Expand the compacted format and compute the line size    */
1842 /*----------------------------------------------------------*/
1843 
ExpFmt(GmfMshSct * msh,int KwdCod)1844 static void ExpFmt(GmfMshSct *msh, int KwdCod)
1845 {
1846     int i, j, TmpSiz=0, IntWrd, FltWrd;
1847     char chr;
1848     const char *InpFmt = GmfKwdFmt[ KwdCod ][3];
1849     KwdSct *kwd = &msh->KwdTab[ KwdCod ];
1850 
1851     /* Set the kwd's type */
1852 
1853     if(!strlen(GmfKwdFmt[ KwdCod ][2]))
1854         kwd->typ = InfKwd;
1855     else if(!strcmp(InpFmt, "sr"))
1856         kwd->typ = SolKwd;
1857     else
1858         kwd->typ = RegKwd;
1859 
1860     /* Get the solution-field's size */
1861 
1862     if(kwd->typ == SolKwd)
1863         for(i=0;i<kwd->NmbTyp;i++)
1864             switch(kwd->TypTab[i])
1865             {
1866                 case GmfSca    : TmpSiz += 1; break;
1867                 case GmfVec    : TmpSiz += msh->dim; break;
1868                 case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break;
1869                 case GmfMat    : TmpSiz += msh->dim * msh->dim; break;
1870             }
1871 
1872     /* Scan each character from the format string */
1873 
1874     i = kwd->SolSiz = kwd->NmbWrd = 0;
1875 
1876     while(i < (int)strlen(InpFmt))
1877     {
1878         chr = InpFmt[ i++ ];
1879 
1880         if(chr == 'd')
1881         {
1882             chr = InpFmt[i++];
1883 
1884             for(j=0;j<msh->dim;j++)
1885                 kwd->fmt[ kwd->SolSiz++ ] = chr;
1886         }
1887         else if(chr == 's')
1888         {
1889             chr = InpFmt[i++];
1890 
1891             for(j=0;j<TmpSiz;j++)
1892                 kwd->fmt[ kwd->SolSiz++ ] = chr;
1893         }
1894         else
1895             kwd->fmt[ kwd->SolSiz++ ] = chr;
1896     }
1897 
1898     if(msh->ver <= 1)
1899         FltWrd = 1;
1900     else
1901         FltWrd = 2;
1902 
1903     if(msh->ver <= 3)
1904         IntWrd = 1;
1905     else
1906         IntWrd = 2;
1907 
1908     for(i=0;i<kwd->SolSiz;i++)
1909         switch(kwd->fmt[i])
1910         {
1911             case 'i' : kwd->NmbWrd += IntWrd; break;
1912             case 'c' : kwd->NmbWrd += FilStrSiz; break;
1913             case 'r' : kwd->NmbWrd += FltWrd;break;
1914         }
1915 }
1916 
1917 
1918 /*----------------------------------------------------------*/
1919 /* Read a four bytes word from a mesh file                  */
1920 /*----------------------------------------------------------*/
1921 
ScaWrd(GmfMshSct * msh,void * ptr)1922 static void ScaWrd(GmfMshSct *msh, void *ptr)
1923 {
1924     if(read(msh->FilDes, ptr, WrdSiz) != WrdSiz)
1925         longjmp(msh->err, -1);
1926 
1927     if(msh->cod != 1)
1928         SwpWrd((char *)ptr, WrdSiz);
1929 }
1930 
1931 
1932 /*----------------------------------------------------------*/
1933 /* Read an eight bytes word from a mesh file                */
1934 /*----------------------------------------------------------*/
1935 
ScaDblWrd(GmfMshSct * msh,void * ptr)1936 static void ScaDblWrd(GmfMshSct *msh, void *ptr)
1937 {
1938     if(read(msh->FilDes, ptr, WrdSiz * 2) != WrdSiz * 2)
1939         longjmp(msh->err, -1);
1940 
1941     if(msh->cod != 1)
1942         SwpWrd((char *)ptr, 2 * WrdSiz);
1943 }
1944 
1945 
1946 /*----------------------------------------------------------*/
1947 /* Read a 4 or 8 bytes position in mesh file                */
1948 /*----------------------------------------------------------*/
1949 
GetPos(GmfMshSct * msh)1950 static int64_t GetPos(GmfMshSct *msh)
1951 {
1952     int IntVal;
1953     int64_t pos;
1954 
1955     if(msh->ver >= 3)
1956         ScaDblWrd(msh, (unsigned char*)&pos);
1957     else
1958     {
1959         ScaWrd(msh, (unsigned char*)&IntVal);
1960         pos = (int64_t)IntVal;
1961     }
1962 
1963     return(pos);
1964 }
1965 
1966 
1967 /*----------------------------------------------------------*/
1968 /* Write a four bytes word to a mesh file                   */
1969 /*----------------------------------------------------------*/
1970 
RecWrd(GmfMshSct * msh,const void * wrd)1971 static void RecWrd(GmfMshSct *msh, const void *wrd)
1972 {
1973     /* [Bruno] added error control */
1974     if(write(msh->FilDes, wrd, WrdSiz) != WrdSiz) {
1975         longjmp(msh->err,-1);
1976     }
1977 }
1978 
1979 
1980 /*----------------------------------------------------------*/
1981 /* Write an eight bytes word to a mesh file                 */
1982 /*----------------------------------------------------------*/
1983 
RecDblWrd(GmfMshSct * msh,const void * wrd)1984 static void RecDblWrd(GmfMshSct *msh, const void *wrd)
1985 {
1986     /* [Bruno] added error control */
1987     if(write(msh->FilDes, wrd, WrdSiz * 2) != WrdSiz*2) {
1988         longjmp(msh->err,-1);
1989     }
1990 }
1991 
1992 
1993 /*----------------------------------------------------------*/
1994 /* Write a block of four bytes word to a mesh file          */
1995 /*----------------------------------------------------------*/
1996 
RecBlk(GmfMshSct * msh,const void * blk,int siz)1997 static void RecBlk(GmfMshSct *msh, const void *blk, int siz)
1998 {
1999     /* Copy this line-block into the main mesh buffer */
2000 
2001     if(siz)
2002     {
2003         memcpy(&msh->blk[ msh->pos ], blk, (size_t)(siz * WrdSiz));
2004         msh->pos += siz * WrdSiz;
2005     }
2006 
2007     /* When the buffer is full or this procedure is APIF77ed with a 0 size, flush the cache on disk */
2008 
2009     if( (msh->pos > BufSiz) || (!siz && msh->pos) )
2010     {
2011 #ifdef GMF_WINDOWS
2012         /*
2013          *   [Bruno] TODO: check that msh->pos is smaller
2014          * than 4G (fits in 32 bits).
2015          *   Note: for now, when trying to write more than 4Gb, it will
2016          * trigger an error (longjmp).
2017          *   As far as I understand:
2018          *   Given that this function just flushes the cache, and given that
2019          * the cache size is 10000 words, this is much much smaller than 4Gb
2020          * so there is probably no problem.
2021          */
2022         if((int64_t)write(msh->FilDes, msh->blk, (int)msh->pos) != msh->pos) {
2023             longjmp(msh->err,-1);
2024         }
2025 #else
2026         if(write(msh->FilDes, msh->blk, msh->pos) != msh->pos) {
2027             longjmp(msh->err,-1);
2028         }
2029 #endif
2030         msh->pos = 0;
2031     }
2032 }
2033 
2034 
2035 /*----------------------------------------------------------*/
2036 /* Write a 4 or 8 bytes position in a mesh file             */
2037 /*----------------------------------------------------------*/
2038 
SetPos(GmfMshSct * msh,int64_t pos)2039 static void SetPos(GmfMshSct *msh, int64_t pos)
2040 {
2041     int IntVal;
2042 
2043     if(msh->ver >= 3)
2044         RecDblWrd(msh, (unsigned char*)&pos);
2045     else
2046     {
2047         IntVal = (int)pos;
2048         RecWrd(msh, (unsigned char*)&IntVal);
2049     }
2050 }
2051 
2052 
2053 /*----------------------------------------------------------*/
2054 /* Endianness conversion                                    */
2055 /*----------------------------------------------------------*/
2056 
SwpWrd(char * wrd,int siz)2057 static void SwpWrd(char *wrd, int siz)
2058 {
2059     char swp;
2060     int i;
2061 
2062     for(i=0;i<siz/2;i++)
2063     {
2064         swp = wrd[ siz-i-1 ];
2065         wrd[ siz-i-1 ] = wrd[i];
2066         wrd[i] = swp;
2067     }
2068 }
2069 
2070 
2071 /*----------------------------------------------------------*/
2072 /* Set current position in a file                           */
2073 /*----------------------------------------------------------*/
2074 
SetFilPos(GmfMshSct * msh,int64_t pos)2075 static int SetFilPos(GmfMshSct *msh, int64_t pos)
2076 {
2077     if(msh->typ & Bin)
2078         return((lseek(msh->FilDes, (off_t)pos, 0) != -1));
2079     else
2080         return((fseek(msh->hdl, (off_t)pos, SEEK_SET) == 0));
2081 }
2082 
2083 
2084 /*----------------------------------------------------------*/
2085 /* Get current position in a file                           */
2086 /*----------------------------------------------------------*/
2087 
GetFilPos(GmfMshSct * msh)2088 static int64_t GetFilPos(GmfMshSct *msh)
2089 {
2090     if(msh->typ & Bin)
2091         return(lseek(msh->FilDes, 0, 1));
2092     else
2093         return(ftell(msh->hdl));
2094 }
2095 
2096 
2097 /*----------------------------------------------------------*/
2098 /* Move the position to the end of file and return the size */
2099 /*----------------------------------------------------------*/
2100 
GetFilSiz(GmfMshSct * msh)2101 static int64_t GetFilSiz(GmfMshSct *msh)
2102 {
2103     int64_t CurPos, EndPos = 0;
2104 
2105     if(msh->typ & Bin)
2106     {
2107         CurPos = lseek(msh->FilDes, 0, 1);
2108         EndPos = lseek(msh->FilDes, 0, 2);
2109         lseek(msh->FilDes, (off_t)CurPos, 0);
2110     }
2111     else
2112     {
2113         CurPos = ftell(msh->hdl);
2114 
2115         if(fseek(msh->hdl, 0, SEEK_END) != 0)
2116             longjmp(msh->err, -1);
2117 
2118         EndPos = ftell(msh->hdl);
2119 
2120         if(fseek(msh->hdl, (off_t)CurPos, SEEK_SET) != 0)
2121             longjmp(msh->err, -1);
2122     }
2123 
2124     return(EndPos);
2125 }
2126 
2127 
2128 /*----------------------------------------------------------*/
2129 /* Fortran 77 API                                           */
2130 /*----------------------------------------------------------*/
2131 
2132 #ifdef F77API
2133 
APIF77(gmfopenmesh)2134 int64_t APIF77(gmfopenmesh)(char *FilNam, int *mod, int *ver, int *dim, int StrSiz)
2135 {
2136     int i;
2137     char TmpNam[ GmfStrSiz ];
2138 
2139     for(i=0;i<StrSiz;i++)
2140         TmpNam[i] = FilNam[i];
2141 
2142     TmpNam[ StrSiz ] = 0;
2143 
2144     if(*mod == GmfRead)
2145         return(GmfOpenMesh(TmpNam, *mod, ver, dim));
2146     else
2147         return(GmfOpenMesh(TmpNam, *mod, *ver, *dim));
2148 }
2149 
APIF77(gmfclosemesh)2150 int APIF77(gmfclosemesh)(int64_t *idx)
2151 {
2152     return(GmfCloseMesh(*idx));
2153 }
2154 
APIF77(gmfgotokwd)2155 int APIF77(gmfgotokwd)(int64_t *MshIdx, int *KwdIdx)
2156 {
2157     return(GmfGotoKwd(*MshIdx, *KwdIdx));
2158 }
2159 
APIF77(gmfstatkwd)2160 int APIF77(gmfstatkwd)(int64_t *MshIdx, int *KwdIdx, int *NmbTyp, int *SolSiz, int *TypTab)
2161 {
2162     if(!strcmp(GmfKwdFmt[ *KwdIdx ][3], "sr"))
2163         return(GmfStatKwd(*MshIdx, *KwdIdx, NmbTyp, SolSiz, TypTab));
2164     else
2165         return(GmfStatKwd(*MshIdx, *KwdIdx));
2166 }
2167 
APIF77(gmfsetkwd)2168 int APIF77(gmfsetkwd)(int64_t *MshIdx, int *KwdIdx, int *NmbLin, int *NmbTyp, int *TypTab)
2169 {
2170     if(!strcmp(GmfKwdFmt[ *KwdIdx ][3], "sr"))
2171         return(GmfSetKwd(*MshIdx, *KwdIdx, *NmbLin, *NmbTyp, TypTab));
2172     else if(strlen(GmfKwdFmt[ *KwdIdx ][2]))
2173         return(GmfSetKwd(*MshIdx, *KwdIdx, *NmbLin));
2174     else
2175         return(GmfSetKwd(*MshIdx, *KwdIdx));
2176 }
2177 
2178 
2179 /*----------------------------------------------------------*/
2180 /* Duplication macros                                       */
2181 /*----------------------------------------------------------*/
2182 
2183 #define DUP(s,n) DUP ## n (s)
2184 #define DUP1(s) s
2185 #define DUP2(s) DUP1(s),s
2186 #define DUP3(s) DUP2(s),s
2187 #define DUP4(s) DUP3(s),s
2188 #define DUP5(s) DUP4(s),s
2189 #define DUP6(s) DUP5(s),s
2190 #define DUP7(s) DUP6(s),s
2191 #define DUP8(s) DUP7(s),s
2192 #define DUP9(s) DUP8(s),s
2193 #define DUP10(s) DUP9(s),s
2194 #define DUP11(s) DUP10(s),s
2195 #define DUP12(s) DUP11(s),s
2196 #define DUP13(s) DUP12(s),s
2197 #define DUP14(s) DUP13(s),s
2198 #define DUP15(s) DUP14(s),s
2199 #define DUP16(s) DUP15(s),s
2200 #define DUP17(s) DUP16(s),s
2201 #define DUP18(s) DUP17(s),s
2202 #define DUP19(s) DUP18(s),s
2203 #define DUP20(s) DUP19(s),s
2204 
2205 
2206 #define ARG(a,n) ARG ## n (a)
2207 #define ARG1(a) a[0]
2208 #define ARG2(a) ARG1(a),a[1]
2209 #define ARG3(a) ARG2(a),a[2]
2210 #define ARG4(a) ARG3(a),a[3]
2211 #define ARG5(a) ARG4(a),a[4]
2212 #define ARG6(a) ARG5(a),a[5]
2213 #define ARG7(a) ARG6(a),a[6]
2214 #define ARG8(a) ARG7(a),a[7]
2215 #define ARG9(a) ARG8(a),a[8]
2216 #define ARG10(a) ARG9(a),a[9]
2217 #define ARG11(a) ARG10(a),a[10]
2218 #define ARG12(a) ARG11(a),a[11]
2219 #define ARG13(a) ARG12(a),a[12]
2220 #define ARG14(a) ARG13(a),a[13]
2221 #define ARG15(a) ARG14(a),a[14]
2222 #define ARG16(a) ARG15(a),a[15]
2223 #define ARG17(a) ARG16(a),a[16]
2224 #define ARG18(a) ARG17(a),a[17]
2225 #define ARG19(a) ARG18(a),a[18]
2226 #define ARG20(a) ARG19(a),a[19]
2227 
2228 
2229 /*----------------------------------------------------------*/
2230 /* Call a fortran thread with 1 to 20 arguments             */
2231 /*----------------------------------------------------------*/
2232 
CalF77Prc(int64_t BegIdx,int64_t EndIdx,void * prc,int NmbArg,void ** ArgTab)2233 static void CalF77Prc(int64_t BegIdx, int64_t EndIdx, void *prc, int NmbArg, void **ArgTab)
2234 {
2235     switch(NmbArg)
2236     {
2237         case 1 :
2238         {
2239             void (*prc1)(int64_t *, int64_t *, DUP(void *, 1)) = \
2240                 (void (*)(int64_t *, int64_t *, DUP(void *, 1)))prc;
2241             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 1));
2242         }break;
2243 
2244         case 2 :
2245         {
2246             void (*prc1)(int64_t *, int64_t *, DUP(void *, 2)) = \
2247                 (void (*)(int64_t *, int64_t *, DUP(void *, 2)))prc;
2248             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 2));
2249         }break;
2250 
2251         case 3 :
2252         {
2253             void (*prc1)(int64_t *, int64_t *, DUP(void *, 3)) = \
2254                 (void (*)(int64_t *, int64_t *, DUP(void *, 3)))prc;
2255             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 3));
2256         }break;
2257 
2258         case 4 :
2259         {
2260             void (*prc1)(int64_t *, int64_t *, DUP(void *, 4)) = \
2261                 (void (*)(int64_t *, int64_t *, DUP(void *, 4)))prc;
2262             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 4));
2263         }break;
2264 
2265         case 5 :
2266         {
2267             void (*prc1)(int64_t *, int64_t *, DUP(void *, 5)) = \
2268                 (void (*)(int64_t *, int64_t *, DUP(void *, 5)))prc;
2269             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 5));
2270         }break;
2271 
2272         case 6 :
2273         {
2274             void (*prc1)(int64_t *, int64_t *, DUP(void *, 6)) = \
2275                 (void (*)(int64_t *, int64_t *, DUP(void *, 6)))prc;
2276             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 6));
2277         }break;
2278 
2279         case 7 :
2280         {
2281             void (*prc1)(int64_t *, int64_t *, DUP(void *, 7)) = \
2282                 (void (*)(int64_t *, int64_t *, DUP(void *, 7)))prc;
2283             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 7));
2284         }break;
2285 
2286         case 8 :
2287         {
2288             void (*prc1)(int64_t *, int64_t *, DUP(void *, 8)) = \
2289                 (void (*)(int64_t *, int64_t *, DUP(void *, 8)))prc;
2290             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 8));
2291         }break;
2292 
2293         case 9 :
2294         {
2295             void (*prc1)(int64_t *, int64_t *, DUP(void *, 9)) = \
2296                 (void (*)(int64_t *, int64_t *, DUP(void *, 9)))prc;
2297             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 9));
2298         }break;
2299 
2300         case 10 :
2301         {
2302             void (*prc1)(int64_t *, int64_t *, DUP(void *, 10)) = \
2303                 (void (*)(int64_t *, int64_t *, DUP(void *, 10)))prc;
2304             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 10));
2305         }break;
2306 
2307         case 11 :
2308         {
2309             void (*prc1)(int64_t *, int64_t *, DUP(void *, 11)) = \
2310                 (void (*)(int64_t *, int64_t *, DUP(void *, 11)))prc;
2311             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 11));
2312         }break;
2313 
2314         case 12 :
2315         {
2316             void (*prc1)(int64_t *, int64_t *, DUP(void *, 12)) = \
2317                 (void (*)(int64_t *, int64_t *, DUP(void *, 12)))prc;
2318             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 12));
2319         }break;
2320 
2321         case 13 :
2322         {
2323             void (*prc1)(int64_t *, int64_t *, DUP(void *, 13)) = \
2324                 (void (*)(int64_t *, int64_t *, DUP(void *, 13)))prc;
2325             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 13));
2326         }break;
2327 
2328         case 14 :
2329         {
2330             void (*prc1)(int64_t *, int64_t *, DUP(void *, 14)) = \
2331                 (void (*)(int64_t *, int64_t *, DUP(void *, 14)))prc;
2332             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 14));
2333         }break;
2334 
2335         case 15 :
2336         {
2337             void (*prc1)(int64_t *, int64_t *, DUP(void *, 15)) = \
2338                 (void (*)(int64_t *, int64_t *, DUP(void *, 15)))prc;
2339             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 15));
2340         }break;
2341 
2342         case 16 :
2343         {
2344             void (*prc1)(int64_t *, int64_t *, DUP(void *, 16)) = \
2345                 (void (*)(int64_t *, int64_t *, DUP(void *, 16)))prc;
2346             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 16));
2347         }break;
2348 
2349         case 17 :
2350         {
2351             void (*prc1)(int64_t *, int64_t *, DUP(void *, 17)) = \
2352                 (void (*)(int64_t *, int64_t *, DUP(void *, 17)))prc;
2353             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 17));
2354         }break;
2355 
2356         case 18 :
2357         {
2358             void (*prc1)(int64_t *, int64_t *, DUP(void *, 18)) = \
2359                 (void (*)(int64_t *, int64_t *, DUP(void *, 18)))prc;
2360             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 18));
2361         }break;
2362 
2363         case 19 :
2364         {
2365             void (*prc1)(int64_t *, int64_t *, DUP(void *, 19)) = \
2366                 (void (*)(int64_t *, int64_t *, DUP(void *, 19)))prc;
2367             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 19));
2368         }break;
2369 
2370         case 20 :
2371         {
2372             void (*prc1)(int64_t *, int64_t *, DUP(void *, 20)) = \
2373                 (void (*)(int64_t *, int64_t *, DUP(void *, 20)))prc;
2374             prc1(&BegIdx, &EndIdx, ARG(ArgTab, 20));
2375         }break;
2376     }
2377 }
2378 
2379 #endif
2380