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