1 /*****************************************************************************
2  * Copyright (c) 2019 FrontISTR Commons
3  * This software is released under the MIT License, see LICENSE.txt
4  *****************************************************************************/
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <ctype.h>
11 #include <dirent.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include "hecmw_util.h"
15 #include "hecmw_control.h"
16 #include "hecmw_ctrllex.h"
17 #include "hecmw_path.h"
18 
19 static char ctrl_filename[HECMW_FILENAME_LEN + 1];
20 
21 static int table_entire_mesh[] = {
22     HECMW_CTRL_FTYPE_HECMW_ENTIRE, HECMW_CTRL_FTYPE_GEOFEM,
23     HECMW_CTRL_FTYPE_ABAQUS,       HECMW_CTRL_FTYPE_NASTRAN,
24     HECMW_CTRL_FTYPE_FEMAP,
25 };
26 
27 struct mesh_entry {
28   char *name_ID;
29   int type;
30   int io;
31   int refine;
32   char *filename;
33   struct mesh_entry *next;
34 };
35 
36 struct mesh_grp_entry {
37   char *name_ID;
38   int n_mesh;
39   struct mesh_entry **mesh;
40   struct mesh_grp_entry *next;
41 };
42 
43 struct restart_entry {
44   char *name_ID;
45   int io;
46   /*#define HECMW_CTRL_FILE_IO_IN 1*/
47   /*#define HECMW_CTRL_FILE_IO_OUT 2*/
48   /* #define HECMW_CTRL_FILE_IO_INOUT 4 */
49   char *filename;
50   struct restart_entry *next;
51 };
52 
53 struct result_entry {
54   char *name_ID;
55   int io;
56   /*#define HECMW_CTRL_FILE_IO_IN 1*/
57   /*#define HECMW_CTRL_FILE_IO_OUT 2*/
58   int fg_text; /* 1:text(default), 0:binary */
59   char *filename;
60   struct result_entry *next;
61 };
62 
63 struct ctrl_entry {
64   char *name_ID;
65   char *filename;
66   struct ctrl_entry *next;
67 };
68 
69 static int subdir_on = 0;
70 
71 static int nlimit;
72 
73 static struct ctrl_entry *ctrl_ent;
74 
75 static struct mesh_entry *mesh_ent;
76 
77 static struct mesh_grp_entry *mesh_grp_ent;
78 
79 static struct restart_entry *restart_ent;
80 
81 static struct result_entry *result_ent;
82 
83 /*----------------------------------------------------------------------------*/
84 
is_entire_mesh(int type)85 static int is_entire_mesh(int type) {
86   int i, n;
87   n = sizeof(table_entire_mesh) / sizeof(table_entire_mesh[0]);
88 
89   for (i = 0; i < n; i++) {
90     if (table_entire_mesh[i] == type) return 1;
91   }
92 
93   return 0;
94 }
95 
96 /* return dir + subdir + prefix + file + suffix + .rank */
make_filename(char * dir,char * subdir,char * prefix,char * file,char * suffix,int myrank,int flag_rank)97 static char *make_filename(char *dir, char *subdir, char *prefix, char *file,
98                            char *suffix, int myrank, int flag_rank) {
99   static char filename[HECMW_FILENAME_LEN + 1];
100   char rank[10];
101   char separator[10];
102   strcpy(filename, "");
103 
104   if (dir && strlen(dir) > 0) {
105     sprintf(separator, "%c", HECMW_get_path_separator());
106 
107     if ((strlen(dir) + strlen(separator)) > HECMW_FILENAME_LEN) return NULL;
108 
109     sprintf(filename, "%s%s", dir, separator);
110   }
111 
112   if (subdir && strlen(subdir) > 0) {
113     sprintf(separator, "%c", HECMW_get_path_separator());
114 
115     if ((strlen(filename) + strlen(subdir) + strlen(separator)) >
116         HECMW_FILENAME_LEN)
117       return NULL;
118 
119     strcat(filename, subdir);
120     strcat(filename, separator);
121   }
122 
123   if (prefix && strlen(prefix) > 0) {
124     sprintf(separator, "%c", HECMW_get_path_separator());
125 
126     if ((strlen(filename) + strlen(prefix) + strlen(separator)) >
127         HECMW_FILENAME_LEN)
128       return NULL;
129 
130     strcat(filename, prefix);
131     strcat(filename, separator);
132   }
133 
134   if ((strlen(filename) + strlen(file)) > HECMW_FILENAME_LEN) return NULL;
135 
136   strcat(filename, file);
137 
138   if (suffix) {
139     if ((strlen(filename) + strlen(suffix)) > HECMW_FILENAME_LEN) return NULL;
140 
141     strcat(filename, suffix);
142   }
143 
144   if (flag_rank) {
145     sprintf(rank, ".%d", myrank);
146 
147     if ((strlen(filename) + strlen(rank)) > HECMW_FILENAME_LEN) return NULL;
148 
149     strcat(filename, rank);
150   }
151 
152   return filename;
153 }
154 
155 /* return dir + subdir + prefix + file + suffix + .rank (thread-safe version) */
make_filename_r(char * dir,char * subdir,char * prefix,char * file,char * suffix,int myrank,int flag_rank,char * filename,int filename_len)156 static char *make_filename_r(char *dir, char *subdir, char *prefix, char *file,
157                              char *suffix, int myrank, int flag_rank,
158                              char *filename, int filename_len) {
159   char rank[10];
160   char separator[10];
161   strcpy(filename, "");
162 
163   HECMW_assert( filename );
164 
165   if (dir && strlen(dir) > 0) {
166     sprintf(separator, "%c", HECMW_get_path_separator());
167 
168     if ((strlen(dir) + strlen(separator)) > filename_len) return NULL;
169 
170     sprintf(filename, "%s%s", dir, separator);
171   }
172 
173   if (subdir && strlen(subdir) > 0) {
174     sprintf(separator, "%c", HECMW_get_path_separator());
175 
176     if ((strlen(filename) + strlen(subdir) + strlen(separator)) >
177         filename_len)
178       return NULL;
179 
180     strcat(filename, subdir);
181     strcat(filename, separator);
182   }
183 
184   if (prefix && strlen(prefix) > 0) {
185     sprintf(separator, "%c", HECMW_get_path_separator());
186 
187     if ((strlen(filename) + strlen(prefix) + strlen(separator)) >
188         filename_len)
189       return NULL;
190 
191     strcat(filename, prefix);
192     strcat(filename, separator);
193   }
194 
195   if ((strlen(filename) + strlen(file)) > filename_len) return NULL;
196 
197   strcat(filename, file);
198 
199   if (suffix) {
200     if ((strlen(filename) + strlen(suffix)) > filename_len) return NULL;
201 
202     strcat(filename, suffix);
203   }
204 
205   if (flag_rank) {
206     sprintf(rank, ".%d", myrank);
207 
208     if ((strlen(filename) + strlen(rank)) > filename_len) return NULL;
209 
210     strcat(filename, rank);
211   }
212 
213   return filename;
214 }
215 
216 /*----------------------------------------------------------------------------*/
217 
free_mesh_entry(void)218 static void free_mesh_entry(void) {
219   struct mesh_entry *p, *q;
220 
221   for (p = mesh_ent; p; p = q) {
222     q = p->next;
223     HECMW_free(p->name_ID);
224     HECMW_free(p->filename);
225     HECMW_free(p);
226   }
227 
228   mesh_ent = NULL;
229 }
230 
free_mesh_grp_entry(void)231 static void free_mesh_grp_entry(void) {
232   struct mesh_grp_entry *p, *q;
233 
234   for (p = mesh_grp_ent; p; p = q) {
235     q = p->next;
236     HECMW_free(p->name_ID);
237     HECMW_free(p->mesh); /* free only mesh array */
238     HECMW_free(p);
239   }
240 
241   mesh_grp_ent = NULL;
242 }
243 
free_restart_entry(void)244 static void free_restart_entry(void) {
245   struct restart_entry *p, *q;
246 
247   for (p = restart_ent; p; p = q) {
248     q = p->next;
249     HECMW_free(p->name_ID);
250     HECMW_free(p->filename);
251     HECMW_free(p);
252   }
253 
254   restart_ent = NULL;
255 }
256 
free_result_entry(void)257 static void free_result_entry(void) {
258   struct result_entry *p, *q;
259 
260   for (p = result_ent; p; p = q) {
261     q = p->next;
262     HECMW_free(p->name_ID);
263     HECMW_free(p->filename);
264     HECMW_free(p);
265   }
266 
267   result_ent = NULL;
268 }
269 
free_ctrl_entry(void)270 static void free_ctrl_entry(void) {
271   struct ctrl_entry *p, *q;
272 
273   for (p = ctrl_ent; p; p = q) {
274     q = p->next;
275     HECMW_free(p->name_ID);
276     HECMW_free(p->filename);
277     HECMW_free(p);
278   }
279 
280   ctrl_ent = NULL;
281 }
282 
283 /*----------------------------------------------------------------------------*/
284 
get_mesh_entry(char * name_ID)285 static struct mesh_entry *get_mesh_entry(char *name_ID) {
286   struct mesh_entry *p;
287 
288   if (name_ID == NULL) return NULL;
289 
290   for (p = mesh_ent; p; p = p->next) {
291     if (strcmp(p->name_ID, name_ID) == 0) return p;
292   }
293 
294   return NULL;
295 }
296 
get_mesh_grp_entry(char * name_ID)297 static struct mesh_grp_entry *get_mesh_grp_entry(char *name_ID) {
298   struct mesh_grp_entry *p;
299 
300   if (name_ID == NULL) return NULL;
301 
302   for (p = mesh_grp_ent; p; p = p->next) {
303     if (strcmp(p->name_ID, name_ID) == 0) return p;
304   }
305 
306   return NULL;
307 }
308 
get_restart_entry(char * name_ID)309 static struct restart_entry *get_restart_entry(char *name_ID) {
310   struct restart_entry *p;
311 
312   if (name_ID == NULL) return NULL;
313 
314   for (p = restart_ent; p; p = p->next) {
315     if (strcmp(p->name_ID, name_ID) == 0) return p;
316   }
317 
318   return NULL;
319 }
320 
get_restart_entry_by_io(int io)321 static struct restart_entry *get_restart_entry_by_io(int io) {
322   struct restart_entry *p;
323 
324   for (p = restart_ent; p; p = p->next) {
325     if (p->io & io) return p; /* attention!! arg io is bitmap */
326   }
327 
328   return NULL;
329 }
330 
get_result_entry(char * name_ID)331 static struct result_entry *get_result_entry(char *name_ID) {
332   struct result_entry *p;
333 
334   if (name_ID == NULL) return NULL;
335 
336   for (p = result_ent; p; p = p->next) {
337     if (strcmp(p->name_ID, name_ID) == 0) return p;
338   }
339 
340   return NULL;
341 }
342 
get_ctrl_entry(char * name_ID)343 static struct ctrl_entry *get_ctrl_entry(char *name_ID) {
344   struct ctrl_entry *p;
345 
346   if (name_ID == NULL) return NULL;
347 
348   for (p = ctrl_ent; p; p = p->next) {
349     if (strcmp(p->name_ID, name_ID) == 0) return p;
350   }
351 
352   return NULL;
353 }
354 
355 /*----------------------------------------------------------------------------*/
356 
make_mesh_entry(char * name_ID,int type,int io,int refine,char * filename)357 static struct mesh_entry *make_mesh_entry(char *name_ID, int type, int io,
358                                           int refine, char *filename) {
359   char *p;
360   struct mesh_entry *mesh = NULL;
361   mesh                    = HECMW_calloc(1, sizeof(*mesh));
362 
363   if (mesh == NULL) {
364     HECMW_set_error(errno, "");
365     goto error;
366   }
367 
368   mesh->type   = type;
369   mesh->io     = io;
370   mesh->refine = refine;
371   mesh->next   = NULL;
372   p            = HECMW_strdup(name_ID);
373 
374   if (p == NULL) {
375     HECMW_set_error(errno, "");
376     goto error;
377   }
378 
379   mesh->name_ID = p;
380   p             = HECMW_strdup(filename);
381 
382   if (p == NULL) {
383     HECMW_set_error(errno, "");
384     goto error;
385   }
386 
387   mesh->filename = p;
388   return mesh;
389 error:
390 
391   if (mesh) {
392     HECMW_free(mesh->name_ID);
393     HECMW_free(mesh->filename);
394     HECMW_free(mesh);
395   }
396 
397   return NULL;
398 }
399 
add_mesh_entry(struct mesh_entry * mesh)400 static int add_mesh_entry(struct mesh_entry *mesh) {
401   struct mesh_entry *p, *q;
402   q = NULL;
403 
404   for (p = mesh_ent; p; p = (q = p)->next)
405     ;
406 
407   if (q == NULL) {
408     mesh_ent = mesh;
409 
410   } else {
411     q->next = mesh;
412   }
413 
414   return 0;
415 }
416 
make_mesh_group_entry(char * name_ID,int n_mesh,char ** mesh)417 static struct mesh_grp_entry *make_mesh_group_entry(char *name_ID, int n_mesh,
418                                                     char **mesh) {
419   int i;
420   struct mesh_grp_entry *meshgrp = NULL;
421   meshgrp                        = HECMW_calloc(1, sizeof(*meshgrp));
422 
423   if (meshgrp == NULL) {
424     HECMW_set_error(errno, "");
425     goto error;
426   }
427 
428   meshgrp->name_ID = HECMW_strdup(name_ID);
429 
430   if (meshgrp->name_ID == NULL) {
431     HECMW_set_error(errno, "");
432     goto error;
433   }
434 
435   meshgrp->n_mesh = n_mesh;
436   meshgrp->mesh   = HECMW_calloc(n_mesh, sizeof(*meshgrp->mesh));
437 
438   if (meshgrp->mesh == NULL) {
439     HECMW_set_error(errno, "");
440     goto error;
441   }
442 
443   for (i = 0; i < n_mesh; i++) {
444     meshgrp->mesh[i] = get_mesh_entry(mesh[i]);
445 
446     if (meshgrp->mesh[i] == NULL) goto error;
447   }
448 
449   meshgrp->next = NULL;
450   return meshgrp;
451 error:
452 
453   if (meshgrp) {
454     HECMW_free(meshgrp->name_ID);
455     HECMW_free(meshgrp->mesh);
456     HECMW_free(meshgrp);
457   }
458 
459   return NULL;
460 }
461 
add_mesh_group_entry(struct mesh_grp_entry * mesh)462 static int add_mesh_group_entry(struct mesh_grp_entry *mesh) {
463   struct mesh_grp_entry *p, *q;
464   q = NULL;
465 
466   for (p = mesh_grp_ent; p; p = (q = p)->next)
467     ;
468 
469   if (q == NULL) {
470     mesh_grp_ent = mesh;
471 
472   } else {
473     q->next = mesh;
474   }
475 
476   return 0;
477 }
478 
make_result_entry(char * name_ID,int io,int fg_text,char * filename)479 static struct result_entry *make_result_entry(char *name_ID, int io,
480                                               int fg_text, char *filename) {
481   char *p;
482   struct result_entry *result = NULL;
483   result                      = HECMW_calloc(1, sizeof(*result));
484 
485   if (result == NULL) {
486     HECMW_set_error(errno, "");
487     goto error;
488   }
489 
490   result->io      = io;
491   result->fg_text = fg_text;
492   result->next    = NULL;
493   p               = HECMW_strdup(name_ID);
494 
495   if (p == NULL) {
496     HECMW_set_error(errno, "");
497     goto error;
498   }
499 
500   result->name_ID = p;
501   p               = HECMW_strdup(filename);
502 
503   if (p == NULL) {
504     HECMW_set_error(errno, "");
505     goto error;
506   }
507 
508   result->filename = p;
509   return result;
510 error:
511 
512   if (result) {
513     HECMW_free(result->name_ID);
514     HECMW_free(result->filename);
515     HECMW_free(result);
516   }
517 
518   return NULL;
519 }
520 
add_result_entry(struct result_entry * result)521 static int add_result_entry(struct result_entry *result) {
522   struct result_entry *p, *q;
523   q = NULL;
524 
525   for (p = result_ent; p; p = (q = p)->next)
526     ;
527 
528   if (q == NULL) {
529     result_ent = result;
530 
531   } else {
532     q->next = result;
533   }
534 
535   return 0;
536 }
537 
make_restart_entry(char * name_ID,int io,char * filename)538 static struct restart_entry *make_restart_entry(char *name_ID, int io,
539                                                 char *filename) {
540   char *p;
541   struct restart_entry *restart = NULL;
542   restart                       = HECMW_calloc(1, sizeof(*restart));
543 
544   if (restart == NULL) {
545     HECMW_set_error(errno, "");
546     goto error;
547   }
548 
549   restart->io   = io;
550   restart->next = NULL;
551   p             = HECMW_strdup(name_ID);
552 
553   if (p == NULL) {
554     HECMW_set_error(errno, "");
555     goto error;
556   }
557 
558   restart->name_ID = p;
559   p                = HECMW_strdup(filename);
560 
561   if (p == NULL) {
562     HECMW_set_error(errno, "");
563     goto error;
564   }
565 
566   restart->filename = p;
567   return restart;
568 error:
569 
570   if (restart) {
571     HECMW_free(restart->name_ID);
572     HECMW_free(restart->filename);
573     HECMW_free(restart);
574   }
575 
576   return NULL;
577 }
578 
add_restart_entry(struct restart_entry * restart)579 static int add_restart_entry(struct restart_entry *restart) {
580   struct restart_entry *p, *q;
581   q = NULL;
582 
583   for (p = restart_ent; p; p = (q = p)->next)
584     ;
585 
586   if (q == NULL) {
587     restart_ent = restart;
588 
589   } else {
590     q->next = restart;
591   }
592 
593   return 0;
594 }
595 
make_ctrl_entry(char * name_ID,char * filename)596 static struct ctrl_entry *make_ctrl_entry(char *name_ID, char *filename) {
597   char *p;
598   struct ctrl_entry *ctrl = NULL;
599   ctrl                    = HECMW_calloc(1, sizeof(*ctrl));
600 
601   if (ctrl == NULL) {
602     HECMW_set_error(errno, "");
603     goto error;
604   }
605 
606   ctrl->next = NULL;
607   p          = HECMW_strdup(name_ID);
608 
609   if (p == NULL) {
610     HECMW_set_error(errno, "");
611     goto error;
612   }
613 
614   ctrl->name_ID = p;
615   p             = HECMW_strdup(filename);
616 
617   if (p == NULL) {
618     HECMW_set_error(errno, "");
619     goto error;
620   }
621 
622   ctrl->filename = p;
623   return ctrl;
624 error:
625 
626   if (ctrl) {
627     HECMW_free(ctrl->name_ID);
628     HECMW_free(ctrl->filename);
629     HECMW_free(ctrl);
630   }
631 
632   return NULL;
633 }
634 
add_ctrl_entry(struct ctrl_entry * ctrl)635 static int add_ctrl_entry(struct ctrl_entry *ctrl) {
636   struct ctrl_entry *p, *q;
637   q = NULL;
638 
639   for (p = ctrl_ent; p; p = (q = p)->next)
640     ;
641 
642   if (q == NULL) {
643     ctrl_ent = ctrl;
644 
645   } else {
646     q->next = ctrl;
647   }
648 
649   return 0;
650 }
651 
652 /*----------------------------------------------------------------------------*/
653 
do_logging(int loglv,int msgno,int add_location,const char * fmt,va_list ap)654 static void do_logging(int loglv, int msgno, int add_location, const char *fmt,
655                        va_list ap) {
656   char line[100] = "";
657   char msg[HECMW_MSG_LEN + 1];
658   HECMW_vsnprintf(msg, sizeof(msg), fmt, ap);
659 
660   if (add_location) {
661     char *s = "";
662 
663     if (strlen(msg) > 0) s = ": ";
664 
665     HECMW_snprintf(line, sizeof(line), "%s:%d%s", ctrl_filename,
666                    HECMW_ctrllex_get_lineno(), s);
667   }
668 
669   HECMW_set_error(msgno, "%s%s", line, msg);
670 }
671 
set_err(int msgno,const char * fmt,...)672 static void set_err(int msgno, const char *fmt, ...) {
673   va_list ap;
674   va_start(ap, fmt);
675   do_logging(HECMW_LOG_ERROR, msgno, 1, fmt, ap);
676   va_end(ap);
677 }
678 
set_err_token(int token,int msgno,const char * fmt,...)679 static void set_err_token(int token, int msgno, const char *fmt, ...) {
680   int msg_no;
681   va_list ap;
682 
683   if (!token) {
684     msg_no = HECMW_UTIL_E0003;
685 
686   } else {
687     msg_no = msgno;
688   }
689 
690   va_start(ap, fmt);
691   do_logging(HECMW_LOG_ERROR, msg_no, 1, fmt, ap);
692   va_end(ap);
693 }
694 
695 /*----------------------------------------------------------------------------*/
696 
read_mesh_header(void)697 static int read_mesh_header(void) {
698   int token;
699   /* !MESH */
700   token = HECMW_ctrllex_next_token();
701 
702   if (token != HECMW_CTRLLEX_H_MESH) {
703     set_err(HECMW_UTIL_E0010, "!MESH required");
704     return -1;
705   }
706 
707   /* ',' */
708   token = HECMW_ctrllex_next_token();
709 
710   if (token != ',') {
711     set_err_token(token, HECMW_UTIL_E0010, "',' required after !MESH");
712     return -1;
713   }
714 
715   return 0;
716 }
717 
read_mesh_head_param_name(char * name)718 static int read_mesh_head_param_name(char *name) {
719   int token;
720   char *p;
721   token = HECMW_ctrllex_next_token();
722 
723   if (token != '=') {
724     set_err_token(token, HECMW_UTIL_E0010, "'=' required after NAME");
725     return -1;
726   }
727 
728   /* NAME value */
729   token = HECMW_ctrllex_next_token();
730 
731   if (token != HECMW_CTRLLEX_NAME) {
732     set_err_token(token, HECMW_UTIL_E0010,
733                   "NAME must begin with a letter or '_'");
734     return -1;
735   }
736 
737   p = HECMW_ctrllex_get_text();
738 
739   if (strlen(p) > HECMW_NAME_LEN) {
740     set_err(HECMW_IO_E0001, "");
741     return -1;
742   }
743 
744   strcpy(name, p);
745 
746   /* check */
747   if (get_mesh_entry(name) || get_mesh_grp_entry(name)) {
748     set_err(HECMW_UTIL_E0013, "");
749     return -1;
750   }
751 
752   return 0;
753 }
754 
read_mesh_head_param_type(int * type)755 static int read_mesh_head_param_type(int *type) {
756   int token;
757   token = HECMW_ctrllex_next_token();
758 
759   if (token != '=') {
760     set_err_token(token, HECMW_UTIL_E0010, "'=' required after TYPE");
761     return -1;
762   }
763 
764   /* TYPE value */
765   token = HECMW_ctrllex_next_token();
766 
767   if (token == HECMW_CTRLLEX_K_HECMW_DIST) {
768     *type = HECMW_CTRL_FTYPE_HECMW_DIST;
769 
770   } else if (token == HECMW_CTRLLEX_K_HECMW_ENTIRE) {
771     *type = HECMW_CTRL_FTYPE_HECMW_ENTIRE;
772 
773   } else if (token == HECMW_CTRLLEX_K_GEOFEM) {
774     *type = HECMW_CTRL_FTYPE_GEOFEM;
775 
776   } else if (token == HECMW_CTRLLEX_K_ABAQUS) {
777     *type = HECMW_CTRL_FTYPE_ABAQUS;
778 
779   } else if (token == HECMW_CTRLLEX_K_NASTRAN) {
780     *type = HECMW_CTRL_FTYPE_NASTRAN;
781 #if 0
782 
783   } else  if (token == HECMW_CTRLLEX_K_FEMAP) {
784     *type = HECMW_CTRL_FTYPE_FEMAP;
785 #endif
786 
787   } else {
788     set_err_token(token, HECMW_UTIL_E0010, "Invalid TYPE");
789     return -1;
790   }
791 
792   return 0;
793 }
794 
read_mesh_head_param_io(int * io)795 static int read_mesh_head_param_io(int *io) {
796   int token;
797   token = HECMW_ctrllex_next_token();
798 
799   if (token != '=') {
800     set_err_token(token, HECMW_UTIL_E0010, "'=' required after IO");
801     return -1;
802   }
803 
804   /* IO value */
805   token = HECMW_ctrllex_next_token();
806 
807   if (token == HECMW_CTRLLEX_K_IN) {
808     *io = HECMW_CTRL_FILE_IO_IN;
809 
810   } else if (token == HECMW_CTRLLEX_K_OUT) {
811     *io = HECMW_CTRL_FILE_IO_OUT;
812 
813   } else {
814     set_err_token(token, HECMW_UTIL_E0010, "Invalid IO");
815     return -1;
816   }
817 
818   return 0;
819 }
820 
read_mesh_head_param_refine(int * refine)821 static int read_mesh_head_param_refine(int *refine) {
822   int token;
823   token = HECMW_ctrllex_next_token();
824 
825   if (token != '=') {
826     set_err_token(token, HECMW_UTIL_E0010, "'=' required after REFINE");
827     return -1;
828   }
829 
830   /* REFINE value */
831   token = HECMW_ctrllex_next_token();
832 
833   if (token != HECMW_CTRLLEX_INT) {
834     set_err_token(token, HECMW_UTIL_E0010, "Invalid REFINE");
835     return -1;
836 
837   } else {
838     *refine = HECMW_ctrllex_get_number();
839   }
840 
841   return 0;
842 }
843 
read_mesh_data(char * name,int type,int io,int refine)844 static int read_mesh_data(char *name, int type, int io, int refine) {
845   int token;
846   char *p;
847   struct mesh_entry *mesh;
848   /* filename */
849   token = HECMW_ctrllex_next_token();
850 
851   if (token != HECMW_CTRLLEX_NAME && token != HECMW_CTRLLEX_FILENAME) {
852     set_err_token(token, HECMW_UTIL_E0010, "Invalid filename");
853     return -1;
854   }
855 
856   p = HECMW_ctrllex_get_text();
857 
858   if (strlen(p) > HECMW_FILENAME_LEN) {
859     set_err(HECMW_IO_E0002, "");
860     return -1;
861   }
862 
863   /* create */
864   mesh = make_mesh_entry(name, type, io, refine, p);
865 
866   if (mesh == NULL) return -1;
867 
868   /* add */
869   if (add_mesh_entry(mesh)) return -1;
870 
871   /* NL*/
872   token = HECMW_ctrllex_next_token();
873 
874   if (token != HECMW_CTRLLEX_NL) {
875     set_err_token(token, HECMW_UTIL_E0010, "NL required after filename");
876     return -1;
877   }
878 
879   return 0;
880 }
881 
read_mesh(void)882 static int read_mesh(void) {
883   int state;
884   int token                     = -1;
885   int flag_name                 = 0; /* flag for NAME */
886   int flag_type                 = 0; /* flag for TYPE */
887   int flag_io                   = 0; /* flag for IO */
888   int flag_refine               = 0; /* flag for REFINE */
889   int type                      = -1;
890   int io                        = HECMW_CTRL_FILE_IO_IN;
891   int refine                    = 0;
892   char name[HECMW_NAME_LEN + 1] = "";
893   enum {
894     ST_FINISHED,
895     ST_HEADER_LINE,
896     ST_HEADER_LINE_PARAM,
897     ST_DATA_LINE,
898   };
899   state = ST_HEADER_LINE;
900 
901   while (state != ST_FINISHED) {
902     if (state == ST_HEADER_LINE) {
903       if (read_mesh_header()) return -1;
904 
905       /* set next state */
906       state = ST_HEADER_LINE_PARAM;
907 
908     } else if (state == ST_HEADER_LINE_PARAM) {
909       token = HECMW_ctrllex_next_token();
910 
911       if (token == HECMW_CTRLLEX_K_NAME) {
912         /* must */
913         if (read_mesh_head_param_name(name)) return -1;
914 
915         flag_name = 1;
916 
917       } else if (token == HECMW_CTRLLEX_K_TYPE) {
918         /* must */
919         if (read_mesh_head_param_type(&type)) return -1;
920 
921         flag_type = 1;
922 
923       } else if (token == HECMW_CTRLLEX_K_IO) {
924         /* optional */
925         if (read_mesh_head_param_io(&io)) return -1;
926 
927         flag_io = 1;
928 
929       } else if (token == HECMW_CTRLLEX_K_REFINE) {
930         /* optional */
931         if (read_mesh_head_param_refine(&refine)) return -1;
932 
933         flag_refine = 1;
934 
935       } else {
936         set_err_token(token, HECMW_UTIL_E0010, "Unknown parameter");
937         return -1;
938       }
939 
940       /* check next parameter */
941       token = HECMW_ctrllex_next_token();
942 
943       if (token == HECMW_CTRLLEX_NL) {
944         /* check NAME */
945         if (!flag_name) {
946           set_err(HECMW_UTIL_E0011, "");
947           return -1;
948         }
949 
950         /* check TYPE */
951         if (!flag_type) {
952           set_err(HECMW_UTIL_E0012, "");
953           return -1;
954         }
955 
956         state = ST_DATA_LINE;
957 
958       } else if (token == ',') {
959         ; /* continue this state */
960 
961       } else {
962         set_err_token(token, HECMW_UTIL_E0010, "Unknown parameter");
963         return -1;
964       }
965 
966     } else if (state == ST_DATA_LINE) {
967       HECMW_assert(flag_name);
968       HECMW_assert(flag_type);
969 
970       if (read_mesh_data(name, type, io, refine)) return -1;
971 
972       state = ST_FINISHED;
973 
974     } else {
975       HECMW_assert(0);
976     }
977   }
978 
979   /* check */
980   if (!strcmp(name, "fstrMSH") && type == HECMW_CTRL_FTYPE_HECMW_ENTIRE &&
981       HECMW_comm_get_size() > 1) {
982     set_err_token(token, HECMW_UTIL_E0010, "Invalid TYPE");
983     return -1;
984   }
985 
986   return 0;
987 }
988 
989 /*----------------------------------------------------------------------------*/
990 
read_meshgrp_header(void)991 static int read_meshgrp_header(void) {
992   int token;
993   /* !MESH GROUP */
994   token = HECMW_ctrllex_next_token();
995 
996   if (token != HECMW_CTRLLEX_H_MESH_GROUP) {
997     set_err(HECMW_UTIL_E0050, "!MESH GROUP required");
998     return -1;
999   }
1000 
1001   /* ',' */
1002   token = HECMW_ctrllex_next_token();
1003 
1004   if (token != ',') {
1005     set_err_token(token, HECMW_UTIL_E0050, "',' required after !MESH GROUP");
1006     return -1;
1007   }
1008 
1009   return 0;
1010 }
1011 
read_meshgrp_head_param_name(char * name)1012 static int read_meshgrp_head_param_name(char *name) {
1013   int token;
1014   char *p;
1015   token = HECMW_ctrllex_next_token();
1016 
1017   if (token != '=') {
1018     set_err_token(token, HECMW_UTIL_E0050, "'=' required after NAME");
1019     return -1;
1020   }
1021 
1022   /* NAME value */
1023   token = HECMW_ctrllex_next_token();
1024 
1025   if (token != HECMW_CTRLLEX_NAME) {
1026     set_err_token(token, HECMW_UTIL_E0050,
1027                   "NAME must begin with a letter or '_'");
1028     return -1;
1029   }
1030 
1031   p = HECMW_ctrllex_get_text();
1032 
1033   if (strlen(p) > HECMW_NAME_LEN) {
1034     set_err(HECMW_IO_E0001, "");
1035     return -1;
1036   }
1037 
1038   strcpy(name, p);
1039 
1040   /* check */
1041   if (get_mesh_entry(name) || get_mesh_grp_entry(name)) {
1042     set_err(HECMW_UTIL_E0053, "");
1043     return -1;
1044   }
1045 
1046   return 0;
1047 }
1048 
read_meshgrp_data(char * name)1049 static int read_meshgrp_data(char *name) {
1050   int i, token, n_mesh, n_mesh_max;
1051   char *p, **q;
1052   char **mesh                    = NULL;
1053   struct mesh_grp_entry *meshgrp = NULL;
1054   struct mesh_entry *ment;
1055   n_mesh_max = 10; /* default */
1056   mesh       = HECMW_malloc(sizeof(*mesh) * n_mesh_max);
1057 
1058   if (mesh == NULL) {
1059     HECMW_set_error(errno, "");
1060     return -1;
1061   }
1062 
1063   n_mesh = 0;
1064 
1065   while (1) {
1066     /* filename */
1067     token = HECMW_ctrllex_next_token();
1068 
1069     if (token != HECMW_CTRLLEX_NAME && token != HECMW_CTRLLEX_FILENAME) {
1070       if (n_mesh == 0) {
1071         set_err_token(token, HECMW_UTIL_E0050, "name_ID required");
1072         return -1;
1073       }
1074 
1075       HECMW_ctrllex_unput_token();
1076       break;
1077     }
1078 
1079     p = HECMW_ctrllex_get_text();
1080 
1081     if (strlen(p) > HECMW_FILENAME_LEN) {
1082       set_err(HECMW_IO_E0002, "");
1083       return -1;
1084     }
1085 
1086     if ((ment = get_mesh_entry(p)) == NULL) {
1087       set_err_token(token, HECMW_UTIL_E0052, "name_ID: %s", p);
1088       return -1;
1089     }
1090 
1091     if (!is_entire_mesh(ment->type)) {
1092       set_err_token(token, HECMW_UTIL_E0055, "name_ID: %s", p);
1093       return -1;
1094     }
1095 
1096     if (n_mesh == n_mesh_max) {
1097       n_mesh_max *= 2;
1098       q = HECMW_realloc(mesh, sizeof(*mesh) * n_mesh_max);
1099 
1100       if (q == NULL) {
1101         HECMW_set_error(errno, "");
1102         return -1;
1103       }
1104 
1105       mesh = q;
1106     }
1107 
1108     mesh[n_mesh] = HECMW_strdup(p);
1109 
1110     if (mesh[n_mesh] == NULL) {
1111       HECMW_set_error(errno, "");
1112       return -1;
1113     }
1114 
1115     n_mesh++;
1116     /* ',' or NL*/
1117     token = HECMW_ctrllex_next_token();
1118 
1119     if (token != HECMW_CTRLLEX_NL && token != ',') {
1120       set_err_token(token, HECMW_UTIL_E0050,
1121                     "','  or NL required after name_ID");
1122       return -1;
1123     }
1124   }
1125 
1126   /* create */
1127   meshgrp = make_mesh_group_entry(name, n_mesh, mesh);
1128 
1129   if (meshgrp == NULL) return -1;
1130 
1131   /* add */
1132   if (add_mesh_group_entry(meshgrp)) return -1;
1133 
1134   for (i = 0; i < n_mesh; i++) {
1135     HECMW_free(mesh[i]);
1136   }
1137 
1138   HECMW_free(mesh);
1139   return 0;
1140 }
1141 
read_meshgrp(void)1142 static int read_meshgrp(void) {
1143   int token, state;
1144   int flag_name                 = 0; /* flag for NAME */
1145   char name[HECMW_NAME_LEN + 1] = "";
1146   enum {
1147     ST_FINISHED,
1148     ST_HEADER_LINE,
1149     ST_HEADER_LINE_PARAM,
1150     ST_DATA_LINE,
1151   };
1152   state = ST_HEADER_LINE;
1153 
1154   while (state != ST_FINISHED) {
1155     if (state == ST_HEADER_LINE) {
1156       if (read_meshgrp_header()) return -1;
1157 
1158       /* set next state */
1159       state = ST_HEADER_LINE_PARAM;
1160 
1161     } else if (state == ST_HEADER_LINE_PARAM) {
1162       token = HECMW_ctrllex_next_token();
1163 
1164       if (token == HECMW_CTRLLEX_K_NAME) {
1165         /* must */
1166         if (read_meshgrp_head_param_name(name)) return -1;
1167 
1168         flag_name = 1;
1169 
1170       } else {
1171         set_err_token(token, HECMW_UTIL_E0050, "Unknown parameter");
1172         return -1;
1173       }
1174 
1175       /* check next parameter */
1176       token = HECMW_ctrllex_next_token();
1177 
1178       if (token == HECMW_CTRLLEX_NL) {
1179         /* check NAME */
1180         if (!flag_name) {
1181           set_err(HECMW_UTIL_E0051, "");
1182           return -1;
1183         }
1184 
1185         state = ST_DATA_LINE;
1186 
1187       } else if (token == ',') {
1188         ; /* continue this state */
1189 
1190       } else {
1191         set_err_token(token, HECMW_UTIL_E0050, "Unknown parameter");
1192         return -1;
1193       }
1194 
1195     } else if (state == ST_DATA_LINE) {
1196       HECMW_assert(flag_name);
1197 
1198       if (read_meshgrp_data(name)) return -1;
1199 
1200       state = ST_FINISHED;
1201 
1202     } else {
1203       HECMW_assert(0);
1204     }
1205   }
1206 
1207   return 0;
1208 }
1209 
1210 /*----------------------------------------------------------------------------*/
1211 
read_result_head(void)1212 static int read_result_head(void) {
1213   int token;
1214   /* !RESULT */
1215   token = HECMW_ctrllex_next_token();
1216 
1217   if (token != HECMW_CTRLLEX_H_RESULT) {
1218     set_err(HECMW_UTIL_E0020, "!RESULT required");
1219     return -1;
1220   }
1221 
1222   /* ',' */
1223   token = HECMW_ctrllex_next_token();
1224 
1225   if (token != ',') {
1226     set_err_token(token, HECMW_UTIL_E0020, "',' required after !RESULT");
1227     return -1;
1228   }
1229 
1230   return 0;
1231 }
1232 
read_result_param_name(char * name)1233 static int read_result_param_name(char *name) {
1234   int token;
1235   char *p;
1236   token = HECMW_ctrllex_next_token();
1237 
1238   if (token != '=') {
1239     set_err_token(token, HECMW_UTIL_E0020, "'=' required after NAME");
1240     return -1;
1241   }
1242 
1243   /* NAME value */
1244   token = HECMW_ctrllex_next_token();
1245 
1246   if (token != HECMW_CTRLLEX_NAME) {
1247     set_err_token(token, HECMW_UTIL_E0020,
1248                   "NAME must begin with a letter or '_'");
1249     return -1;
1250   }
1251 
1252   p = HECMW_ctrllex_get_text();
1253 
1254   if (strlen(p) > HECMW_NAME_LEN) {
1255     set_err(HECMW_IO_E0001, "");
1256     return -1;
1257   }
1258 
1259   strcpy(name, p);
1260 
1261   /* check */
1262   if (get_result_entry(name)) {
1263     set_err(HECMW_UTIL_E0023, "");
1264     return -1;
1265   }
1266 
1267   return 0;
1268 }
1269 
read_result_param_io(int * io)1270 static int read_result_param_io(int *io) {
1271   int token;
1272   token = HECMW_ctrllex_next_token();
1273 
1274   if (token != '=') {
1275     set_err_token(token, HECMW_UTIL_E0020, "'=' required after IO");
1276     return -1;
1277   }
1278 
1279   /* IO value */
1280   token = HECMW_ctrllex_next_token();
1281 
1282   if (token == HECMW_CTRLLEX_K_IN) {
1283     *io = HECMW_CTRL_FILE_IO_IN;
1284 
1285   } else if (token == HECMW_CTRLLEX_K_OUT) {
1286     *io = HECMW_CTRL_FILE_IO_OUT;
1287 
1288   } else {
1289     set_err_token(token, HECMW_UTIL_E0020, "Invalid IO");
1290     return -1;
1291   }
1292 
1293   return 0;
1294 }
1295 
read_result_param_type(int * fg_text)1296 static int read_result_param_type(int *fg_text) {
1297   int token;
1298   char s[HECMW_NAME_LEN + 1];
1299   char *p;
1300   char *sp;
1301   token = HECMW_ctrllex_next_token();
1302 
1303   if (token != '=') {
1304     set_err_token(token, HECMW_UTIL_E0020, "'=' required after TYPE");
1305     return -1;
1306   }
1307 
1308   /* TYPE value */
1309   token = HECMW_ctrllex_next_token();
1310   p     = HECMW_ctrllex_get_text();
1311 
1312   if (strlen(p) > HECMW_NAME_LEN) {
1313     set_err(HECMW_UTIL_E0020, "");
1314     return -1;
1315   }
1316 
1317   sp = s;
1318 
1319   while (*p) {
1320     *sp = (char)toupper(*p);
1321     p++;
1322     sp++;
1323   }
1324 
1325   *sp = 0;
1326 
1327   if (strcmp(s, "TEXT") == 0) {
1328     *fg_text = 1;
1329 
1330   } else if (strcmp(s, "BINARY") == 0) {
1331     *fg_text = 0;
1332 
1333   } else {
1334     set_err(HECMW_UTIL_E0020, "TEXT or BINARY required");
1335     return -1;
1336   }
1337 
1338   return 0;
1339 }
1340 
read_result_data(char * name,int io,int fg_text)1341 static int read_result_data(char *name, int io, int fg_text) {
1342   int token;
1343   char *p;
1344   struct result_entry *result;
1345   /* filename */
1346   token = HECMW_ctrllex_next_token();
1347 
1348   if (token != HECMW_CTRLLEX_NAME && token != HECMW_CTRLLEX_FILENAME) {
1349     set_err_token(token, HECMW_UTIL_E0020, "Invalid filename");
1350   }
1351 
1352   p = HECMW_ctrllex_get_text();
1353 
1354   if (strlen(p) > HECMW_FILENAME_LEN) {
1355     set_err(HECMW_IO_E0002, "NL required after filename");
1356     return -1;
1357   }
1358 
1359   /* create */
1360   result = make_result_entry(name, io, fg_text, p);
1361 
1362   if (result == NULL) return -1;
1363 
1364   /* add */
1365   if (add_result_entry(result)) return -1;
1366 
1367   /* NL*/
1368   token = HECMW_ctrllex_next_token();
1369 
1370   if (token != HECMW_CTRLLEX_NL) {
1371     set_err_token(token, HECMW_UTIL_E0020, "NL required after filename");
1372     return -1;
1373   }
1374 
1375   return 0;
1376 }
1377 
read_result(void)1378 static int read_result(void) {
1379   int token, state;
1380   int flag_name = 0; /* flag for NAME */
1381   int flag_io   = 0; /* flag for IO */
1382   int io;
1383   int fg_text; /* default : text */
1384   char name[HECMW_NAME_LEN + 1] = "";
1385   enum {
1386     ST_FINISHED,
1387     ST_HEADER_LINE,
1388     ST_HEADER_LINE_PARAM,
1389     ST_DATA_LINE,
1390   };
1391   fg_text = 1;
1392   state   = ST_HEADER_LINE;
1393 
1394   while (state != ST_FINISHED) {
1395     if (state == ST_HEADER_LINE) {
1396       if (read_result_head()) return -1;
1397 
1398       state = ST_HEADER_LINE_PARAM;
1399 
1400     } else if (state == ST_HEADER_LINE_PARAM) {
1401       token = HECMW_ctrllex_next_token();
1402 
1403       if (token == HECMW_CTRLLEX_K_NAME) {
1404         /* must */
1405         if (read_result_param_name(name)) return -1;
1406 
1407         flag_name = 1;
1408 
1409       } else if (token == HECMW_CTRLLEX_K_IO) {
1410         /* must */
1411         if (read_result_param_io(&io)) return -1;
1412 
1413         flag_io = 1;
1414 
1415       } else if (token == HECMW_CTRLLEX_K_TYPE) {
1416         /* option */
1417         if (read_result_param_type(&fg_text)) return -1;
1418 
1419       } else {
1420         set_err_token(token, HECMW_UTIL_E0020, "Unknown parameter");
1421         return -1;
1422       }
1423 
1424       /* check next parameter */
1425       token = HECMW_ctrllex_next_token();
1426 
1427       if (token == HECMW_CTRLLEX_NL) {
1428         /* check NAME */
1429         if (!flag_name) {
1430           set_err(HECMW_UTIL_E0021, "");
1431           return -1;
1432         }
1433 
1434         /* check IO */
1435         if (!flag_io) {
1436           set_err(HECMW_UTIL_E0022, "");
1437           return -1;
1438         }
1439 
1440         state = ST_DATA_LINE;
1441 
1442       } else if (token == ',') {
1443         ; /* continue this state */
1444 
1445       } else {
1446         set_err_token(token, HECMW_UTIL_E0020, "Unknown parameter");
1447         return -1;
1448       }
1449 
1450     } else if (state == ST_DATA_LINE) {
1451       HECMW_assert(flag_name);
1452 
1453       if (read_result_data(name, io, fg_text)) return -1;
1454 
1455       state = ST_FINISHED;
1456 
1457     } else {
1458       HECMW_assert(0);
1459     }
1460   }
1461 
1462   return 0;
1463 }
1464 
1465 /*----------------------------------------------------------------------------*/
1466 
read_restart_head(void)1467 static int read_restart_head(void) {
1468   int token;
1469   /* !RESULT */
1470   token = HECMW_ctrllex_next_token();
1471 
1472   if (token != HECMW_CTRLLEX_H_RESTART) {
1473     set_err(HECMW_UTIL_E0040, "!RESTART required");
1474     return -1;
1475   }
1476 
1477   /* ',' */
1478   token = HECMW_ctrllex_next_token();
1479 
1480   if (token != ',') {
1481     set_err_token(token, HECMW_UTIL_E0040, "',' required after !RESTART");
1482     return -1;
1483   }
1484 
1485   return 0;
1486 }
1487 
read_restart_param_name(char * name)1488 static int read_restart_param_name(char *name) {
1489   int token;
1490   char *p;
1491   token = HECMW_ctrllex_next_token();
1492 
1493   if (token != '=') {
1494     set_err_token(token, HECMW_UTIL_E0040, "'=' required after NAME");
1495     return -1;
1496   }
1497 
1498   /* NAME value */
1499   token = HECMW_ctrllex_next_token();
1500 
1501   if (token != HECMW_CTRLLEX_NAME) {
1502     set_err_token(token, HECMW_UTIL_E0040,
1503                   "NAME must begin with a letter or '_'");
1504     return -1;
1505   }
1506 
1507   p = HECMW_ctrllex_get_text();
1508 
1509   if (strlen(p) > HECMW_NAME_LEN) {
1510     set_err(HECMW_IO_E0001, "");
1511     return -1;
1512   }
1513 
1514   strcpy(name, p);
1515 
1516   /* check */
1517   if (get_restart_entry(name)) {
1518     set_err(HECMW_UTIL_E0043, "");
1519     return -1;
1520   }
1521 
1522   return 0;
1523 }
1524 
read_restart_param_io(int * io)1525 static int read_restart_param_io(int *io) {
1526   int token;
1527   token = HECMW_ctrllex_next_token();
1528 
1529   if (token != '=') {
1530     set_err_token(token, HECMW_UTIL_E0040, "'=' required after IO");
1531     return -1;
1532   }
1533 
1534   /* IO value */
1535   token = HECMW_ctrllex_next_token();
1536 
1537   if (token == HECMW_CTRLLEX_K_IN) {
1538     *io = HECMW_CTRL_FILE_IO_IN;
1539 
1540   } else if (token == HECMW_CTRLLEX_K_OUT) {
1541     *io = HECMW_CTRL_FILE_IO_OUT;
1542 
1543   } else if (token == HECMW_CTRLLEX_K_INOUT) {
1544     *io = HECMW_CTRL_FILE_IO_INOUT;
1545 
1546   } else {
1547     set_err_token(token, HECMW_UTIL_E0040, "Invalid IO");
1548     return -1;
1549   }
1550 
1551   return 0;
1552 }
1553 
read_restart_data(char * name,int io)1554 static int read_restart_data(char *name, int io) {
1555   int token;
1556   char *p;
1557   struct restart_entry *restart;
1558   /* filename */
1559   token = HECMW_ctrllex_next_token();
1560 
1561   if (token != HECMW_CTRLLEX_NAME && token != HECMW_CTRLLEX_FILENAME) {
1562     set_err_token(token, HECMW_UTIL_E0040, "Invalid filename");
1563   }
1564 
1565   p = HECMW_ctrllex_get_text();
1566 
1567   if (strlen(p) > HECMW_FILENAME_LEN) {
1568     set_err(HECMW_IO_E0002, "NL required after filename");
1569     return -1;
1570   }
1571 
1572   /* create */
1573   restart = make_restart_entry(name, io, p);
1574 
1575   if (restart == NULL) return -1;
1576 
1577   /* add */
1578   if (add_restart_entry(restart)) return -1;
1579 
1580   /* NL*/
1581   token = HECMW_ctrllex_next_token();
1582 
1583   if (token != HECMW_CTRLLEX_NL) {
1584     set_err_token(token, HECMW_UTIL_E0040, "NL required after filename");
1585     return -1;
1586   }
1587 
1588   return 0;
1589 }
1590 
read_restart(void)1591 static int read_restart(void) {
1592   int token, state;
1593   int flag_name = 0; /* flag for NAME */
1594   int flag_io   = 0; /* flag for IO */
1595   int io;
1596   char name[HECMW_NAME_LEN + 1] = "";
1597   enum {
1598     ST_FINISHED,
1599     ST_HEADER_LINE,
1600     ST_HEADER_LINE_PARAM,
1601     ST_DATA_LINE,
1602   };
1603   state = ST_HEADER_LINE;
1604 
1605   while (state != ST_FINISHED) {
1606     if (state == ST_HEADER_LINE) {
1607       if (read_restart_head()) return -1;
1608 
1609       /* set next state */
1610       state = ST_HEADER_LINE_PARAM;
1611 
1612     } else if (state == ST_HEADER_LINE_PARAM) {
1613       token = HECMW_ctrllex_next_token();
1614 
1615       if (token == HECMW_CTRLLEX_K_NAME) {
1616         /* must */
1617         if (read_restart_param_name(name)) return -1;
1618 
1619         flag_name = 1;
1620 
1621       } else if (token == HECMW_CTRLLEX_K_IO) {
1622         /* must */
1623         if (read_restart_param_io(&io)) return -1;
1624 
1625         flag_io = 1;
1626 
1627       } else {
1628         set_err_token(token, HECMW_UTIL_E0040, "Unknown parameter");
1629         return -1;
1630       }
1631 
1632       /* check next parameter */
1633       token = HECMW_ctrllex_next_token();
1634 
1635       if (token == HECMW_CTRLLEX_NL) {
1636         /* check NAME */
1637         if (!flag_name) {
1638           set_err(HECMW_UTIL_E0041, "");
1639           return -1;
1640         }
1641 
1642         /* check IO */
1643         if (!flag_io) {
1644           set_err(HECMW_UTIL_E0042, "");
1645           return -1;
1646         }
1647 
1648         state = ST_DATA_LINE;
1649 
1650       } else if (token == ',') {
1651         ; /* continue this state */
1652 
1653       } else {
1654         set_err_token(token, HECMW_UTIL_E0040, "Unknown parameter");
1655         return -1;
1656       }
1657 
1658     } else if (state == ST_DATA_LINE) {
1659       HECMW_assert(flag_name);
1660       HECMW_assert(flag_io);
1661 
1662       if (read_restart_data(name, io)) return -1;
1663 
1664       state = ST_FINISHED;
1665 
1666     } else {
1667       HECMW_assert(0);
1668     }
1669   }
1670 
1671   return 0;
1672 }
1673 
1674 /*----------------------------------------------------------------------------*/
1675 
read_control_head(void)1676 static int read_control_head(void) {
1677   int token;
1678   /* !CONTROL */
1679   token = HECMW_ctrllex_next_token();
1680 
1681   if (token != HECMW_CTRLLEX_H_CONTROL) {
1682     set_err(HECMW_UTIL_E0030, "!CONTROL required");
1683     return -1;
1684   }
1685 
1686   /* ',' */
1687   token = HECMW_ctrllex_next_token();
1688 
1689   if (token != ',') {
1690     set_err_token(token, HECMW_UTIL_E0030, "',' required after !CONTROL");
1691     return -1;
1692   }
1693 
1694   return 0;
1695 }
1696 
read_control_head_param_name(char * name)1697 static int read_control_head_param_name(char *name) {
1698   int token;
1699   char *p;
1700   token = HECMW_ctrllex_next_token();
1701 
1702   if (token != '=') {
1703     set_err_token(token, HECMW_UTIL_E0030, "'=' required after NAME");
1704     return -1;
1705   }
1706 
1707   /* NAME value */
1708   token = HECMW_ctrllex_next_token();
1709 
1710   if (token != HECMW_CTRLLEX_NAME) {
1711     set_err_token(token, HECMW_UTIL_E0030,
1712                   "NAME must begin with a letter or '_'");
1713     return -1;
1714   }
1715 
1716   p = HECMW_ctrllex_get_text();
1717 
1718   if (strlen(p) > HECMW_NAME_LEN) {
1719     set_err(HECMW_IO_E0001, "");
1720     return -1;
1721   }
1722 
1723   strcpy(name, p);
1724 
1725   /* check */
1726   if (get_ctrl_entry(name)) {
1727     set_err(HECMW_UTIL_E0032, "");
1728     return -1;
1729   }
1730 
1731   return 0;
1732 }
1733 
read_control_data(char * name)1734 static int read_control_data(char *name) {
1735   int token;
1736   char *p;
1737   struct ctrl_entry *control;
1738   /* filename */
1739   token = HECMW_ctrllex_next_token();
1740 
1741   if (token != HECMW_CTRLLEX_NAME && token != HECMW_CTRLLEX_FILENAME) {
1742     set_err_token(token, HECMW_UTIL_E0030, "Invalid filename");
1743     return -1;
1744   }
1745 
1746   p = HECMW_ctrllex_get_text();
1747 
1748   if (strlen(p) > HECMW_FILENAME_LEN) {
1749     set_err(HECMW_IO_E0002, "NL required after filename");
1750     return -1;
1751   }
1752 
1753   /* create */
1754   control = make_ctrl_entry(name, p);
1755 
1756   if (control == NULL) {
1757     return -1;
1758   }
1759 
1760   /* add */
1761   if (add_ctrl_entry(control)) {
1762     return -1;
1763   }
1764 
1765   /* NL*/
1766   token = HECMW_ctrllex_next_token();
1767 
1768   if (token != HECMW_CTRLLEX_NL) {
1769     set_err_token(token, HECMW_UTIL_E0030, "NL required after filename");
1770     return -1;
1771   }
1772 
1773   return 0;
1774 }
1775 
read_control(void)1776 static int read_control(void) {
1777   int token, state;
1778   int flag_name                 = 0; /* flag for NAME */
1779   char name[HECMW_NAME_LEN + 1] = "";
1780   enum {
1781     ST_FINISHED,
1782     ST_HEADER_LINE,
1783     ST_HEADER_LINE_PARAM,
1784     ST_DATA_LINE,
1785   };
1786   state = ST_HEADER_LINE;
1787 
1788   while (state != ST_FINISHED) {
1789     if (state == ST_HEADER_LINE) {
1790       if (read_control_head()) return -1;
1791 
1792       /* set next state */
1793       state = ST_HEADER_LINE_PARAM;
1794 
1795     } else if (state == ST_HEADER_LINE_PARAM) {
1796       token = HECMW_ctrllex_next_token();
1797 
1798       if (token == HECMW_CTRLLEX_K_NAME) {
1799         /* must */
1800         if (read_control_head_param_name(name)) return -1;
1801 
1802         flag_name = 1;
1803 
1804       } else {
1805         set_err_token(token, HECMW_UTIL_E0030, "Unknown parameter");
1806         return -1;
1807       }
1808 
1809       /* check next parameter */
1810       token = HECMW_ctrllex_next_token();
1811 
1812       if (token == HECMW_CTRLLEX_NL) {
1813         /* check NAME */
1814         if (!flag_name) {
1815           set_err(HECMW_UTIL_E0031, "");
1816           return -1;
1817         }
1818 
1819         state = ST_DATA_LINE;
1820 
1821       } else if (token == ',') {
1822         ; /* continue this state */
1823 
1824       } else {
1825         set_err_token(token, HECMW_UTIL_E0030, "Unknown parameter");
1826         return -1;
1827       }
1828 
1829     } else if (state == ST_DATA_LINE) {
1830       HECMW_assert(flag_name);
1831 
1832       if (read_control_data(name)) return -1;
1833 
1834       state = ST_FINISHED;
1835 
1836     } else {
1837       HECMW_assert(0);
1838     }
1839   }
1840 
1841   return 0;
1842 }
1843 
1844 /*----------------------------------------------------------------------------*/
1845 
read_subdir_head(void)1846 static int read_subdir_head(void) {
1847   int token;
1848   /* !SUBDIR */
1849   token = HECMW_ctrllex_next_token();
1850 
1851   if (token != HECMW_CTRLLEX_H_SUBDIR) {
1852     set_err(HECMW_UTIL_E0060, "!SUBDIR required");
1853     return -1;
1854   }
1855 
1856   /* ',' */
1857   token = HECMW_ctrllex_next_token();
1858 
1859   if (token != ',') {
1860     set_err_token(token, HECMW_UTIL_E0060, "',' required after !SUBDIR");
1861     return -1;
1862   }
1863 
1864   return 0;
1865 }
1866 
read_subdir_head_param_limit(void)1867 static int read_subdir_head_param_limit(void) {
1868   int token;
1869   token = HECMW_ctrllex_next_token();
1870 
1871   if (token != '=') {
1872     set_err_token(token, HECMW_UTIL_E0060, "'=' required after LIMIT");
1873     return -1;
1874   }
1875 
1876   /* LIMIT value */
1877   token = HECMW_ctrllex_next_token();
1878 
1879   if (token != HECMW_CTRLLEX_INT) {
1880     set_err_token(token, HECMW_UTIL_E0060, "Invalid LIMIT");
1881     return -1;
1882 
1883   } else {
1884     nlimit = HECMW_ctrllex_get_number();
1885   }
1886 
1887   return 0;
1888 }
1889 
read_subdir(void)1890 static int read_subdir(void) {
1891   int token, state;
1892   int flag_name                 = 0; /* flag for NAME */
1893   enum {
1894     ST_FINISHED,
1895     ST_HEADER_LINE,
1896     ST_HEADER_LINE_PARAM,
1897   };
1898   nlimit = 5000;
1899   state  = ST_HEADER_LINE;
1900 
1901   while (state != ST_FINISHED) {
1902     if (state == ST_HEADER_LINE) {
1903       if (read_subdir_head()) return -1;
1904 
1905       /* set next state */
1906       state = ST_HEADER_LINE_PARAM;
1907 
1908     } else if (state == ST_HEADER_LINE_PARAM) {
1909       token = HECMW_ctrllex_next_token();
1910 
1911       if (token == HECMW_CTRLLEX_K_ON) {
1912         /* must */
1913         subdir_on = 1;
1914         flag_name = 1;
1915 
1916       } else if (token == HECMW_CTRLLEX_K_OFF) {
1917         /* must */
1918         subdir_on = 0;
1919         flag_name = 1;
1920 
1921       } else if (token == HECMW_CTRLLEX_K_LIMIT) {
1922         if (read_subdir_head_param_limit()) return -1;
1923 
1924       } else {
1925         set_err_token(token, HECMW_UTIL_E0060, "Unknown parameter");
1926         return -1;
1927       }
1928 
1929       /* check next parameter */
1930       token = HECMW_ctrllex_next_token();
1931 
1932       if (token == HECMW_CTRLLEX_NL) {
1933         if (!flag_name) {
1934           set_err(HECMW_UTIL_E0061, "");
1935           return -1;
1936         }
1937 
1938         state = ST_FINISHED;
1939 
1940       } else if (token == ',') {
1941         ; /* continue this state */
1942 
1943       } else {
1944         set_err_token(token, HECMW_UTIL_E0060, "Unknown parameter");
1945         return -1;
1946       }
1947 
1948     } else {
1949       HECMW_assert(0);
1950     }
1951   }
1952 
1953   return 0;
1954 }
1955 
1956 /*------------------------------------------------------------------------------
1957   ReadFunc table
1958 */
1959 
1960 typedef int (*ReadFunc)(void);
1961 
1962 static struct read_func_table {
1963   int token;
1964   ReadFunc func;
1965 } read_func_table[] = {
1966     {HECMW_CTRLLEX_H_CONTROL, read_control},
1967     {HECMW_CTRLLEX_H_MESH, read_mesh},
1968     {HECMW_CTRLLEX_H_MESH_GROUP, read_meshgrp},
1969     {HECMW_CTRLLEX_H_RESULT, read_result},
1970     {HECMW_CTRLLEX_H_RESTART, read_restart},
1971     {HECMW_CTRLLEX_H_SUBDIR, read_subdir},
1972 };
1973 
1974 #define N_READ_FUNC (sizeof(read_func_table) / sizeof(read_func_table[0]))
1975 
1976 /* static int (* get_read_func(int token))(void) */
get_read_func(int token)1977 static ReadFunc get_read_func(int token) {
1978   int i;
1979 
1980   for (i = 0; i < N_READ_FUNC; i++) {
1981     if (token == read_func_table[i].token) {
1982       return read_func_table[i].func;
1983     }
1984   }
1985 
1986   return NULL;
1987 }
1988 
1989 /*----------------------------------------------------------------------------*/
1990 
parse(void)1991 static int parse(void) {
1992   int token;
1993   ReadFunc func;
1994 
1995   while ((token = HECMW_ctrllex_next_token())) {
1996     if (token == HECMW_CTRLLEX_NL) continue;
1997 
1998     func = get_read_func(token);
1999 
2000     if (func == NULL) {
2001       char *p = HECMW_ctrllex_get_text();
2002 
2003       if (p[0] == '!') {
2004         set_err(HECMW_UTIL_E0004, "");
2005 
2006       } else {
2007         set_err(HECMW_UTIL_E0005, "");
2008       }
2009 
2010       return -1;
2011     }
2012 
2013     HECMW_ctrllex_unput_token(); /* unput !XXXX */
2014 
2015     if ((*func)()) return -1;
2016   }
2017 
2018   return 0;
2019 }
2020 
HECMW_ctrl_init_ex(const char * ctrlfile)2021 int HECMW_ctrl_init_ex(const char *ctrlfile) {
2022   FILE *fp;
2023   HECMW_log(HECMW_LOG_DEBUG, "Getting control data");
2024 
2025   if (ctrlfile == NULL) {
2026     HECMW_set_error(HECMW_ALL_E0101, "Not specified control file name");
2027     return -1;
2028   }
2029 
2030   strcpy(ctrl_filename, ctrlfile);
2031   HECMW_log(HECMW_LOG_DEBUG, "Control file is '%s'", ctrl_filename);
2032 
2033   if ((fp = fopen(ctrl_filename, "r")) == NULL) {
2034     HECMW_set_error(HECMW_UTIL_E0001, "File: %s, %s", ctrl_filename,
2035                     strerror(errno));
2036     return -1;
2037   }
2038 
2039   if (HECMW_ctrllex_set_input(fp)) return -1;
2040 
2041   if (parse()) {
2042     return -1;
2043   }
2044 
2045   if (fclose(fp)) {
2046     HECMW_set_error(HECMW_UTIL_E0002, "File: %s, %s", ctrl_filename,
2047                     strerror(errno));
2048     return -1;
2049   }
2050 
2051   return 0;
2052 }
2053 
HECMW_ctrl_init(void)2054 int HECMW_ctrl_init(void) { return HECMW_ctrl_init_ex(HECMW_CTRL_FILE); }
2055 
HECMW_ctrl_finalize(void)2056 int HECMW_ctrl_finalize(void) {
2057   HECMW_log(HECMW_LOG_DEBUG, "Finalizing control data");
2058   free_ctrl_entry();
2059   free_mesh_entry();
2060   free_mesh_grp_entry();
2061   free_result_entry();
2062   free_restart_entry();
2063   return 0;
2064 }
2065 
HECMW_ctrl_free_meshfiles(struct hecmw_ctrl_meshfiles * meshfiles)2066 void HECMW_ctrl_free_meshfiles(struct hecmw_ctrl_meshfiles *meshfiles) {
2067   int i;
2068 
2069   for (i = 0; i < meshfiles->n_mesh; i++) {
2070     HECMW_free(meshfiles->meshfiles[i].filename);
2071   }
2072 
2073   HECMW_free(meshfiles->meshfiles);
2074   HECMW_free(meshfiles);
2075 }
2076 
make_meshfiles_struct(int n_mesh,struct mesh_entry ** mesh,int n_rank,int i_rank,int flag_rank_none)2077 static struct hecmw_ctrl_meshfiles *make_meshfiles_struct(
2078     int n_mesh, struct mesh_entry **mesh, int n_rank, int i_rank,
2079     int flag_rank_none) {
2080   int i, flag_rank, nrank, myrank, irank;
2081   char *fname;
2082   char *retval;
2083   struct hecmw_ctrl_meshfiles *files;
2084   char prefix[10];
2085   files = HECMW_malloc(sizeof(*files));
2086 
2087   if (files == NULL) {
2088     HECMW_set_error(errno, "");
2089     return NULL;
2090   }
2091 
2092   if (n_rank == 0) {
2093     nrank  = HECMW_comm_get_size();
2094     myrank = HECMW_comm_get_rank();
2095 
2096   } else {
2097     nrank  = n_rank;
2098     myrank = i_rank;
2099   }
2100 
2101   files->n_mesh    = n_mesh;
2102   files->meshfiles = HECMW_malloc(sizeof(*files->meshfiles) * n_mesh);
2103 
2104   if (files->meshfiles == NULL) {
2105     HECMW_set_error(errno, "");
2106     return NULL;
2107   }
2108 
2109   for (i = 0; i < n_mesh; i++) {
2110     struct hecmw_ctrl_meshfile *file = &files->meshfiles[i];
2111     struct mesh_entry *ment          = mesh[i];
2112     file->type                       = ment->type;
2113     file->io                         = ment->io;
2114     file->refine                     = ment->refine;
2115 
2116     if (flag_rank_none) {
2117       flag_rank = 0;
2118 
2119     } else {
2120       if (is_entire_mesh(file->type)) {
2121         flag_rank = 0;
2122 
2123       } else {
2124         flag_rank = 1;
2125       }
2126     }
2127 
2128     fname = HECMW_malloc(sizeof(char) * (HECMW_FILENAME_LEN + 1));
2129 
2130     if (fname == NULL) {
2131       HECMW_set_error(errno, "");
2132       return NULL;
2133     }
2134 
2135     if (ment->type == HECMW_CTRL_FTYPE_HECMW_ENTIRE) {
2136       retval = make_filename_r(NULL, NULL, NULL, ment->filename, "", myrank,
2137                                flag_rank, fname, HECMW_FILENAME_LEN);
2138 
2139     } else {
2140       if (subdir_on && nrank > nlimit) {
2141         irank = myrank / nlimit;
2142         sprintf(prefix, "TRUNK%d", irank);
2143         retval = make_filename_r("MESH", NULL, prefix, ment->filename, "", myrank,
2144                                  flag_rank, fname, HECMW_FILENAME_LEN);
2145 
2146       } else if (subdir_on && ment->type == HECMW_CTRL_FTYPE_HECMW_DIST) {
2147         retval = make_filename_r("MESH", NULL, NULL, ment->filename, "", myrank,
2148                                  flag_rank, fname, HECMW_FILENAME_LEN);
2149 
2150       } else if (subdir_on && nrank > 1) {
2151         retval = make_filename_r("MESH", NULL, NULL, ment->filename, "", myrank,
2152                                  flag_rank, fname, HECMW_FILENAME_LEN);
2153 
2154       } else {
2155         retval = make_filename_r(NULL, NULL, NULL, ment->filename, "", myrank,
2156                                  flag_rank, fname, HECMW_FILENAME_LEN);
2157       }
2158     }
2159 
2160     if (retval == NULL) {
2161       HECMW_set_error(HECMW_IO_E0002, "Cannot create mesh filename");
2162       HECMW_free(fname);
2163       return NULL;
2164     }
2165 
2166     file->filename = fname;
2167   }
2168 
2169   return files;
2170 }
2171 
get_meshfiles(char * name_ID,int n_rank,int i_rank,int flag_rank_none)2172 static struct hecmw_ctrl_meshfiles *get_meshfiles(char *name_ID, int n_rank,
2173                                                   int i_rank,
2174                                                   int flag_rank_none) {
2175   struct mesh_entry *mesh;
2176   struct mesh_grp_entry *mesh_grp;
2177   struct hecmw_ctrl_meshfiles *files = NULL;
2178   mesh_grp                           = get_mesh_grp_entry(name_ID);
2179 
2180   if (mesh_grp) {
2181     files = make_meshfiles_struct(mesh_grp->n_mesh, mesh_grp->mesh, n_rank,
2182                                   i_rank, flag_rank_none);
2183 
2184     if (files == NULL) return NULL;
2185   }
2186 
2187   if (files == NULL) {
2188     mesh = get_mesh_entry(name_ID);
2189 
2190     if (mesh) {
2191       files = make_meshfiles_struct(1, &mesh, n_rank, i_rank, flag_rank_none);
2192 
2193       if (files == NULL) return NULL;
2194     }
2195   }
2196 
2197   if (files == NULL) {
2198     HECMW_set_error(HECMW_UTIL_E0014, "NAME: %s", name_ID);
2199     return NULL;
2200   }
2201 
2202   return files;
2203 }
2204 
HECMW_ctrl_get_meshfiles(char * name_ID)2205 struct hecmw_ctrl_meshfiles *HECMW_ctrl_get_meshfiles(char *name_ID) {
2206   return get_meshfiles(name_ID, 0, 0, 0);
2207 }
2208 
HECMW_ctrl_get_meshfiles_header(char * name_ID)2209 struct hecmw_ctrl_meshfiles *HECMW_ctrl_get_meshfiles_header(char *name_ID) {
2210   return get_meshfiles(name_ID, 0, 0, 1);
2211 }
2212 
HECMW_ctrl_get_meshfiles_sub(char * name_ID,int n_rank,int i_rank)2213 struct hecmw_ctrl_meshfiles *HECMW_ctrl_get_meshfiles_sub(char *name_ID,
2214                                                           int n_rank,
2215                                                           int i_rank) {
2216   return get_meshfiles(name_ID, n_rank, i_rank, 0);
2217 }
2218 
HECMW_ctrl_get_meshfiles_header_sub(char * name_ID,int n_rank,int i_rank)2219 struct hecmw_ctrl_meshfiles *HECMW_ctrl_get_meshfiles_header_sub(char *name_ID,
2220                                                                  int n_rank,
2221                                                                  int i_rank) {
2222   return get_meshfiles(name_ID, n_rank, i_rank, 1);
2223 }
2224 
get_result_file(char * name_ID,int istep,int n_rank,int i_rank,int * fg_text,int flag_rank_none)2225 static char *get_result_file(char *name_ID, int istep, int n_rank,
2226                              int i_rank, int *fg_text, int flag_rank_none) {
2227   int nrank, myrank, irank;
2228   char *fname, *retfname;
2229   struct result_entry *result;
2230   char subname[10], prefix[10];
2231   result = get_result_entry(name_ID);
2232 
2233   if (result == NULL) {
2234     HECMW_set_error(HECMW_UTIL_E0024, "NAME: %s",
2235                     name_ID ? name_ID : "Not specified");
2236     return NULL;
2237   }
2238 
2239   if (n_rank == 0) {
2240     nrank  = HECMW_comm_get_size();
2241     myrank = HECMW_comm_get_rank();
2242 
2243   } else {
2244     nrank  = n_rank;
2245     myrank = i_rank;
2246   }
2247 
2248   if (subdir_on && !strcmp(name_ID, "vis_out")) {
2249     fname = make_filename(name_ID, NULL, NULL, result->filename, "", myrank,
2250                           flag_rank_none);
2251 
2252   } else if (subdir_on && nrank > nlimit) {
2253     sprintf(subname, "STEP%d", istep);
2254     irank = myrank / nlimit;
2255     sprintf(prefix, "TRUNK%d", irank);
2256     fname = make_filename(name_ID, subname, prefix, result->filename, "",
2257                           myrank, flag_rank_none);
2258 
2259   } else if (subdir_on) {
2260     sprintf(subname, "STEP%d", istep);
2261     fname = make_filename(name_ID, subname, NULL, result->filename, "", myrank,
2262                           flag_rank_none);
2263 
2264   } else {
2265     fname = make_filename(NULL, NULL, NULL, result->filename, "", myrank,
2266                           flag_rank_none);
2267   }
2268 
2269   if (fname == NULL) {
2270     HECMW_set_error(HECMW_IO_E0002, "Cannot create result filename");
2271     return NULL;
2272   }
2273 
2274   retfname = HECMW_strdup(fname);
2275 
2276   if (retfname == NULL) {
2277     HECMW_set_error(errno, "");
2278     return NULL;
2279   }
2280 
2281   *fg_text = result->fg_text;
2282   return retfname;
2283 }
2284 
get_filename_body(char * file)2285 static char *get_filename_body(char *file) {
2286   static char filename[HECMW_FILENAME_LEN+1];
2287   strcpy(filename, "");
2288   strcat(filename, file);
2289   return filename;
2290 }
2291 
get_result_filebody(char * name_ID)2292 static char *get_result_filebody(char *name_ID) {
2293   struct result_entry *result;
2294   char *fname, *retfname;
2295 
2296   result = get_result_entry(name_ID);
2297 
2298   if (result == NULL) {
2299     HECMW_set_error(HECMW_UTIL_E0024, "NAME: %s",
2300                     name_ID ? name_ID : "Not specified");
2301     return NULL;
2302   }
2303 
2304   fname = get_filename_body(result->filename);
2305 
2306   retfname = HECMW_strdup(fname);
2307 
2308   if (retfname == NULL) {
2309     HECMW_set_error(errno, "");
2310     return NULL;
2311   }
2312 
2313   return retfname;
2314 }
2315 
HECMW_ctrl_get_result_file(char * name_ID,int istep,int * fg_text)2316 char *HECMW_ctrl_get_result_file(char *name_ID, int istep,
2317                                  int *fg_text) {
2318   return get_result_file(name_ID, istep, 0, 0, fg_text, 1);
2319 }
2320 
HECMW_ctrl_get_result_fileheader(char * name_ID,int istep,int * fg_text)2321 char *HECMW_ctrl_get_result_fileheader(char *name_ID, int istep,
2322                                        int *fg_text) {
2323   return get_result_file(name_ID, istep, 0, 0, fg_text, 0);
2324 }
2325 
HECMW_ctrl_get_result_file_sub(char * name_ID,int istep,int n_rank,int i_rank,int * fg_text)2326 char *HECMW_ctrl_get_result_file_sub(char *name_ID, int istep,
2327                                      int n_rank, int i_rank, int *fg_text) {
2328   return get_result_file(name_ID, istep, n_rank, i_rank, fg_text, 1);
2329 }
2330 
HECMW_ctrl_get_result_fileheader_sub(char * name_ID,int istep,int n_rank,int i_rank,int * fg_text)2331 char *HECMW_ctrl_get_result_fileheader_sub(char *name_ID, int istep,
2332                                            int n_rank, int i_rank,
2333                                            int *fg_text) {
2334   return get_result_file(name_ID, istep, n_rank, i_rank, fg_text, 0);
2335 }
2336 
HECMW_ctrl_get_result_filebody(char * name_ID)2337 char *HECMW_ctrl_get_result_filebody(char *name_ID) {
2338   return get_result_filebody(name_ID);
2339 }
2340 
HECMW_ctrl_get_restart_file(char * name_ID)2341 char *HECMW_ctrl_get_restart_file(char *name_ID) {
2342   int nrank, myrank, irank;
2343   char *fname, *retfname;
2344   struct restart_entry *restart;
2345   char prefix[10];
2346   restart = get_restart_entry(name_ID);
2347 
2348   if (restart == NULL) {
2349     HECMW_set_error(HECMW_UTIL_E0044, "NAME: %s",
2350                     name_ID ? name_ID : "Not specified");
2351     return NULL;
2352   }
2353 
2354   nrank  = HECMW_comm_get_size();
2355   myrank = HECMW_comm_get_rank();
2356 
2357   if (subdir_on && nrank > nlimit) {
2358     irank = myrank / nlimit;
2359     sprintf(prefix, "TRUNK%d", irank);
2360     fname =
2361         make_filename(name_ID, NULL, prefix, restart->filename, "", myrank, 1);
2362 
2363   } else if (subdir_on) {
2364     fname =
2365         make_filename(name_ID, NULL, NULL, restart->filename, "", myrank, 1);
2366 
2367   } else {
2368     fname = make_filename(NULL, NULL, NULL, restart->filename, "", myrank, 1);
2369   }
2370 
2371   if (fname == NULL) {
2372     HECMW_set_error(HECMW_IO_E0002, "Cannot create restart filename");
2373     return NULL;
2374   }
2375 
2376   retfname = HECMW_strdup(fname);
2377 
2378   if (retfname == NULL) {
2379     HECMW_set_error(errno, "");
2380     return NULL;
2381   }
2382 
2383   return retfname;
2384 }
2385 
HECMW_ctrl_get_restart_file_by_io(int io)2386 char *HECMW_ctrl_get_restart_file_by_io(int io) {
2387   int nrank, myrank, irank;
2388   char *fname, *retfname;
2389   struct restart_entry *p;
2390   char prefix[10];
2391   p = get_restart_entry_by_io(io);
2392 
2393   if (p == NULL) {
2394     HECMW_set_error(HECMW_UTIL_E0045, "");
2395     return NULL;
2396   }
2397 
2398   nrank  = HECMW_comm_get_size();
2399   myrank = HECMW_comm_get_rank();
2400 
2401   if (subdir_on && nrank > nlimit) {
2402     irank = myrank / nlimit;
2403     sprintf(prefix, "TRUNK%d", irank);
2404     fname = make_filename(p->name_ID, NULL, prefix, p->filename, "", myrank, 1);
2405 
2406   } else if (subdir_on) {
2407     fname = make_filename(p->name_ID, NULL, NULL, p->filename, "", myrank, 1);
2408 
2409   } else {
2410     fname = make_filename(NULL, NULL, NULL, p->filename, "", myrank, 1);
2411   }
2412 
2413   if (fname == NULL) {
2414     HECMW_set_error(HECMW_IO_E0002, "Cannot create restart filename");
2415     return NULL;
2416   }
2417 
2418   retfname = HECMW_strdup(fname);
2419 
2420   if (retfname == NULL) {
2421     HECMW_set_error(errno, "");
2422     return NULL;
2423   }
2424 
2425   return retfname;
2426 }
2427 
HECMW_ctrl_get_control_file(char * name_ID)2428 char *HECMW_ctrl_get_control_file(char *name_ID) {
2429   char *fname;
2430   struct ctrl_entry *ctrl;
2431   ctrl = get_ctrl_entry(name_ID);
2432 
2433   if (ctrl == NULL) {
2434     HECMW_set_error(HECMW_UTIL_E0033, "NAME: %s",
2435                     name_ID ? name_ID : "Not specified");
2436     return NULL;
2437   }
2438 
2439   fname = HECMW_strdup(ctrl->filename);
2440   return fname;
2441 }
2442 
HECMW_ctrl_is_exists_control(char * name_ID)2443 int HECMW_ctrl_is_exists_control(char *name_ID) {
2444   return get_ctrl_entry(name_ID) ? 1 : 0;
2445 }
2446 
HECMW_ctrl_make_subdir(char * filename)2447 int HECMW_ctrl_make_subdir(char *filename) {
2448   char fname[HECMW_FILENAME_LEN + 1];
2449   char dirname[HECMW_FILENAME_LEN + 1];
2450   char *token;
2451   char separator[10];
2452   char *saveptr;
2453   mode_t mode;
2454   DIR *dp;
2455 #ifndef _WINDOWS
2456   mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
2457 #endif
2458   strcpy(fname, filename);
2459   sprintf(separator, "%c", HECMW_get_path_separator());
2460 #if defined(__WIN32__) || defined(__WIN64__)
2461   /* strtok is thread-safe on Windows */
2462   token = strtok(fname, separator);
2463   sprintf(dirname, "%s", token);
2464   token = strtok(NULL, separator);
2465 #else
2466   token = strtok_r(fname, separator, &saveptr);
2467   sprintf(dirname, "%s", token);
2468   token = strtok_r(NULL, separator, &saveptr);
2469 #endif
2470 
2471   while (token) {
2472     if ((dp = opendir(dirname)) == NULL) {
2473 #ifndef _WINDOWS
2474 
2475       if (mkdir(dirname, mode) != 0) {
2476 #else
2477 
2478       if (mkdir(dirname) != 0) {
2479 #endif
2480 
2481         if (errno != EEXIST) return -1;
2482       }
2483 
2484     } else {
2485       closedir(dp);
2486     }
2487 
2488     strcat(dirname, separator);
2489     strcat(dirname, token);
2490 #if defined(__WIN32__) || defined(__WIN64__)
2491     token = strtok(NULL, separator);
2492 #else
2493     token = strtok_r(NULL, separator, &saveptr);
2494 #endif
2495   }
2496 
2497   return 0;
2498 }
2499 
2500 int HECMW_ctrl_is_subdir(void) { return subdir_on; }
2501 
2502 /*---------------------------------------------------------------------------*/
2503 
2504 void hecmw_ctrl_init_if(int *err) {
2505   *err = 1;
2506 
2507   if (HECMW_ctrl_init()) return;
2508 
2509   *err = 0;
2510 }
2511 
2512 void hecmw_ctrl_init_if_(int *err) { hecmw_ctrl_init_if(err); }
2513 
2514 void hecmw_ctrl_init_if__(int *err) { hecmw_ctrl_init_if(err); }
2515 
2516 void HECMW_CTRL_INIT_IF(int *err) { hecmw_ctrl_init_if(err); }
2517 
2518 /*---------------------------------------------------------------------------*/
2519 
2520 void hecmw_ctrl_init_ex_if(char *ctrlfile, int *err, int len) {
2521   char c_ctrlfile[HECMW_FILENAME_LEN + 1];
2522   *err = 1;
2523 
2524   if (HECMW_strcpy_f2c_r(ctrlfile, len, c_ctrlfile, sizeof(c_ctrlfile)) == NULL)
2525     return;
2526 
2527   if (HECMW_ctrl_init_ex(c_ctrlfile)) return;
2528 
2529   *err = 0;
2530 }
2531 
2532 void hecmw_ctrl_init_ex_if_(char *ctrlfile, int *err, int len) {
2533   hecmw_ctrl_init_ex_if(ctrlfile, err, len);
2534 }
2535 
2536 void hecmw_ctrl_init_ex_if__(char *ctrlfile, int *err, int len) {
2537   hecmw_ctrl_init_ex_if(ctrlfile, err, len);
2538 }
2539 
2540 void HECMW_CTRL_INIT_EX_IF(char *ctrlfile, int *err, int len) {
2541   hecmw_ctrl_init_ex_if(ctrlfile, err, len);
2542 }
2543 
2544 /*---------------------------------------------------------------------------*/
2545 
2546 void hecmw_ctrl_finalize_if(void) { HECMW_ctrl_finalize(); }
2547 
2548 void hecmw_ctrl_finalize_if_(void) { hecmw_ctrl_finalize_if(); }
2549 
2550 void hecmw_ctrl_finalize_if__(void) { hecmw_ctrl_finalize_if(); }
2551 
2552 void HECMW_CTRL_FINALIZE_IF(void) { hecmw_ctrl_finalize_if(); }
2553 
2554 /*---------------------------------------------------------------------------*/
2555 
2556 void hecmw_ctrl_get_control_file_if(char *name_ID, char *buf, int *err,
2557                                     int name_len, int buf_len) {
2558   char c_name_ID[HECMW_NAME_LEN + 1];
2559   char *c_buf;
2560   int ret;
2561   *err = 1;
2562 
2563   if (HECMW_strcpy_f2c_r(name_ID, name_len, c_name_ID, sizeof(c_name_ID)) ==
2564       NULL)
2565     return;
2566 
2567   if ((c_buf = HECMW_ctrl_get_control_file(c_name_ID)) == NULL) return;
2568 
2569   ret = HECMW_strcpy_c2f(c_buf, buf, buf_len);
2570   HECMW_free(c_buf);
2571 
2572   if (ret == 0) return;
2573 
2574   *err = 0;
2575 }
2576 
2577 void hecmw_ctrl_get_control_file_if_(char *name_ID, char *buf, int *err,
2578                                      int name_len, int buf_len) {
2579   hecmw_ctrl_get_control_file_if(name_ID, buf, err, name_len, buf_len);
2580 }
2581 
2582 void hecmw_ctrl_get_control_file_if__(char *name_ID, char *buf, int *err,
2583                                       int name_len, int buf_len) {
2584   hecmw_ctrl_get_control_file_if(name_ID, buf, err, name_len, buf_len);
2585 }
2586 
2587 void HECMW_CTRL_GET_CONTROL_FILE_IF(char *name_ID, char *buf, int *err,
2588                                     int name_len, int buf_len) {
2589   hecmw_ctrl_get_control_file_if(name_ID, buf, err, name_len, buf_len);
2590 }
2591 
2592 /*---------------------------------------------------------------------------*/
2593 
2594 void hecmw_ctrl_make_subdir(char *filename, int *err, int len) {
2595   char fname[HECMW_FILENAME_LEN + 1];
2596   *err = 1;
2597 
2598   if (HECMW_strcpy_f2c_r(filename, len, fname, sizeof(fname)) == NULL) return;
2599 
2600   if (HECMW_ctrl_make_subdir(fname) != 0) return;
2601 
2602   *err = 0;
2603 }
2604 
2605 void hecmw_ctrl_make_subdir_(char *filename, int *err, int len) {
2606   hecmw_ctrl_make_subdir(filename, err, len);
2607 }
2608 
2609 void hecmw_ctrl_make_subdir__(char *filename, int *err, int len) {
2610   hecmw_ctrl_make_subdir(filename, err, len);
2611 }
2612 
2613 void HECMW_CTRL_MAKE_SUBDIR(char *filename, int *err, int len) {
2614   hecmw_ctrl_make_subdir(filename, err, len);
2615 }
2616 
2617 /*---------------------------------------------------------------------------*/
2618 
2619 void hecmw_ctrl_is_subdir(int *flag, int *limit) {
2620   *flag  = subdir_on;
2621   *limit = nlimit;
2622 }
2623 
2624 void hecmw_ctrl_is_subdir_(int *flag, int *limit) {
2625   hecmw_ctrl_is_subdir(flag, limit);
2626 }
2627 
2628 void hecmw_ctrl_is_subdir__(int *flag, int *limit) {
2629   hecmw_ctrl_is_subdir(flag, limit);
2630 }
2631 
2632 void HECMW_CTRL_IS_SUBDIR(int *flag, int *limit) {
2633   hecmw_ctrl_is_subdir(flag, limit);
2634 }
2635