SURFEX v8.1
General documentation of Surfex
lfi_altm.c
Go to the documentation of this file.
1 /**** *lfi_altm.c* - Multi-file LFI layer.
2  *
3  * Author.
4  * -------
5  * Philippe Marguinaud *METEO-FRANCE*
6  * Original : 12-08-2013
7  *
8  * Description :
9  * This LFI library is based on lfi_alts and is able to handle multiple files.
10  */
11 #include <stdlib.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <unistd.h>
17 #include <errno.h>
18 
19 #include "lfi_type.h"
20 #include "lfi_altm.h"
21 #include "lfi_dumm.h"
22 #include "lfi_miss.h"
23 #include "lfi_abor.h"
24 #include "lfi_grok.h"
25 #include "lfi_hndl.h"
26 #include "lfi_alts.h"
27 #include "lfi_verb.h"
28 #include "lfi_fmul.h"
29 #include "lfi_util.h"
30 
31 #include "drhook.h"
32 
33 /* Ancillary macros; the article name length is defined here */
34 
35 #define ARTNLEN 16
36 #define minARTN(x) ((x) > ARTNLEN ? ARTNLEN : (x))
37 
38 #define eqan(a,b) (strncmp ((a), (b), ARTNLEN) == 0)
39 #define neqan(a,b) (!eqan(a,b))
40 
41 /* Name of a hole in the index */
42 static const char *
44 ;
45 
46 /* Sub-file descriptor */
47 typedef struct lfi_altm_fh_fidx_t
48 {
49  lfi_hndl_t * als; /* LFI handle associated to this file */
50  const char * cnomf; /* File name */
51  integer64 inumer; /* File unit */
52  int dead; /* File is empty (and may have been removed) */
53 }
55 
56 /* Article descriptor */
57 typedef struct lfi_altm_fh_aidx_t
58 {
59  character name[ARTNLEN]; /* Article name */
60  character namf[ARTNLEN]; /* Article name in LFI file */
61  integer64 ifh; /* File rank; refers to a lfi_altm_fh_fidx_t
62  * struct in the file index */
63 }
65 
66 /* Open unit descriptor */
67 typedef struct lfi_altm_fh_t
68 {
69  struct lfi_altm_fh_t * next;
70 
71  integer64 inumer; /* File unit */
72  const char * cnomf; /* File name */
73  const char * cstto; /* File status (Fortran) */
74  integer64 inimes; /* Message level */
75  logical llerfa; /* All errors are fatal */
76  int nfidx; /* Number of LFI files opened */
77  lfi_altm_fh_fidx_t * fidx; /* LFI handles */
78  int naidx; /* Number of articles */
79  lfi_altm_fh_aidx_t * aidx; /* Articles descriptors */
80  int iart; /* Current article rank */
81  int modified; /* File was modified */
82  integer64 ifh_w; /* File index to write to */
83  integer64 fmult; /* Facteur multiplicatif */
84  int unlink; /* Unlink unreferenced sub-files */
85  int rmdir; /* Remove directory of sub-files when empty */
86 }
88 
89 /* LFI library descriptor */
90 typedef struct lfi_altm_t
91 {
92  char cmagic[8];
93  lfi_altm_fh_t * fh; /* File descriptors list */
94  integer64 fmult; /* Facteur multiplicatif */
95  lfi_fmul_t * fmult_list; /* Predefined "facteurs multiplicatifs" */
96  int maxartals; /* Maximum number of articles per sub-file */
97  int nerfag; /* Erreurs fatales */
98  int inivau; /* Niveau global des messages */
99  int iulout; /* Unite Fortran pour impression des messages */
100 }
101 lfi_altm_t;
102 
103 /* Find a suitable name for a sub-file; this name is based on main file name */
104 static const char * getfname (const char * cnomf)
105 {
106  int cnomf_len = strlen (cnomf);
107  char cnomfy[cnomf_len+20];
108  int i;
109 
110  /* Look for a suitable name */
111 
112  strcpy (cnomfy, cnomf);
113  strcat (cnomfy, ".d");
114 
115  if (lfi_mkdir (cnomfy) < 0)
116  lfi_abor ("Cannot mkdir `%s'", cnomfy);
117 
118  for (i = 0; ; i++)
119  {
120  struct stat st;
121  sprintf (cnomfy+cnomf_len+2, "/%6.6d", i);
122  if (stat (cnomfy, &st) < 0)
123  break;
124  }
125 
126  return strdup (cnomfy);
127 }
128 
129 /* Cast and check opaque void * in a lfi_altm_t pointer */
130 static lfi_altm_t * lookup_alm (void * LFI)
131 {
132  lfi_altm_t * alm = LFI;
133  if (strncmp (alm->cmagic, "lfi_altm", 8))
134  lfi_abor ("Corrupted descriptor");
135  return alm;
136 }
137 
138 /* Find unit descriptor by unit number */
139 static lfi_altm_fh_t * lookup_fh (lfi_altm_t * alm, integer64 * KNUMER, int fatal)
140 {
141  lfi_altm_fh_t * fh;
142  for (fh = alm->fh; fh; fh = fh->next)
143  if (fh->inumer == *KNUMER)
144  return fh;
145  if (fatal)
146  lfi_abor ("File number `%lld' is not opened", *KNUMER);
147  return NULL;
148 }
149 
150 /* Look for next/previous article in the index */
151 static int seek_rc (lfi_altm_fh_t * fh, int d)
152 {
153  int iart = fh->iart;
154  d = d >= 0 ? +1 : -1;
155 
156  if ((d < 0) && (iart < 0))
157  iart = fh->naidx;
158 
159  while (1)
160  {
161  iart = iart + d;
162  if ((iart >= fh->naidx) || (iart < 0))
163  goto ko;
164  if (neqan (fh->aidx[iart].name, blank_index))
165  goto ok;
166  }
167 
168  return 0;
169 ko:
170  return -1;
171 ok:
172  return iart;
173 }
174 
175 /* Check article name length */
176 static int check_an_len (const char * CDNOMA, const character_len CDNOMA_len)
177 {
178  int len = lfi_fstrlen (CDNOMA, CDNOMA_len);
179  return len > ARTNLEN ? 0 : 1;
180 }
181 
182 /* Check whether article name is valid */
183 static int check_an (const char * CDNOMA, const character_len CDNOMA_len)
184 {
185  int len;
186  if (! check_an_len (CDNOMA, CDNOMA_len))
187  return 0;
188  len = minARTN (CDNOMA_len);
189  return strncmp (CDNOMA, blank_index, len);
190 }
191 
192 /* Search article by name */
193 static int lookup_rc (lfi_altm_fh_t * fh, character * name, character_len name_len)
194 {
195  char _name[ARTNLEN];
196  int iart;
197 
198  if (! check_an_len (name, name_len))
199  return -15;
200 
201  memset (_name, ' ', ARTNLEN);
202  memcpy (_name, name, minARTN (name_len));
203 
204  /* Look around current article */
205  if (fh->iart >= 0)
206  {
207  const int da = 1;
208  int iart1 = fh->iart-da > 0 ? fh->iart-da : 0;
209  int iart2 = fh->iart+da < fh->naidx ? fh->iart+da : fh->naidx;
210  for (iart = iart1; iart < iart2; iart++)
211  if (eqan (_name, fh->aidx[iart].name))
212  return iart;
213  }
214 
215  for (iart = 0; iart < fh->naidx; iart++)
216  if (eqan (_name, fh->aidx[iart].name))
217  return iart;
218 
219  return -20;
220 }
221 
222 
223 /* Write file header; this is an ASCII file */
225 {
226  integer64 ifh, len;
227  integer64 iart, nart;
228  integer64 fh2na[fh->nfidx]; /* Number of articles per file */
229  integer64 fh2ra[fh->nfidx]; /* File reranking map */
230  integer64 rank;
231  FILE * fp;
232 
233  errno = 0;
234  fp = fopen (fh->cnomf, "w");
235 
236  if (fp == NULL)
237  lfi_abor ("Cannot open `%s' for writing", fh->cnomf);
238 
239  /* File name max len */
240 
241  for (len = 0, ifh = 0; ifh < fh->nfidx; ifh++)
242  len = len < strlen (fh->fidx[ifh].cnomf) ? strlen (fh->fidx[ifh].cnomf) : len;
243 
244  /* Number of articles per file */
245 
246  for (ifh = 0; ifh < fh->nfidx; ifh++)
247  fh2na[ifh] = 0;
248 
249  for (iart = 0; iart < fh->naidx; iart++)
250  if (neqan (blank_index, fh->aidx[iart].name))
251  fh2na[fh->aidx[iart].ifh]++;
252 
253  /* Compute files ranks */
254 
255  for (rank = 0, ifh = 0; ifh < fh->nfidx; ifh++)
256  if (fh2na[ifh] > 0)
257  fh2ra[ifh] = rank++;
258  else
259  fh2ra[ifh] = -1;
260 
261  if (fprintf (fp, "LFI_ALTM\n") != 9)
262  goto write_err;
263 
264  /* Number of files, file name max length */
265  fprintf (fp, "%lld %lld\n", rank, len);
266 
267  /* Print file list */
268  for (ifh = 0; ifh < fh->nfidx; ifh++)
269  /* Skip files when no article is referenced */
270  if (fh2ra[ifh] >= 0)
271  {
272  const char * cnomf = fh->fidx[ifh].cnomf;
273  if (fprintf (fp, "%s\n", cnomf) != strlen (cnomf) + 1)
274  goto write_err;
275  }
276  else if (fh->unlink && (! fh->fidx[ifh].dead))
277  /* Unlink unreferenced files */
278  {
279  const char * cnomf = fh->fidx[ifh].cnomf;
280  if (unlink (cnomf) < 0)
281  lfi_abor ("Cannot unlink `%s'", cnomf);
282  if (fh->rmdir)
283  {
284  const char * dir = lfi_dirname (cnomf);
285  lfi_rmdir (dir);
286  free ((void *)dir);
287  }
288  fh->fidx[ifh].dead = 1;
289  }
290 
291  for (nart = 0, iart = 0; iart < fh->naidx; iart++)
292  if (neqan (blank_index, fh->aidx[iart].name))
293  nart++;
294 
295  /* Number of articles, article name length */
296  fprintf (fp, "%lld %d\n", nart, ARTNLEN);
297 
298  /* Print article names */
299  for (iart = 0; iart < fh->naidx; iart++)
300  {
301  if (eqan (fh->aidx[iart].name, blank_index))
302  continue;
303 
304  ifh = fh->aidx[iart].ifh;
305 
306  fprintf (fp, "%lld ", fh2ra[ifh]);
307 
308  /* Article name is the same in sub-file */
309  if (eqan (fh->aidx[iart].name, fh->aidx[iart].namf))
310  {
311  if (fprintf (fp, "%-16.16s ", fh->aidx[iart].name) != 17)
312  goto write_err;
313  }
314  /* Article name is different in sub-file; write its name in sub-file */
315  else
316  {
317  if (fprintf (fp, "%-16.16s.%-16.16s ", fh->aidx[iart].name, fh->aidx[iart].namf) != 34)
318  goto write_err;
319  }
320  if (fh2ra[ifh] < 0)
321  lfi_abor ("Internal error; unexpected negative file rank");
322  if (fprintf (fp, "\n") != 1)
323  goto write_err;
324  }
325 
326  if (fclose (fp) != 0)
327  goto close_err;
328 
329  *KREP = 0;
330 
331  return;
332 
333 write_err:
334 
335  lfi_abor ("Cannot write to `%s'", fh->cnomf);
336 
337 close_err:
338 
339  lfi_abor ("Cannot close `%s'", fh->cnomf);
340 
341 }
342 
343 /* Mark file as modified */
344 static void fh_modified (lfi_altm_fh_t * fh)
345 {
346  integer64 IREP;
347 
348  if (fh->modified)
349  return;
350 
351  fh->modified = 1;
352 
353  fh_write_hdr (fh, &IREP);
354 }
355 
356 /* Get a new sub-file handle for writing;
357  * this sub-file descriptor is returned by value, and be used in a limited scope */
359 {
360  lfi_altm_fh_fidx_t fhw;
361 
362  /* If a file is already open, then return it */
363  if ((! new) && (fh->ifh_w >= 0))
364  {
365  fhw = fh->fidx[fh->ifh_w];
366  return fhw;
367  }
368 
369  /* Reallocate file handle index */
370 
371  fh->fidx = (lfi_altm_fh_fidx_t *)realloc (fh->fidx, (fh->nfidx + 1) * sizeof (lfi_altm_fh_fidx_t));
372  fh->ifh_w = fh->nfidx;
373  fh->nfidx = fh->nfidx + 1;
374 
375 
376  /* Initialize & open new file handle */
377 
378  fh->fidx[fh->ifh_w].als = lfi_get_alts_hndl (NULL);
379  fh->fidx[fh->ifh_w].inumer = fh->inumer;
380  fh->fidx[fh->ifh_w].cnomf = getfname (fh->cnomf);
381  fh->fidx[fh->ifh_w].dead = 0;
382 
383  fhw = fh->fidx[fh->ifh_w];
384 
385  /* Open sub-file */
386  {
387  logical LLNOMM = fort_TRUE, LLERFA = fort_FALSE, LLIMST = fort_FALSE;
388  integer64 INIMES = 0, INBARP = 0, INBARI = 0;
389  integer64 INUMER = fhw.inumer;
390  integer64 IREP;
391  character * CLSTTO = (character *)"NEW";
392  character * CLNOMF = (character *)fhw.cnomf;
393 
394  fhw.als->cb->lfifmd (fhw.als->data, &fh->fmult);
395 
396  fhw.als->cb->lfiouv (fhw.als->data, &IREP, &INUMER, &LLNOMM, CLNOMF, CLSTTO, &LLERFA, &LLIMST, &INIMES, &INBARP, &INBARI,
397  strlen (CLNOMF), strlen (CLSTTO));
398  if (IREP != 0)
399  lfi_abor ("Failed to open `%s' for writing", CLNOMF);
400  }
401 
402  return fhw;
403 }
404 
405 static void fh_set_filename (lfi_altm_fh_t * fh, character * CDNOMF, character_len CDNOMF_len)
406 {
407  if (fh->cnomf != NULL)
408  free ((void *)fh->cnomf);
409 
410  fh->cnomf = lfi_fstrdup (CDNOMF, CDNOMF_len, NULL);
411 }
412 
413 static const char * resolve_filename (const char * base, const char * filename, int filename_len, char * path)
414 {
415  LFI_CSTR (_file, filename);
416  int base_len = strlen (base);
417 
418  if (path == NULL)
419  path = (char *)malloc (base_len + filename_len + 10);
420 
421  if (_file[0] != '/')
422  {
423  int i;
424  strcpy (path, base);
425  for (i = base_len-1; i >= 0; i--)
426  if (path[i] == '/')
427  break;
428  path[i+1] = '\0';
429  strcat (path, _file);
430  }
431  else
432  {
433  strcpy (path, _file);
434  }
435 
436  lfi_cleanup_path (path);
437 
438  return path;
439 }
440 
441 
442 static lfi_hndl_t * _getfhr (const char * base, character * CDNOMF, integer64 * KNUMER, character_len CDNOMF_len)
443 {
444  integer64 IREP, INIMES = 0, INBARP = 0, INBARI = 0;
445  logical LLNOMM = fort_TRUE, LLERFA = fort_FALSE, LLIMST = fort_FALSE;
446  character * CLSTTO = (character *)"OLD";
447  lfi_hndl_t * als = lfi_get_alts_hndl (NULL);
448  const char * cnomf = resolve_filename (base, CDNOMF, CDNOMF_len, NULL);
449 
450  als->cb->lfiouv (als->data, &IREP, KNUMER, &LLNOMM, cnomf, CLSTTO, &LLERFA, &LLIMST, &INIMES, &INBARP, &INBARI,
451  strlen (cnomf), strlen (CLSTTO));
452 
453  if (IREP != 0)
454  {
455  lfi_abor ("Failed to open `%s' for reading", cnomf);
456  }
457 
458  free ((void *)cnomf);
459 
460  return als;
461 }
462 
463 /* Get a file descriptor for file of rank ifh;
464  * the object is returned by value and should be used in a limited scope
465  * this routine has to be THREAD-SAFE */
467 {
468  lfi_altm_fh_fidx_t fhr;
469 
470  if (ifh < 0)
471  {
472  memset (&fhr, 0, sizeof (fhr));
473  return fhr;
474  }
475 
476  /* Open sub-file */
477  if (fh->fidx[ifh].als == NULL)
478  {
479  character * CLNOMF = (character *)fh->fidx[ifh].cnomf;
480  character_len CLNOMF_len = strlen (CLNOMF);
481  integer64 * INUMER = &fh->fidx[ifh].inumer;
482  fh->fidx[ifh].als = _getfhr (fh->cnomf, CLNOMF, INUMER, CLNOMF_len);
483  }
484 
485  return fh->fidx[ifh];
486 }
487 
488 #define ALM_DECL \
489  lfi_altm_t * alm = lookup_alm (LFI);
490 #define FH_DECL(fatal) \
491  lfi_altm_fh_t * fh = lookup_fh (alm, KNUMER, fatal);
492 #define ART_DECL \
493  int iart = lookup_rc (fh, CDNOMA, CDNOMA_len); \
494  integer64 ifh = iart < 0 ? -1 : fh->aidx[iart].ifh; \
495  lfi_altm_fh_fidx_t fhr = getfhr (fh, ifh);
496 
497 /* Allocate and initialize a new file descriptor */
498 static lfi_altm_fh_t * fh_new (LFIOUV_ARGS_DECL)
499 {
500  ALM_DECL;
501  lfi_altm_fh_t * fh;
502 
503  *KREP = 0;
504  *KNBARI = 0;
505 
506  if (*KNUMER == 0)
507  {
508  integer64 inumer = -2000000;
509  lfi_altm_fh_t * fh;
510 again:
511  for (fh = alm->fh; fh; fh = fh->next)
512  if (fh->inumer == inumer)
513  {
514  inumer--;
515  goto again;
516  }
517  *KNUMER = inumer;
518  }
519 
520  fh = (lfi_altm_fh_t *)malloc (sizeof (lfi_altm_fh_t));
521  memset (fh, '\0', sizeof (lfi_altm_fh_t));
522  fh->next = NULL;
523  fh->inumer = *KNUMER;
524  fh->inimes = *KNIMES;
525  fh->llerfa = *LDERFA;
526  fh->cstto = lfi_fstrdup (CDSTTO, CDSTTO_len, NULL);
527  fh->iart = -1;
528  fh->ifh_w = -1;
529  fh->fmult = alm->fmult;
530  fh->unlink = 1;
531  fh->rmdir = 1;
532  fh_set_filename (fh, CDNOMF, CDNOMF_len);
533  lfi_fmul_get (alm->fmult_list, KNUMER, &fh->fmult);
534 
535 
536  return fh;
537 }
538 
539 /* Open a LFI_ALTM file; do not register it in the LFI handle */
540 static lfi_altm_fh_t * lfiouv_mult (LFIOUV_ARGS_DECL)
541 {
542  integer64 ifh, len;
543  integer64 iart, artnlen;
544  FILE * fp = NULL;
545  char cmagic[9];
546  lfi_altm_fh_t * fh = fh_new (LFIOUV_ARGS_LIST);
547 
548  errno = 0;
549 
550  fp = fopen (fh->cnomf, "r");
551 
552  if (fp == NULL)
553  lfi_abor ("Cannot open `%s' for reading", fh->cnomf);
554 
555  if (fscanf (fp, "%8s\n", cmagic) < 0)
556  goto read_err;
557 
558  if (fscanf (fp, "%d %lld\n", &fh->nfidx, &len) != 2)
559  goto read_err;
560 
561  fh->fidx = (lfi_altm_fh_fidx_t *)calloc (sizeof (lfi_altm_fh_fidx_t), fh->nfidx);
562 
563  for (ifh = 0; ifh < fh->nfidx; ifh++)
564  {
565  fh->fidx[ifh].cnomf = (const char *)malloc (len+1);
566  fh->fidx[ifh].inumer = *KNUMER;
567  if (fscanf (fp, "%s\n", (char *)fh->fidx[ifh].cnomf) != 1)
568  goto read_err;
569  }
570 
571  if (fscanf (fp, "%d %lld\n", &fh->naidx, &artnlen) != 2)
572  goto read_err;
573 
574  if (artnlen != ARTNLEN)
575  lfi_abor ("Unexpected article length in unit %lld, `%s'", artnlen, fh->cnomf);
576 
577  fh->aidx = (lfi_altm_fh_aidx_t *)malloc (sizeof (lfi_altm_fh_aidx_t) * fh->naidx);
578 
579  for (iart = 0; iart < fh->naidx; iart++)
580  {
581  char c;
582 
583  if (fscanf (fp, "%lld ", &fh->aidx[iart].ifh) != 1)
584  goto read_err;
585 
586  if (fread (fh->aidx[iart].name, 1, ARTNLEN, fp) != ARTNLEN)
587  goto read_err;
588 
589  if (fread (&c, 1, 1, fp) != 1)
590  goto read_err;
591 
592  if (c != ' ')
593  {
594  if (fread (fh->aidx[iart].namf, 1, ARTNLEN, fp) != ARTNLEN)
595  goto read_err;
596  }
597  else
598  {
599  memcpy (fh->aidx[iart].namf, fh->aidx[iart].name, ARTNLEN);
600  }
601 
602  }
603 
604  if (fclose (fp) != 0)
605  goto close_err;
606 
607  *KNBARI = fh->naidx;
608  *KREP = 0;
609 
610  return fh;
611 
612 read_err:
613 
614  lfi_abor ("Cannot read from `%s'", fh->cnomf);
615 
616 close_err:
617 
618  lfi_abor ("Cannot close `%s'", fh->cnomf);
619 
620  return NULL;
621 }
622 
623 static void lfifer_mult (lfi_altm_fh_t * fh)
624 {
625  int ifh;
626 
627  /* Free all data */
628 
629  for (ifh = 0; ifh < fh->nfidx; ifh++)
630  {
631  if (fh->fidx[ifh].als != NULL)
632  lfi_abor ("Attempt to free LFI_ALTM handle while sub-files are still opened");
633  free ((void *)fh->fidx[ifh].cnomf);
634  }
635 
636  free (fh->fidx);
637  free (fh->aidx);
638  free ((void *)fh->cnomf); /* Avoid warning with (void *) */
639  free ((void *)fh->cstto); /* Avoid warning with (void *) */
640  free (fh);
641 
642 }
643 
644 
646 {
647  int iart;
648  int rmd = 0;
649 
650  for (iart = 0; iart < fh->naidx; iart++)
651  {
652  /* Check if article was read afterwards; if so, blank the last entry */
653  int iartx;
654  for (iartx = iart+1; iartx < fh->naidx; iartx++)
655  if (eqan (fh->aidx[iart].name, fh->aidx[iartx].name))
656  {
657  memcpy (fh->aidx[iartx].name, blank_index, ARTNLEN);
658  rmd++;
659  }
660  }
661 
662  return rmd;
663 }
664 
665 
666 /* Create a new multi-file object from a list of traditional LFI files ;
667  * all arguments have the same meaning as in lfiouv,
668  * except that CDNOMF is a character array of size KNNOMF+1, whose first element is the multi-file name,
669  * and remaining elements are LFI files to take into account */
670 static lfi_altm_fh_t * lfiouv_pure_lfi (void * LFI, integer64 * KREP, integer64 * KNUMER, logical * LDNOMM, character * CDNOMF,
671  integer64 * KNNOMF, character * CDSTTO, logical * LDERFA, logical * LDIMST, integer64 * KNIMES,
672  integer64 * KNBARP, integer64 * KNBARI, character_len CDNOMF_len, character_len CDSTTO_len,
673  int fast)
674 {
675  integer64 ILONG, IPOSEX;
676  logical LLAVAN = fort_TRUE;
677  character CLNOMA[ARTNLEN];
678  integer64 CLNOMA_len = ARTNLEN;
679  int iart, ifh;
680  lfi_altm_fh_t * fh;
681 
682  DRHOOK_START ("lfiouv_pure_lfi");
683 
684  fh = fh_new (LFIOUV_ARGS_LIST);
685 
686  fh->nfidx = *KNNOMF;
687  fh->fidx = (lfi_altm_fh_fidx_t *)malloc (sizeof (lfi_altm_fh_fidx_t) * fh->nfidx);
688 
689  /* Open LFI files */
690 
691  for (ifh = 0; ifh < fh->nfidx; ifh++)
692  {
693  fh->fidx[ifh].als = NULL;
694  fh->fidx[ifh].cnomf = lfi_fstrdup (CDNOMF + CDNOMF_len * (ifh + 1), CDNOMF_len, NULL);
695  fh->fidx[ifh].inumer = *KNUMER;
696  fh->fidx[ifh].dead = 0;
697  }
698 
699  if ((fast) && (*KNNOMF > 1))
700 #pragma omp parallel private (ifh)
701  {
702 #pragma omp for schedule (dynamic)
703  for (ifh = 0; ifh < fh->nfidx; ifh++)
704  getfhr (fh, ifh);
705  }
706 
707  /* Count the number of LFI articles */
708 
709  for (fh->naidx = 0, ifh = 0; ifh < fh->nfidx; ifh++)
710  {
711  lfi_altm_fh_fidx_t fhr = getfhr (fh, ifh);
712  integer64 INALDO, INTROU, INARES, INAMAX;
713  fhr.als->cb->lfinaf (fhr.als->data, KREP, &fhr.inumer, &INALDO, &INTROU, &INARES, &INAMAX);
714  fh->naidx += INALDO;
715  }
716 
717  /* Allocate article index */
718 
719  fh->aidx = (lfi_altm_fh_aidx_t *)malloc (sizeof (lfi_altm_fh_aidx_t) * fh->naidx);
720 
721  /* Read LFI article list */
722 
723  for (iart = 0, ifh = 0; ifh < fh->nfidx; ifh++)
724  {
725  lfi_altm_fh_fidx_t fhr = getfhr (fh, ifh);
726  fhr.als->cb->lfipos (fhr.als->data, KREP, KNUMER);
727  for (; ; iart++)
728  {
729  fhr.als->cb->lficas (fhr.als->data, KREP, &fhr.inumer, CLNOMA, &ILONG, &IPOSEX, &LLAVAN, CLNOMA_len);
730  if ((ILONG == 0) && eqan (CLNOMA, blank_index))
731  break;
732  memcpy (fh->aidx[iart].name, CLNOMA, ARTNLEN);
733  memcpy (fh->aidx[iart].namf, CLNOMA, ARTNLEN);
734  fh->aidx[iart].ifh = ifh;
735  }
736  }
737 
738  *KNBARI = fh->naidx;
739 
740  *KNBARI -= remove_duplicates (fh);
741 
742  fh_modified (fh);
743 
744  DRHOOK_END (0);
745 
746  return fh;
747 }
748 
749 static lfi_altm_fh_t * lfiouv_mixed_lfi (void * LFI, integer64 * KREP, integer64 * KNUMER, logical * LDNOMM, character * CDNOMF,
750  integer64 * KNNOMF, character * CDSTTO, logical * LDERFA, logical * LDIMST, integer64 * KNIMES,
751  integer64 * KNBARP, integer64 * KNBARI, logical * LDRELATIVE,
752  character_len CDNOMF_len, character_len CDSTTO_len,
753  int fast, int do_link, int do_copy, int do_unlink)
754 {
755  integer64 ILONG, IPOSEX;
756  logical LLAVAN = fort_TRUE;
757  character CLNOMA[ARTNLEN];
758  integer64 CLNOMA_len = ARTNLEN;
759  int iart, ifh;
760  lfi_altm_fh_t * fh;
761 
762  typedef struct
763  {
764  int pure;
765  char * cnomf;
766  character * CLNOMF;
767  lfi_hndl_t * als;
768  lfi_altm_fh_t * fh;
769  integer64 inumer;
770  integer64 irep;
771  int _errno;
772  } _lfi_mixed_t;
773 
774  _lfi_mixed_t * lm;
775  int ifi;
776 
777  DRHOOK_START ("lfiouv_mixed_lfi");
778 
779  fh = fh_new (LFIOUV_ARGS_LIST);
780 
781  fh->unlink = do_unlink;
782  fh->rmdir = do_unlink;
783 
784  lm = (_lfi_mixed_t *)malloc (sizeof (_lfi_mixed_t) * *KNNOMF);
785  memset (lm, 0, sizeof (_lfi_mixed_t) * *KNNOMF);
786 
787  /* Open all sub-files */
788 
789  /* omp pragmas may crash the Cray compiler ; use O0 in that case. REK 13-Jan-2015 */
790 #pragma omp parallel if (fast)
791  {
792  int ifi, err = 0;
793 #pragma omp for schedule (dynamic)
794  for (ifi = 0; ifi < *KNNOMF; ifi++)
795  {
796  lfi_grok_t grok;
797  character * CLNOMF = CDNOMF + CDNOMF_len * (ifi + 1);
798 
799  if (err > 0)
800  continue;
801 
802  grok = lfi_grok (CLNOMF, CDNOMF_len);
803  lm[ifi].CLNOMF = CLNOMF;
804 
805  switch (grok)
806  {
807  case LFI_NONE:
808  lm[ifi]._errno = ENOENT;
809  lm[ifi].irep = 1;
810  goto error_omp;
811  case LFI_UNKN:
812  lm[ifi].irep = -10;
813  goto error_omp;
814  case LFI_PURE:
815  lm[ifi].pure = 1;
816  lm[ifi].cnomf = lfi_fstrdup (CLNOMF, CDNOMF_len, NULL);
817  lm[ifi].als = _getfhr ("", CLNOMF, &lm[ifi].inumer, CDNOMF_len);
818  break;
819  case LFI_ALTM:
820  {
821  integer64 INIMES = 0, INBARP = 0, INBARI = 0;
822  logical LLNOMM = fort_TRUE, LLERFA = fort_FALSE, LLIMST = fort_FALSE;
823  character * CLSTTO = (character *)"OLD";
824  lm[ifi].fh = lfiouv_mult (LFI, &lm[ifi].irep, &lm[ifi].inumer, &LLNOMM, CLNOMF, CLSTTO, &LLERFA,
825  &LLIMST, &INIMES, &INBARP, &INBARI, CDNOMF_len, strlen (CLSTTO));
826  if (lm[ifi].irep != 0)
827  {
828  goto error_omp;
829  }
830  }
831  break;
832  default:
833  lm[ifi].irep = -10;
834  goto error_omp;
835  }
836 
837  continue;
838 
839 error_omp:
840  err++;
841  }
842  }
843 
844  /* Check if any errors occured */
845 
846  {
847  int ifi, err = 0;
848  for (ifi = 0; ifi < *KNNOMF; ifi++)
849  {
850  if (lm[ifi].irep)
851  {
852  errno = lm[ifi]._errno;
853  *KREP = lm[ifi].irep;
854  lfi_verb (NULL, "lfiouv_mixed_lfi", "KREP", KREP, "CDNOMF", lm[ifi].CLNOMF, CDNOMF_len, NULL);
855  err++;
856  }
857  if (err)
858  goto error;
859  }
860  }
861 
862  /* Reckon the number of sub-files */
863 
864  fh->nfidx = 0;
865 
866  for (ifi = 0; ifi < *KNNOMF; ifi++)
867  if (lm[ifi].pure)
868  fh->nfidx++;
869  else
870  fh->nfidx += lm[ifi].fh->nfidx;
871 
872  fh->fidx = (lfi_altm_fh_fidx_t *)malloc (sizeof (lfi_altm_fh_fidx_t) * fh->nfidx);
873 
874  /* Set sub files attributes of newly created file & count articles */
875 
876  fh->naidx = 0;
877 
878 {
879  LFI_CSTR (cnomf, CDNOMF);
880  const char * cnoml;
881 
882  for (ifi = 0, ifh = 0; ifi < *KNNOMF; ifi++)
883  if (lm[ifi].pure)
884  {
885  integer64 INALDO, INTROU, INARES, INAMAX;
886  lfi_hndl_t * als = lm[ifi].als;
887 
888  if (do_link)
889  {
890  cnoml = getfname (cnomf);
891 
892  /* Link sub-file */
893 
894  if ((*KREP = lfi_smartcopy (lm[ifi].cnomf, cnoml, do_copy)) != 0)
895  goto error;
896  }
897  else
898  {
899  cnoml = strdup (lm[ifi].cnomf);
900  }
901 
902 
903  /* Make path of sub-file relative to path of main file */
904  if (istrue (*LDRELATIVE))
905  cnoml = lfi_make_relative_path (cnomf, cnoml);
906 
907  fh->fidx[ifh].als = als;
908  fh->fidx[ifh].cnomf = cnoml;
909  fh->fidx[ifh].inumer = lm[ifi].inumer;
910  fh->fidx[ifh].dead = 0;
911 
912  free ((void *)lm[ifi].cnomf);
913 
914  lm[ifi].als = NULL;
915  lm[ifi].cnomf = NULL;
916  lm[ifi].inumer = 0;
917 
918  als->cb->lfinaf (als->data, KREP, &fh->fidx[ifh].inumer, &INALDO, &INTROU, &INARES, &INAMAX);
919  fh->naidx += INALDO;
920 
921  ifh++;
922  }
923  else
924  {
925  int ifg;
926  lfi_altm_fh_t * fg = lm[ifi].fh;
927 
928  for (ifg = 0; ifg < fg->nfidx; ifg++, ifh++)
929  {
930  const char * cnomg = resolve_filename (fg->cnomf, fg->fidx[ifg].cnomf, strlen (fg->fidx[ifg].cnomf), NULL);
931 
932  if (do_link)
933  {
934  cnoml = getfname (cnomf);
935 
936  /* Link sub-file */
937 
938  if ((*KREP = lfi_smartcopy (cnomg, cnoml, do_copy)) != 0)
939  goto error;
940  }
941  else
942  {
943  cnoml = strdup (cnomg);
944  }
945 
946  /* Make path of sub-file relative to path of main file */
947  if (istrue (*LDRELATIVE))
948  cnoml = lfi_make_relative_path (cnomf, cnoml);
949 
950  fh->fidx[ifh].als = NULL;
951  fh->fidx[ifh].cnomf = cnoml;
952  fh->fidx[ifh].inumer = 0;
953 
954  free ((void *)cnomg);
955  }
956 
957  fh->naidx += fg->naidx;
958  }
959 
960 }
961 
962 
963  /* Allocate article index */
964 
965  fh->aidx = (lfi_altm_fh_aidx_t *)malloc (sizeof (lfi_altm_fh_aidx_t) * fh->naidx);
966 
967  for (iart = 0, ifi = 0, ifh = 0; ifi < *KNNOMF; ifi++)
968  if (lm[ifi].pure)
969  {
970  lfi_altm_fh_fidx_t * fhr = &fh->fidx[ifh]; /* Should be open at this point */
971 
972  if (fhr->als == NULL)
973  lfi_abor ("Internal error: expected opened sub-file");
974 
975  fhr->als->cb->lfipos (fhr->als->data, KREP, &fhr->inumer);
976 
977  for (; ; iart++)
978  {
979  fhr->als->cb->lficas (fhr->als->data, KREP, &fhr->inumer, CLNOMA, &ILONG, &IPOSEX, &LLAVAN, CLNOMA_len);
980  if ((ILONG == 0) && eqan (CLNOMA, blank_index))
981  break;
982  memcpy (fh->aidx[iart].name, CLNOMA, ARTNLEN);
983  memcpy (fh->aidx[iart].namf, CLNOMA, ARTNLEN);
984  fh->aidx[iart].ifh = ifh;
985  }
986 
987  ifh++;
988  }
989  else
990  {
991  int iartg;
992  lfi_altm_fh_t * fg = lm[ifi].fh;
993 
994  for (iartg = 0; iartg < fg->naidx; iartg++, iart++)
995  {
996  memcpy (fh->aidx[iart].name, fg->aidx[iartg].name, ARTNLEN);
997  memcpy (fh->aidx[iart].namf, fg->aidx[iartg].namf, ARTNLEN);
998  fh->aidx[iart].ifh = ifh + fg->aidx[iartg].ifh;
999  }
1000 
1001  ifh += fg->nfidx;
1002  }
1003 
1004  /* Close LFI_ALTM files */
1005 
1006 
1007  for (ifi = 0; ifi < *KNNOMF; ifi++)
1008  if (! lm[ifi].pure)
1009  lfifer_mult (lm[ifi].fh);
1010 
1011  *KNBARI = fh->naidx;
1012 
1013  *KNBARI -= remove_duplicates (fh);
1014 
1015  fh_modified (fh);
1016 
1017  DRHOOK_END (0);
1018 
1019  return fh;
1020 
1021 error:
1022 
1023  return NULL;
1024 }
1025 
1026 static void lfiouv_altm (LFIOUV_ARGS_DECL)
1027 {
1028  ALM_DECL;
1029  FH_DECL (0);
1030  lfi_grok_t islfi;
1031  character CLNOMF[32];
1032 
1033  DRHOOK_START ("lfiouv_altm");
1034 
1035 
1036  if (! istrue (*LDNOMM))
1037  {
1038  if (*KNUMER <= 0)
1039  lfi_abor ("LDNOMM=T is not compatible with KNUMER<=0");
1040  CDNOMF_len = sprintf (CLNOMF, "fort.%lld", *KNUMER);
1041  CDNOMF = CLNOMF;
1042  }
1043 
1044  islfi = lfi_grok (CDNOMF, CDNOMF_len);
1045 
1046  if (fh != NULL)
1047  {
1048  *KREP = -13;
1049  goto end;
1050  }
1051 
1052  islfi = lfi_grok (CDNOMF, CDNOMF_len);
1053 
1054  /* Check Fortran STATUS */
1055  if ((islfi == LFI_PURE) || (islfi == LFI_ALTM))
1056  {
1057  if (lfi_fstrcmp (CDSTTO, "OLD", CDSTTO_len, 3) &&
1058  lfi_fstrcmp (CDSTTO, "UNKNOWN", CDSTTO_len, 7))
1059  {
1060  *KREP = -9;
1061  goto end;
1062  }
1063  }
1064  else if (islfi == LFI_NONE)
1065  {
1066  if (lfi_fstrcmp (CDSTTO, "NEW", CDSTTO_len, 3) &&
1067  lfi_fstrcmp (CDSTTO, "UNKNOWN", CDSTTO_len, 7))
1068  {
1069  *KREP = -9;
1070  goto end;
1071  }
1072  }
1073 
1074  /* Initialize descriptor */
1075 
1076  if (islfi == LFI_PURE)
1077  {
1078  LFI_CSTR (cnomf1, CDNOMF);
1079  const char * cnomf2;
1080  character * CLNOMF;
1081  integer64 INNOMF = 1;
1082  integer64 CLNOMF_len;
1083  integer64 cnomf1_len;
1084  integer64 cnomf2_len;
1085 
1086  /* We have to rename the sub-file to something else, so we create a name and rename the file */
1087 
1088  cnomf2 = getfname (cnomf1);
1089 
1090  cnomf1_len = strlen (cnomf1);
1091  cnomf2_len = strlen (cnomf2);
1092 
1093  CLNOMF_len = cnomf1_len > cnomf2_len ? cnomf1_len : cnomf2_len;
1094 
1095  CLNOMF = (character *)malloc (2 * CLNOMF_len);
1096  memset (CLNOMF, ' ', 2 * CLNOMF_len);
1097 
1098  memcpy (CLNOMF, cnomf1, cnomf1_len);
1099  memcpy (CLNOMF + CLNOMF_len, cnomf2, cnomf2_len);
1100 
1101  if (rename (cnomf1, cnomf2) < 0)
1102  lfi_abor ("Cannot rename `%s' in `%s'", cnomf1, cnomf2);
1103 
1104  /* Invoke lfiouv_pure_lfi */
1105 
1106  fh = lfiouv_pure_lfi (LFI, KREP, KNUMER, LDNOMM, CLNOMF,
1107  &INNOMF, CDSTTO, LDERFA, LDIMST, KNIMES,
1108  KNBARP, KNBARI, CLNOMF_len, CDSTTO_len, 0);
1109 
1110  free ((void *)cnomf1);
1111  free ((void *)cnomf2);
1112  free (CLNOMF);
1113 
1114  }
1115  /* Read LFI index */
1116  else if (islfi == LFI_ALTM)
1117  {
1118  fh = lfiouv_mult (LFIOUV_ARGS_LIST);
1119  }
1120  /* New file */
1121  else if (islfi == LFI_NONE)
1122  {
1123  fh = fh_new (LFIOUV_ARGS_LIST);
1124 
1125  if (strcmp (fh->cstto, "OLD") == 0)
1126  lfi_abor ("File does not exist `%s'", fh->cnomf);
1127 
1128  fh->nfidx = 0;
1129  fh->fidx = (lfi_altm_fh_fidx_t *)malloc (sizeof (lfi_altm_fh_fidx_t) * fh->nfidx);
1130  fh->naidx = 0;
1131  fh->aidx = (lfi_altm_fh_aidx_t *)malloc (sizeof (lfi_altm_fh_aidx_t) * fh->naidx);
1132 
1133  fh_modified (fh);
1134 
1135  *KNBARI = fh->naidx;
1136  *KREP = 0;
1137  }
1138  else
1139  {
1140  LFI_CSTR (cnomf, CDNOMF);
1141  lfi_abor ("Cannot open file `%s'", cnomf);
1142  }
1143 
1144  if (fh != NULL)
1145  {
1146  fh->next = alm->fh;
1147  alm->fh = fh;
1148  }
1149 
1150 end:
1151 
1152  DRHOOK_END (0);
1153 }
1154 
1155 static void lfifer_altm (LFIFER_ARGS_DECL)
1156 {
1157  ALM_DECL;
1158  lfi_altm_fh_t * fh, * fg;
1159  integer64 ifh;
1160 
1161  DRHOOK_START ("lfifer_altm");
1162 
1163  for (fh = alm->fh, fg = NULL; fh; fg = fh, fh = fh->next)
1164  if (fh->inumer == *KNUMER)
1165  break;
1166 
1167  if (fh == alm->fh)
1168  alm->fh = fh->next;
1169  else
1170  fg->next = fh->next;
1171 
1172  /* Save index to file */
1173 
1174  if (fh->modified)
1175  {
1176  fh_write_hdr (fh, KREP);
1177  if (*KREP != 0)
1178  goto error;
1179  }
1180 
1181  /* Close files & free all data */
1182 
1183  for (ifh = 0; ifh < fh->nfidx; ifh++)
1184  {
1185  lfi_hndl_t * als = fh->fidx[ifh].als;
1186  if (als != NULL)
1187  {
1188  void * LFI = als->data;
1189  integer64 * KNUMER = &fh->fidx[ifh].inumer;
1190  fh->fidx[ifh].als->cb->lfifer (LFIFER_ARGS_LIST);
1191  fh->fidx[ifh].als->destroy (fh->fidx[ifh].als);
1192  }
1193  fh->fidx[ifh].als = NULL;
1194  }
1195 
1196  lfifer_mult (fh);
1197 
1198  *KREP = 0;
1199 
1200  goto done;
1201 
1202 error:
1203 
1204  *KREP = -1;
1205 
1206 done:
1207 
1208  DRHOOK_END (0);
1209 }
1210 
1211 static void lficas_altm (LFICAS_ARGS_DECL)
1212 {
1213  ALM_DECL;
1214  FH_DECL (1);
1215  int iart = seek_rc (fh, +1);
1216  DRHOOK_START ("lficas_altm");
1217 
1218  *KREP = 0;
1219  memset (CDNOMA, ' ', CDNOMA_len);
1220 
1221  if (iart < 0)
1222  {
1223  *KLONG = 0;
1224  *KPOSEX = 0;
1225  goto end;
1226  }
1227 
1228  /* Look for article len & pos in sub-file */
1229  {
1230  integer64 ifh = fh->aidx[iart].ifh;
1231  lfi_altm_fh_fidx_t fhr = getfhr (fh, ifh);
1232  /* Argument list */
1233  character CDNOMA[ARTNLEN];
1234  integer64 * KNUMER = &fh->fidx[ifh].inumer;
1235  character_len CDNOMA_len = ARTNLEN;
1236  void * LFI = fhr.als->data;
1237 
1238  memcpy (CDNOMA, fh->aidx[iart].namf, ARTNLEN);
1239  fhr.als->cb->lfinfo (LFINFO_ARGS_LIST);
1240  if ((*KREP != 0) || ((*KLONG == 0) && (*KPOSEX == 0)))
1241  lfi_abor ("Internal error in unit %lld, `%s'", fh->inumer, fh->cnomf);
1242  }
1243 
1244  memcpy (CDNOMA, fh->aidx[iart].name, minARTN (CDNOMA_len));
1245 
1246  if (CDNOMA_len < lfi_fstrlen (fh->aidx[iart].name, ARTNLEN))
1247  {
1248  *KREP = -24;
1249  goto end;
1250  }
1251 
1252  if (istrue (*LDAVAN))
1253  fh->iart = iart;
1254 
1255 end:
1256  DRHOOK_END (0);
1257 }
1258 
1259 static void lfipos_altm (LFIPOS_ARGS_DECL)
1260 {
1261  ALM_DECL;
1262  FH_DECL (1);
1263  DRHOOK_START ("lfipos_altm");
1264 
1265  /* Reset article counter */
1266  fh->iart = -1;
1267 
1268  *KREP = 0;
1269 
1270  DRHOOK_END (0);
1271 }
1272 
1273 static void lfinfo_altm (LFINFO_ARGS_DECL)
1274 {
1275  ALM_DECL;
1276  FH_DECL (1);
1277  ART_DECL;
1278  DRHOOK_START ("lfinfo_altm");
1279 
1280  if (iart < 0)
1281  {
1282  *KREP = 0;
1283  *KLONG = 0;
1284  *KPOSEX = 0;
1285  }
1286  else
1287  {
1288  void * LFI = fhr.als->data;
1289  character * CDNOMA = fh->aidx[iart].namf;
1290  KNUMER = &fh->fidx[ifh].inumer;
1291  fhr.als->cb->lfinfo (LFINFO_ARGS_LIST);
1292 
1293  /* Article was not found; this is an internal error */
1294  if ((*KREP != 0) || ((*KLONG == 0) && (*KREP == 0)))
1295  lfi_abor ("Internal error in unit %lld, `%s'", fh->inumer, fh->cnomf);
1296 
1297  fh->iart = iart;
1298 
1299  *KPOSEX = iart;
1300 
1301  }
1302 
1303  DRHOOK_END (0);
1304 }
1305 
1306 static void lfilaf_altm (LFILAF_ARGS_DECL)
1307 {
1308  ALM_DECL;
1309  FH_DECL (1);
1310  int iart;
1311  integer64 idonn = 1;
1312  DRHOOK_START ("lfilaf_altm");
1313 
1314  *KREP = 0;
1315 
1316  for (iart = 0; iart < fh->naidx; iart++)
1317  {
1318  if (neqan (blank_index, fh->aidx[iart].name))
1319  {
1320  integer64 ILONG, IPOSEX;
1321  int ifh = fh->aidx[iart].ifh;
1322  lfi_altm_fh_fidx_t fhr = getfhr (fh, ifh);
1323  KNUMER = &fhr.inumer;
1324 
1325  fhr.als->cb->lfinfo (fhr.als->data, KREP, KNUMER, fh->aidx[iart].namf, &ILONG, &IPOSEX, ARTNLEN);
1326  if (*KREP != 0)
1327  goto end;
1328 
1329  printf (
1330 "%7lld-eme article de donnees: \"%16.16s\", %6lld mots, position %8lld a %8lld, \"%16.16s\" dans fichier '%s'\n",
1331 idonn++, fh->aidx[iart].name, ILONG, IPOSEX, IPOSEX + ILONG-1, fh->aidx[iart].namf, fh->fidx[ifh].cnomf);
1332  }
1333  }
1334 
1335 end:
1336 
1337  DRHOOK_END (0);
1338 }
1339 
1340 static void lfinum_altm (LFINUM_ARGS_DECL)
1341 {
1342  ALM_DECL;
1343  FH_DECL (0);
1344 
1345  DRHOOK_START ("lfinum_altm");
1346 
1347  *KRANG = fh == NULL ? 0 : 1;
1348 
1349  DRHOOK_END (0);
1350 }
1351 
1352 static void lfilec_altm (LFILEC_ARGS_DECL)
1353 {
1354  ALM_DECL;
1355  FH_DECL (1);
1356  ART_DECL;
1357  DRHOOK_START ("lfilec_altm");
1358 
1359  if (iart < 0)
1360  {
1361  *KREP = iart;
1362  goto end;
1363  }
1364  else
1365  {
1366  fhr.als->cb->lfilec (fhr.als->data, KREP, &fh->fidx[ifh].inumer, fh->aidx[iart].namf, KTAB, KLONG, ARTNLEN);
1367  if (*KREP != 0)
1368  goto end;
1369 
1370  fh->iart = iart;
1371  }
1372 
1373 end:
1374  DRHOOK_END (0);
1375 }
1376 
1377 static void lfilas_altm (LFILAS_ARGS_DECL)
1378 {
1379  ALM_DECL;
1380  FH_DECL (1);
1381  int iart = seek_rc (fh, +1);
1382  DRHOOK_START ("lfilas_altm");
1383 
1384  if (iart < 0)
1385  {
1386  *KREP = -23;
1387  goto end;
1388  }
1389  else
1390  {
1391  integer64 ifh = fh->aidx[iart].ifh;
1392  lfi_altm_fh_fidx_t fhr = getfhr (fh, ifh);
1393 
1394  fhr.als->cb->lfilec (fhr.als->data, KREP, &fhr.inumer, fh->aidx[iart].namf, KTAB, KLONG, ARTNLEN);
1395  if (*KREP != 0)
1396  goto end;
1397 
1398  memset (CDNOMA, ' ', CDNOMA_len);
1399  memcpy (CDNOMA, fh->aidx[iart].name, minARTN (CDNOMA_len));
1400 
1401  if (CDNOMA_len < lfi_fstrlen (fh->aidx[iart].name, ARTNLEN))
1402  {
1403  *KREP = -24;
1404  goto end;
1405  }
1406 
1407  fh->iart = iart;
1408  }
1409 
1410 end:
1411  DRHOOK_END (0);
1412 }
1413 
1414 static void lfilap_altm (LFILAP_ARGS_DECL)
1415 {
1416  ALM_DECL;
1417  FH_DECL (1);
1418  int iart = seek_rc (fh, -1);
1419  DRHOOK_START ("lfilap_altm");
1420 
1421  if (iart < 0)
1422  {
1423  *KREP = -26;
1424  goto end;
1425  }
1426  else
1427  {
1428  integer64 ifh = fh->aidx[iart].ifh;
1429  lfi_altm_fh_fidx_t fhr = getfhr (fh, ifh);
1430 
1431  fhr.als->cb->lfilec (fhr.als->data, KREP, &fhr.inumer, fh->aidx[iart].namf, KTAB, KLONG, ARTNLEN);
1432  if (*KREP != 0)
1433  goto end;
1434 
1435  memset (CDNOMA, ' ', CDNOMA_len);
1436  memcpy (CDNOMA, fh->aidx[iart].name, minARTN (CDNOMA_len));
1437 
1438  if (CDNOMA_len < lfi_fstrlen (fh->aidx[iart].name, ARTNLEN))
1439  {
1440  *KREP = -24;
1441  goto end;
1442  }
1443 
1444  fh->iart = iart;
1445  }
1446 
1447 end:
1448  DRHOOK_END (0);
1449 }
1450 
1451 static void lficap_altm (LFICAP_ARGS_DECL)
1452 {
1453  ALM_DECL;
1454  FH_DECL (1);
1455  int iart = seek_rc (fh, -1);
1456  DRHOOK_START ("lficap_altm");
1457 
1458  memset (CDNOMA, ' ', CDNOMA_len);
1459  *KREP = 0;
1460 
1461  if (iart < 0)
1462  {
1463  *KLONG = 0;
1464  *KPOSEX = 0;
1465  goto end;
1466  }
1467 
1468  {
1469  int ifh = fh->aidx[iart].ifh;
1470  lfi_altm_fh_fidx_t fhr = getfhr (fh, ifh);
1471  integer64 * KNUMER = &fhr.inumer;
1472  character CDNOMA[ARTNLEN];
1473  character_len CDNOMA_len = ARTNLEN;
1474  void * LFI = fhr.als->data;
1475 
1476  memcpy (CDNOMA, fh->aidx[iart].namf, minARTN (CDNOMA_len));
1477  fhr.als->cb->lfinfo (LFINFO_ARGS_LIST);
1478  if ((*KREP != 0) || ((*KLONG == 0) && (*KPOSEX == 0)))
1479  lfi_abor ("Internal error in unit %lld, `%s'", fh->inumer, fh->cnomf);
1480  }
1481 
1482  memcpy (CDNOMA, fh->aidx[iart].name, minARTN (CDNOMA_len));
1483  if (CDNOMA_len < lfi_fstrlen (fh->aidx[iart].name, ARTNLEN))
1484  {
1485  *KREP = -24;
1486  goto end;
1487  }
1488 
1489  if (istrue (*LDRECU))
1490  fh->iart = iart;
1491 
1492 end:
1493  DRHOOK_END (0);
1494 }
1495 
1496 static void lfisup_altm (LFISUP_ARGS_DECL)
1497 {
1498  ALM_DECL;
1499  FH_DECL (1);
1500  ART_DECL;
1501  integer64 IPOSEX;
1502  DRHOOK_START ("lfisup_altm");
1503 
1504  *KREP = 0;
1505 
1506  if (iart < 0)
1507  {
1508  *KREP = iart;
1509  goto end;
1510  }
1511 
1512  fhr.als->cb->lfinfo (fhr.als->data, KREP, &fh->fidx[ifh].inumer, &fh->aidx[ifh].namf[0], KLONUT, &IPOSEX, ARTNLEN);
1513  if (*KREP != 0)
1514  goto end;
1515 
1516  memcpy (fh->aidx[iart].name, blank_index, ARTNLEN);
1517  memcpy (fh->aidx[iart].namf, blank_index, ARTNLEN);
1518 
1519  fh_modified (fh);
1520 
1521 end:
1522  DRHOOK_END (0);
1523 }
1524 
1525 static void lfinaf_altm (LFINAF_ARGS_DECL)
1526 {
1527  ALM_DECL;
1528  FH_DECL (1);
1529  int iart;
1530 
1531  DRHOOK_START ("lfinaf_altm");
1532 
1533  *KNTROU = 0;
1534  *KNALDO = 0;
1535  *KNARES = 0;
1536  *KNAMAX = 0;
1537  *KREP = 0;
1538 
1539  for (iart = 0; iart < fh->naidx; iart++)
1540  if (neqan (blank_index, fh->aidx[iart].name))
1541  (*KNALDO)++;
1542 
1543  DRHOOK_END (0);
1544 }
1545 
1546 static void lfiren_altm (LFIREN_ARGS_DECL)
1547 {
1548  ALM_DECL;
1549  FH_DECL (1);
1550  int iart1 = lookup_rc (fh, CDNOM1, CDNOM1_len);
1551  int iart2 = lookup_rc (fh, CDNOM2, CDNOM2_len);
1552  DRHOOK_START ("lfiren_altm");
1553 
1554  if (iart1 < 0)
1555  {
1556  *KREP = iart1;
1557  goto end;
1558  }
1559 
1560  if (! check_an (CDNOM2, CDNOM2_len))
1561  {
1562  *KREP = -15;
1563  goto end;
1564  }
1565 
1566  if (iart2 >= 0)
1567  {
1568  *KREP = -25;
1569  goto end;
1570  }
1571 
1572  fh_modified (fh);
1573 
1574  memcpy (fh->aidx[iart1].name, blank_index, ARTNLEN);
1575  memcpy (fh->aidx[iart1].name, CDNOM2, minARTN (CDNOM2_len));
1576 
1577  *KREP = 0;
1578 
1579 end:
1580  DRHOOK_END (0);
1581 }
1582 
1583 static void lfiecr_altm (LFIECR_ARGS_DECL)
1584 {
1585  ALM_DECL;
1586  FH_DECL (1);
1587  int iart = lookup_rc (fh, CDNOMA, CDNOMA_len);
1588  integer64 ILONG, IPOSEX;
1589  lfi_altm_fh_fidx_t fhw;
1590 
1591  DRHOOK_START ("lfiecr_altm");
1592 
1593  if (! check_an (CDNOMA, CDNOMA_len))
1594  {
1595  *KREP = -15;
1596  goto end;
1597  }
1598 
1599  if (iart < 0)
1600  {
1601  int naidx;
1602 
1603  for (iart = 0; iart < fh->naidx; iart++)
1604  if (eqan (blank_index, fh->aidx[iart].name))
1605  goto found;
1606 
1607  /* Grow article index */
1608 
1609  naidx = 2 * fh->naidx + 1;
1610 
1611  fh->aidx = (lfi_altm_fh_aidx_t *)realloc (fh->aidx, naidx * sizeof (lfi_altm_fh_aidx_t));
1612  for (iart = fh->naidx; iart < naidx; iart++)
1613  {
1614  memcpy (fh->aidx[iart].name, blank_index, ARTNLEN);
1615  memcpy (fh->aidx[iart].namf, blank_index, ARTNLEN);
1616  fh->aidx[iart].ifh = -1;
1617  }
1618 
1619  iart = fh->naidx;
1620 
1621  fh->naidx = naidx;
1622  }
1623 
1624 found:
1625 
1626  fhw = getfhw (fh, 0);
1627 
1628  fhw.als->cb->lfinfo (fhw.als->data, KREP, &fhw.inumer, CDNOMA, &ILONG, &IPOSEX, CDNOMA_len);
1629 
1630  /*
1631  * Article already exists in LFI file;
1632  * see if it was renamed in main index
1633  */
1634  if ((ILONG != 0) || (IPOSEX != 0))
1635  {
1636  character CLNOMA[ARTNLEN];
1637  memcpy (CLNOMA, blank_index, ARTNLEN);
1638  memcpy (CLNOMA, CDNOMA, minARTN (CDNOMA_len));
1639  if (! (eqan (CLNOMA, fh->aidx[iart].name) && eqan (CLNOMA, fh->aidx[iart].namf)))
1640  fhw = getfhw (fh, 1);
1641  }
1642 
1643  {
1644  integer64 INALDO, INTROU, INARES, INAMAX;
1645  fhw.als->cb->lfinaf (fhw.als->data, KREP, &fhw.inumer, &INALDO, &INTROU, &INARES, &INAMAX);
1646  /*
1647  * Many articles were written to this file;
1648  * switch to a new one
1649  */
1650  if ((INALDO + INTROU) > alm->maxartals)
1651  fhw = getfhw (fh, 1);
1652  }
1653 
1654  /* Update article index */
1655 
1656  memcpy (fh->aidx[iart].name, blank_index, ARTNLEN);
1657  memcpy (fh->aidx[iart].name, CDNOMA, minARTN (CDNOMA_len));
1658  memcpy (fh->aidx[iart].namf, blank_index, ARTNLEN);
1659  memcpy (fh->aidx[iart].namf, CDNOMA, minARTN (CDNOMA_len));
1660 
1661  fh->aidx[iart].ifh = fh->ifh_w;
1662 
1663  /* Write article */
1664 
1665  {
1666  void * LFI = fhw.als->data;
1667  fhw.als->cb->lfiecr (LFIECR_ARGS_LIST);
1668  if (*KREP != 0)
1669  goto end;
1670  }
1671 
1672  fh_modified (fh);
1673 
1674  fh->iart = iart;
1675 
1676 end:
1677 
1678  DRHOOK_END (0);
1679 }
1680 
1681 static void lfiopt_altm (LFIOPT_ARGS_DECL)
1682 {
1683  ALM_DECL;
1684  FH_DECL (0);
1685  DRHOOK_START ("lfiopt_altm");
1686 
1687  if (fh == NULL)
1688  {
1689  *KREP = -1;
1690  goto end;
1691  }
1692 
1693  memset (CDNOMF, ' ', CDNOMF_len);
1694  memset (CDSTTO, ' ', CDSTTO_len);
1695 
1696  memcpy (CDNOMF, fh->cnomf, CDNOMF_len > strlen (fh->cnomf) ? strlen (fh->cnomf) : CDNOMF_len);
1697  memcpy (CDSTTO, fh->cstto, CDSTTO_len > strlen (fh->cstto) ? strlen (fh->cstto) : CDSTTO_len);
1698 
1699  *LDNOMM = fort_TRUE;
1700  *LDIMST = fort_FALSE;
1701  *LDERFA = fh->llerfa;
1702  *KNIMES = fh->inimes;
1703  *KREP = 0;
1704 
1705 end:
1706  DRHOOK_END (0);
1707 
1708 }
1709 
1710 static void lfinim_altm (LFINIM_ARGS_DECL)
1711 {
1712  ALM_DECL;
1713  FH_DECL (1);
1714 
1715  DRHOOK_START ("lfinaf_altm");
1716 
1717  *KREP = 0;
1718 
1719  if ((*KNIMES > 2) || (*KNIMES < 0))
1720  {
1721  *KREP = -2;
1722  goto end;
1723  }
1724 
1725  fh->inimes = *KNIMES;
1726 
1727 end:
1728 
1729  DRHOOK_END (0);
1730 }
1731 
1732 static void lfierf_altm (LFIERF_ARGS_DECL)
1733 {
1734  ALM_DECL;
1735  FH_DECL (1);
1736 
1737  DRHOOK_START ("lfierf_altm");
1738 
1739  fh->llerfa = *LDERFA;
1740  *KREP = 0;
1741 
1742  DRHOOK_END (0);
1743 }
1744 
1745 static void lfioef_altm (LFIOEF_ARGS_DECL)
1746 {
1747  ALM_DECL;
1748  FH_DECL (1);
1749 
1750  DRHOOK_START ("lfioef_altm");
1751 
1752  *LDERFA = fh->llerfa;
1753  *KREP = 0;
1754 
1755  DRHOOK_END (0);
1756 }
1757 
1758 static void lfifmd_altm (LFIFMD_ARGS_DECL)
1759 {
1760  ALM_DECL;
1761  DRHOOK_START ("lfifmd_altm");
1762 
1763  if (*KFACMD > 0)
1764  alm->fmult = *KFACMD;
1765 
1766  DRHOOK_END (0);
1767 }
1768 
1769 static void lfiofd_altm (LFIOFD_ARGS_DECL)
1770 {
1771  ALM_DECL;
1772 
1773  DRHOOK_START ("lfiofd_altm");
1774 
1775  *KFACMD = alm->fmult;
1776 
1777  DRHOOK_END (0);
1778 }
1779 
1780 static void lfiofm_altm (LFIOFM_ARGS_DECL)
1781 {
1782  ALM_DECL;
1783  FH_DECL (0);
1784  DRHOOK_START ("lfiofm_altm");
1785 
1786  *KREP = 0;
1787  if (fh)
1788  {
1789  *KFACTM = fh->fmult;
1790  *LDOUVR = fort_TRUE;
1791  }
1792  else
1793  {
1794  *KFACTM = alm->fmult;
1795  lfi_fmul_get (alm->fmult_list, KNUMER, KFACTM);
1796  *LDOUVR = fort_FALSE;
1797  }
1798 
1799  DRHOOK_END (0);
1800 }
1801 
1802 static void lfiafm_altm (LFIAFM_ARGS_DECL)
1803 {
1804  ALM_DECL;
1805  FH_DECL (0);
1806  DRHOOK_START ("lfiafm_altm");
1807 
1808  *KREP = 0;
1809  if (fh)
1810  {
1811  *KREP = -5;
1812  }
1813  else if (*KFACTM < 0)
1814  {
1815  *KREP = -14;
1816  }
1817  else
1818  {
1819  lfi_fmul_set (&alm->fmult_list, KNUMER, KFACTM);
1820  }
1821 
1822  DRHOOK_END (0);
1823 }
1824 
1825 static void lfisfm_altm (LFISFM_ARGS_DECL)
1826 {
1827 
1828  ALM_DECL;
1829  FH_DECL (0);
1830  DRHOOK_START ("lfisfm_altm");
1831 
1832  *KREP = 0;
1833  if (fh)
1834  {
1835  *KREP = -5;
1836  }
1837  else
1838  {
1839  if (lfi_fmul_del (&alm->fmult_list, KNUMER) < 0)
1840  *KREP = -31;
1841  }
1842 
1843  DRHOOK_END (0);
1844 }
1845 
1846 static void lfineg_altm (LFINEG_ARGS_DECL)
1847 {
1848  ALM_DECL;
1849  DRHOOK_START ("lfineg_altm");
1850  if ((*KNIVAU >= 0) && (*KNIVAU <= 2))
1851  alm->nerfag = *KNIVAU;
1852  DRHOOK_END (0);
1853 }
1854 
1855 static void lfioeg_altm (LFIOEG_ARGS_DECL)
1856 {
1857  ALM_DECL;
1858  DRHOOK_START ("lfioeg_altm");
1859  *KNIVAU = alm->nerfag;
1860  DRHOOK_END (0);
1861 }
1862 
1863 static void lfiomg_altm (LFIOMG_ARGS_DECL)
1864 {
1865  ALM_DECL;
1866  DRHOOK_START ("lfiomg_altm");
1867  *KNIVAU = alm->inivau;
1868  *KULOUT = alm->iulout;
1869  DRHOOK_END (0);
1870 }
1871 
1872 static void lfinmg_altm (LFINMG_ARGS_DECL)
1873 {
1874  ALM_DECL;
1875  DRHOOK_START ("lfinmg_altm");
1876  alm->inivau = *KNIVAU;
1877  alm->iulout = *KULOUT;
1878  DRHOOK_END (0);
1879 }
1880 
1881 #undef ALM_DECL
1882 
1884  lfiouv_altm, /* Ouverture fichier */
1885  lficas_altm, /* KNUMER Caracteristiques de l'article suivant */
1886  lfiecr_altm, /* KNUMER Ecriture */
1887  lfifer_altm, /* KNUMER Fermeture */
1888  lfilec_altm, /* KNUMER Lecture */
1889  lfinfo_altm, /* KNUMER Caracteristiques d'un article nomme */
1890  lfipos_altm, /* KNUMER Remise a zero du pointeur de fichier */
1891  lfiver_dumm, /* KNUMER Verrouillage d'un fichier */
1892  lfiofm_altm, /* KNUMER Obtention du facteur multiplicatif */
1893  lfineg_altm, /* Niveau global d'erreur */
1894  lfilaf_altm, /* KNUMER Liste des articles */
1895  lfiosg_dumm, /* Obtention du niveau d'impression des statistiques */
1896  lfinum_altm, /* KNUMER Rang de l'unite logique KNUMER */
1897  lfisup_altm, /* KNUMER Suppression d'un article */
1898  lfiopt_altm, /* KNUMER Obtention des options d'ouverture d'un fichier */
1899  lfinmg_altm, /* Niveau global d'erreur */
1900  lficap_altm, /* KNUMER Caracteristiques de l'article precedent */
1901  lfifra_dumm, /* Messages en Francais */
1902  lficfg_dumm, /* Impression des parametres de base de LFI */
1903  lfierf_altm, /* KNUMER Erreur fatale */
1904  lfilas_altm, /* KNUMER Lecture de l'article de donnees suivant */
1905  lfiren_altm, /* KNUMER Renommer un article */
1906  lfiini_dumm, /* Initialisation de LFI */
1907  lfipxf_miss, /* KNUMER Export d'un fichier LFI */
1908  lfioeg_altm, /* Obtention du niveau global de traitement des erreurs */
1909  lfinaf_altm, /* KNUMER Nombre d'articles divers */
1910  lfiofd_altm, /* Facteur multiplicatif courant */
1911  lfiomf_dumm, /* KNUMER Obtention du niveau de messagerie */
1912  lfiafm_altm, /* KNUMER Attribution d'un facteur multiplicatif a une unite */
1913  lfista_dumm, /* KNUMER Impression des statistiques d'utilisation */
1914  lfiosf_miss, /* KNUMER Obtention de l'option d'impression des statistiques */
1915  lfilap_altm, /* KNUMER Lecture de l'article precedent */
1916  lfioef_altm, /* KNUMER Obtention de l'option courante de traitement des erreurs */
1917  lfimst_dumm, /* KNUMER Activation de l'option d'impression de statistiques */
1918  lfinim_altm, /* KNUMER Ajustement du niveau de messagerie */
1919  lfisfm_altm, /* KNUMER Suppression d'un facteur multiplicatif */
1920  lfinsg_dumm, /* Niveau global d'impression de statistiques */
1921  lfideb_dumm, /* Mode mise au point (debug) */
1922  lfiomg_altm, /* Obtention du niveau global des messages LFI */
1923  lfifmd_altm, /* Facteur multiplicatif par defaut */
1924 };
1925 
1926 #define ALM_DECL \
1927  lfi_altm_t * alm = lookup_alm (lfi->data);
1928 
1929 static void lfi_del_altm_hndl (lfi_hndl_t * lfi)
1930 {
1931  ALM_DECL;
1932 
1933  if (alm->fh)
1934  lfi_abor ("Attempt to release lfi handler with opened files");
1935 
1936  free (alm);
1937  free (lfi);
1938 }
1939 
1941 {
1942  ALM_DECL;
1943  FH_DECL (0);
1944  return fh == NULL ? 0 : 1;
1945 }
1946 
1948 {
1949  ALM_DECL;
1950  FH_DECL (1);
1951  return fh->inimes == 2 ? 1 : 0;
1952 }
1953 
1955 {
1956  ALM_DECL;
1957  FH_DECL (1);
1958  return (alm->nerfag == 0) || ((alm->nerfag == 1) && istrue (fh->llerfa));
1959 }
1960 
1961 #undef ALM_DECL
1962 
1963 /* Create the LFI handler */
1964 
1966 {
1967  lfi_hndl_t * lfi = (lfi_hndl_t *)malloc (sizeof (lfi_hndl_t));
1968  lfi_altm_t * alm = (lfi_altm_t *)malloc (sizeof (lfi_altm_t));
1969 
1970  memset (alm, 0, sizeof (lfi_altm_t));
1971  memcpy (alm->cmagic, "lfi_altm", 8);
1972 
1973  alm->fmult = 6;
1974  alm->fmult_list = NULL;
1975  alm->maxartals = 3000;
1976  alm->nerfag = 1;
1977  alm->inivau = 0;
1978  alm->iulout = 0;
1979 
1980  lfi->cb = &lficb_altm;
1981  lfi->cb_verb = &lficb_verb;
1982  lfi->data = alm;
1983  lfi->destroy = lfi_del_altm_hndl;
1984  lfi->is_open = lfi_opn_altm_hndl;
1985  lfi->is_verb = lfi_vrb_altm_hndl;
1986  lfi->is_fatl = lfi_fat_altm_hndl;
1987  lfi->next = NULL;
1988 
1989  return lfi;
1990 }
1991 
1992 void lfi_altm_merge_ (integer64 * KREP, character * CDNOMF, integer64 * KNNOMF, logical * LDRELATIVE, character_len CDNOMF_len)
1993 {
1994  lfi_hndl_t * lfi = lfi_get_altm_hndl (NULL);
1995  lfi_altm_t * alm = lfi->data;
1996  integer64 INUMER = 1;
1997 
1998  *KREP = 0;
1999 
2000  /* Open file */
2001  {
2002  integer64 INIMES = 2, INBARP = 0, INBARI = 0;
2003  logical LLNOMM = fort_TRUE, LLERFA = fort_TRUE, LLIMST = fort_TRUE;
2004  character * CLSTTO = (character *)"OLD";
2005  character_len CLSTTO_len = 3;
2006 
2007  alm->fh = lfiouv_mixed_lfi (
2008  alm, KREP, &INUMER, &LLNOMM, CDNOMF,
2009  KNNOMF, CLSTTO, &LLERFA, &LLIMST, &INIMES,
2010  &INBARP, &INBARI, LDRELATIVE, CDNOMF_len, CLSTTO_len,
2011  1, 1, 1, 1 /* Fast, link, copy, unlink */
2012  );
2013 
2014  if (*KREP != 0)
2015  goto end;
2016 
2017  }
2018 
2019  /* Close file */
2020  {
2021  character * CLSTTO = (character *)"KEEP";
2022  character_len CLSTTO_len = 4;
2023  lfi->cb->lfifer (alm, KREP, &INUMER, CLSTTO, CLSTTO_len);
2024 
2025  if (*KREP != 0)
2026  goto end;
2027 
2028  }
2029 
2030  lfi_del_altm_hndl (lfi);
2031 
2032 end:
2033 
2034  if (*KREP != 0)
2035  {
2036  lfi_verb (NULL, "lfi_altm_merge", "KREP", KREP, NULL);
2037  lfi_abor ("lfi_altm_merge");
2038  }
2039 
2040  return;
2041 }
2042 
2043 /* Create an index from several native LFI files */
2044 
2045 void lfi_altm_index_ (integer64 * KREP, character * CDNOMF, integer64 * KNNOMF, logical * LDRELATIVE, character_len CDNOMF_len)
2046 {
2047  lfi_hndl_t * lfi = lfi_get_altm_hndl (NULL);
2048  lfi_altm_t * alm = lfi->data;
2049  integer64 INUMER = 1;
2050 
2051  *KREP = 0;
2052 
2053  /* Open file */
2054  {
2055  integer64 INIMES = 2, INBARP = 0, INBARI = 0;
2056  logical LLNOMM = fort_TRUE, LLERFA = fort_TRUE, LLIMST = fort_TRUE;
2057  character * CLSTTO = (character *)"OLD";
2058  character_len CLSTTO_len = 3;
2059 
2060  alm->fh = lfiouv_mixed_lfi (
2061  alm, KREP, &INUMER, &LLNOMM, CDNOMF,
2062  KNNOMF, CLSTTO, &LLERFA, &LLIMST, &INIMES,
2063  &INBARP, &INBARI, LDRELATIVE, CDNOMF_len, CLSTTO_len,
2064  1, 0, 0, 0 /* Fast, no link, no copy, no unlink */
2065  );
2066 
2067  if (*KREP != 0)
2068  goto end;
2069 
2070  }
2071 
2072  /* Close file */
2073  {
2074  character * CLSTTO = (character *)"KEEP";
2075  character_len CLSTTO_len = 4;
2076  lfi->cb->lfifer (alm, KREP, &INUMER, CLSTTO, CLSTTO_len);
2077 
2078  if (*KREP != 0)
2079  goto end;
2080 
2081  }
2082 
2083  lfi_del_altm_hndl (lfi);
2084 
2085 end:
2086 
2087  if (*KREP != 0)
2088  {
2089  lfi_verb (NULL, "lfi_altm_index", "KREP", KREP, NULL);
2090  lfi_abor ("lfi_altm_index");
2091  }
2092 
2093  return;
2094 }
2095 
2096 
2097 
2098 /*
2099  * Copy a lfi_altm file using hard links
2100  */
2101 void lfi_altm_copy_ (integer64 * KREP, character * CDNOMF1, character * CDNOMF2, logical * LDRELATIVE,
2102  character_len CDNOMF1_len, character_len CDNOMF2_len)
2103 {
2104  lfi_grok_t islfi = lfi_grok (CDNOMF1, CDNOMF1_len);
2105  lfi_hndl_t * lfi = lfi_get_altm_hndl (NULL);
2106  lfi_altm_t * alm = lfi->data;
2107 
2108  *KREP = 0;
2109 
2110  if (islfi == LFI_PURE)
2111  {
2112  LFI_CSTR (cnomf2, CDNOMF2);
2113  /* Link or copy source file */
2114  if ((*KREP = lfi_fsmartcopy (CDNOMF1, CDNOMF2, 1, CDNOMF1_len, CDNOMF2_len)) != 0)
2115  goto clean_alts;
2116  goto end;
2117 clean_alts:
2118  {
2119  int errno_save = errno;
2120  unlink (cnomf2);
2121  errno = errno_save;
2122  goto end;
2123  }
2124  }
2125  else if (islfi == LFI_ALTM)
2126  {
2127  integer64 INUMER = 0;
2128  lfi_altm_fh_t * fh;
2129  int ifh;
2130 
2131  /* Open source file */
2132  {
2133  integer64 INIMES = 2, INBARP = 0, INBARI = 0;
2134  logical LLNOMM = fort_TRUE, LLERFA = fort_TRUE, LLIMST = fort_TRUE;
2135  character * CLSTTO = "OLD";
2136  character_len CLSTTO_len = 3;
2137 
2138  lfi->cb->lfiouv (alm, KREP, &INUMER, &LLNOMM, CDNOMF1, CLSTTO, &LLERFA, &LLIMST,
2139  &INIMES, &INBARP, &INBARI, CDNOMF1_len, CLSTTO_len);
2140 
2141  if (*KREP != 0)
2142  goto end;
2143 
2144  }
2145 
2146  /* Get filehandle */
2147  fh = alm->fh;
2148 
2149  {
2150  LFI_CSTR (cnomf2, CDNOMF2);
2151  int j;
2152 
2153  /* Link sub-files */
2154 
2155  for (ifh = 0; ifh < fh->nfidx; ifh++)
2156  {
2157  const char * cnoml1 = resolve_filename (fh->cnomf, fh->fidx[ifh].cnomf,
2158  strlen (fh->fidx[ifh].cnomf),
2159  NULL); /* Source file */
2160  const char * cnoml2; /* Target file */
2161 
2162  cnoml2 = getfname (cnomf2);
2163 
2164  /* Link sub-file */
2165 
2166  *KREP = lfi_smartcopy (cnoml1, cnoml2, 1);
2167 
2168  free ((void *)cnoml1);
2169 
2170  /* Update sub-file name */
2171  free ((void *)fh->fidx[ifh].cnomf);
2172 
2173  /* Make path of sub-file relative to path of main file */
2174  if (istrue (*LDRELATIVE))
2175  cnoml2 = lfi_make_relative_path (cnomf2, cnoml2);
2176 
2177  fh->fidx[ifh].cnomf = cnoml2;
2178 
2179  if (*KREP != 0)
2180  goto clean_altm;
2181 
2182  }
2183 
2184  }
2185 
2186  /* Replace source file name with destination name */
2187  fh_set_filename (fh, CDNOMF2, CDNOMF2_len);
2188 
2189  /* Write headr */
2190  fh_write_hdr (fh, KREP);
2191 
2192  /* Close */
2193  {
2194  character * CLSTTC = "KEEP";
2195  character_len CLSTTC_len = 4;
2196 
2197  lfi->cb->lfifer (alm, KREP, &INUMER, CLSTTC, CLSTTC_len);
2198 
2199  if (*KREP != 0)
2200  goto clean_altm;
2201 
2202 
2203  goto end;
2204 
2205 clean_altm:
2206  {
2207  int errno_save = errno;
2208  int ifh1;
2209  for (ifh1 = 0; ifh1 < ifh; ifh1++)
2210  {
2211  const char * dir;
2212  dir = lfi_dirname (fh->fidx[ifh1].cnomf);
2213  unlink (fh->fidx[ifh1].cnomf);
2214  rmdir (dir);
2215  free ((void *)dir);
2216  }
2217  errno = errno_save;
2218  goto end;
2219  }
2220 
2221  }
2222 
2223  }
2224  else if (islfi == LFI_NONE)
2225  {
2226  errno = ENOENT;
2227  *KREP = 1;
2228  goto end;
2229  }
2230  else if (islfi == LFI_UNKN)
2231  {
2232  *KREP = -10;
2233  goto end;
2234  }
2235  else
2236  {
2237  lfi_abor ("Unknown return code from lfi_grok");
2238  }
2239 
2240  lfi_del_altm_hndl (lfi);
2241 
2242 end:
2243 
2244  if (*KREP != 0)
2245  {
2246  lfi_verb (NULL, "lfi_altm_copy", "KREP", KREP, NULL);
2247  lfi_abor ("lfi_altm_copy");
2248  }
2249 
2250  return;
2251 }
2252 
2253 /*
2254  * Remove a lfi_altm file
2255  */
2256 void lfi_altm_remove_ (integer64 * KREP, character * CDNOMF, logical * LDFORCE, character_len CDNOMF_len)
2257 {
2258  lfi_grok_t islfi = lfi_grok (CDNOMF, CDNOMF_len);
2259  lfi_hndl_t * lfi = lfi_get_altm_hndl (NULL);
2260  lfi_altm_t * alm = lfi->data;
2261 
2262  *KREP = 0;
2263 
2264  if (islfi == LFI_PURE)
2265  {
2266  LFI_CSTR (cnomf, CDNOMF);
2267  errno = 0;
2268  if (unlink (cnomf))
2269  {
2270  *KREP = errno;
2271  goto end;
2272  }
2273  }
2274  else if (islfi == LFI_ALTM)
2275  {
2276  integer64 INUMER = 0;
2277  lfi_altm_fh_t * fh;
2278 
2279  /* Open source file */
2280  {
2281  integer64 INIMES = 2, INBARP = 0, INBARI = 0;
2282  logical LLNOMM = fort_TRUE, LLERFA = fort_TRUE, LLIMST = fort_TRUE;
2283  character * CLSTTO = "OLD";
2284  character_len CLSTTO_len = 3;
2285 
2286  lfi->cb->lfiouv (alm, KREP, &INUMER, &LLNOMM, CDNOMF, CLSTTO, &LLERFA, &LLIMST,
2287  &INIMES, &INBARP, &INBARI, CDNOMF_len, CLSTTO_len);
2288 
2289  if (*KREP != 0)
2290  goto end;
2291 
2292  }
2293 
2294  /* Get filehandle */
2295  fh = alm->fh;
2296 
2297  {
2298  /* Unlink sub-files */
2299  int ifh;
2300 
2301  for (ifh = 0; ifh < fh->nfidx; ifh++)
2302  {
2303  const char * cnoml = resolve_filename (fh->cnomf, fh->fidx[ifh].cnomf,
2304  strlen (fh->fidx[ifh].cnomf), NULL); /* Source file */
2305  const char * dirnl = lfi_dirname (cnoml);
2306 
2307 
2308  errno = 0;
2309  if (unlink (cnoml) != 0)
2310  {
2311  if (istrue (*LDFORCE))
2312  {
2313  errno = 0;
2314  }
2315  else
2316  {
2317  *KREP = errno;
2318  goto end;
2319  }
2320  }
2321 
2322  lfi_rmdir (dirnl);
2323 
2324  free ((void *)cnoml);
2325  free ((void *)dirnl);
2326  }
2327 
2328  }
2329 
2330  /* Close */
2331  {
2332  character * CLSTTC = "KEEP";
2333  character_len CLSTTC_len = 4;
2334 
2335  lfi->cb->lfifer (alm, KREP, &INUMER, CLSTTC, CLSTTC_len);
2336 
2337  if (*KREP != 0)
2338  goto end;
2339  }
2340 
2341  /* Unlink main file */
2342  {
2343  LFI_CSTR (cnomf, CDNOMF)
2344  errno = 0;
2345  if (unlink (cnomf))
2346  {
2347  *KREP = errno;
2348  goto end;
2349  }
2350  }
2351 
2352  }
2353  else if (islfi == LFI_NONE)
2354  {
2355  errno = ENOENT;
2356  *KREP = 1;
2357  goto end;
2358  }
2359  else if (islfi == LFI_UNKN)
2360  {
2361  *KREP = -10;
2362  goto end;
2363  }
2364  else
2365  {
2366  lfi_abor ("Unknown return code from lfi_grok");
2367  }
2368 
2369  lfi_del_altm_hndl (lfi);
2370 
2371 end:
2372 
2373  if (*KREP != 0)
2374  {
2375  lfi_verb (NULL, "lfi_altm_remove", "KREP", KREP, "CDNOMF", CDNOMF, CDNOMF_len, NULL);
2376  lfi_abor ("lfi_altm_remove");
2377  }
2378 
2379  return;
2380 }
2381 
static void lfierf_altm(LFIERF_ARGS_DECL)
Definition: lfi_altm.c:1732
static lfi_altm_fh_t * lfiouv_pure_lfi(void *LFI, integer64 *KREP, integer64 *KNUMER, logical *LDNOMM, character *CDNOMF, integer64 *KNNOMF, character *CDSTTO, logical *LDERFA, logical *LDIMST, integer64 *KNIMES, integer64 *KNBARP, integer64 *KNBARI, character_len CDNOMF_len, character_len CDSTTO_len, int fast)
Definition: lfi_altm.c:670
lfi_fmul_t * lfi_fmul_get(lfi_fmul_t *fmul, const integer64 *KNUMER, integer64 *KFACTM)
Definition: lfi_fmul.c:36
int(* is_fatl)(struct lfi_hndl_t *, integer64 *)
Definition: lfi_hndl.h:26
void(* lfinaf)(LFINAF_ARGS_DECL)
Definition: lfi_call.h:46
void lfi_altm_index_(integer64 *KREP, character *CDNOMF, integer64 *KNNOMF, logical *LDRELATIVE, character_len CDNOMF_len)
Definition: lfi_altm.c:2045
static const char * blank_index
Definition: lfi_altm.c:43
void lfifra_dumm(LFIFRA_ARGS_DECL)
void lfiosf_miss(LFIOSF_ARGS_DECL)
lfi_hndl_t * lfi_get_altm_hndl(void *data)
Definition: lfi_altm.c:1965
static void lfinaf_altm(LFINAF_ARGS_DECL)
Definition: lfi_altm.c:1525
void lfiosg_dumm(LFIOSG_ARGS_DECL)
static void lfifer_mult(lfi_altm_fh_t *fh)
Definition: lfi_altm.c:623
static void lfiren_altm(LFIREN_ARGS_DECL)
Definition: lfi_altm.c:1546
lfi_fmul_t * lfi_fmul_set(lfi_fmul_t **fmul, const integer64 *KNUMER, const integer64 *KFACTM)
Definition: lfi_fmul.c:15
struct lfi_altm_fh_t lfi_altm_fh_t
void lfiver_dumm(LFIVER_ARGS_DECL)
static void lfiecr_altm(LFIECR_ARGS_DECL)
Definition: lfi_altm.c:1583
lfi_hndl_t * lfi_get_alts_hndl(void *data)
Definition: lfi_alts.c:1792
int lfi_mkdir(const char *path)
Definition: lfi_util.c:157
static void lfiafm_altm(LFIAFM_ARGS_DECL)
Definition: lfi_altm.c:1802
static void lfilas_altm(LFILAS_ARGS_DECL)
Definition: lfi_altm.c:1377
void lfi_altm_copy_(integer64 *KREP, character *CDNOMF1, character *CDNOMF2, logical *LDRELATIVE, character_len CDNOMF1_len, character_len CDNOMF2_len)
Definition: lfi_altm.c:2101
INTERFACE SUBROUTINE FACILO KNIVAU
Definition: facilo.h:4
INTERFACE SUBROUTINE FACILO && KREP
Definition: facilo.h:4
static void lfifer_altm(LFIFER_ARGS_DECL)
Definition: lfi_altm.c:1155
static void lfinmg_altm(LFINMG_ARGS_DECL)
Definition: lfi_altm.c:1872
void lfimst_dumm(LFIMST_ARGS_DECL)
static void lfi_del_altm_hndl(lfi_hndl_t *lfi)
Definition: lfi_altm.c:1929
quick &counting sorts only inumt inumt name
void lficfg_dumm(LFICFG_ARGS_DECL)
static int check_an(const char *CDNOMA, const character_len CDNOMA_len)
Definition: lfi_altm.c:183
lficb_t lficb_altm
Definition: lfi_altm.c:1883
static void lfiopt_altm(LFIOPT_ARGS_DECL)
Definition: lfi_altm.c:1681
int(* is_verb)(struct lfi_hndl_t *, integer64 *)
Definition: lfi_hndl.h:24
static void lfiofm_altm(LFIOFM_ARGS_DECL)
Definition: lfi_altm.c:1780
void(* destroy)(struct lfi_hndl_t *)
Definition: lfi_hndl.h:23
static const char * resolve_filename(const char *base, const char *filename, int filename_len, char *path)
Definition: lfi_altm.c:413
static void lfilec_altm(LFILEC_ARGS_DECL)
Definition: lfi_altm.c:1352
struct lfi_hndl_t * next
Definition: lfi_hndl.h:22
static int lfi_fat_altm_hndl(lfi_hndl_t *lfi, integer64 *KNUMER)
Definition: lfi_altm.c:1954
static const char * getfname(const char *cnomf)
Definition: lfi_altm.c:104
static lfi_altm_t * lookup_alm(void *LFI)
Definition: lfi_altm.c:130
static void lfilaf_altm(LFILAF_ARGS_DECL)
Definition: lfi_altm.c:1306
static lfi_altm_fh_t * lookup_fh(lfi_altm_t *alm, integer64 *KNUMER, int fatal)
Definition: lfi_altm.c:139
FILE * fp
Definition: opfla_perfmon.c:24
void lfista_dumm(LFISTA_ARGS_DECL)
static void lfineg_altm(LFINEG_ARGS_DECL)
Definition: lfi_altm.c:1846
static lfi_hndl_t * _getfhr(const char *base, character *CDNOMF, integer64 *KNUMER, character_len CDNOMF_len)
Definition: lfi_altm.c:442
long long int integer64
Definition: lfi_type.h:15
static int remove_duplicates(lfi_altm_fh_t *fh)
Definition: lfi_altm.c:645
static void fh_write_hdr(lfi_altm_fh_t *fh, integer64 *KREP)
Definition: lfi_altm.c:224
char * lfi_fstrdup(const character *fstr, const character_len len, char *cstr)
Definition: lfi_util.c:30
int lfi_smartcopy(const char *f1, const char *f2, int copy)
Definition: lfi_util.c:140
const char * lfi_dirname(const char *path)
Definition: lfi_util.c:278
static void lfinfo_altm(LFINFO_ARGS_DECL)
Definition: lfi_altm.c:1273
int character_len
Definition: lfi_type.h:17
void lfipxf_miss(LFIPXF_ARGS_DECL)
void(* lfiouv)(LFIOUV_ARGS_DECL)
Definition: lfi_call.h:21
static void lfinim_altm(LFINIM_ARGS_DECL)
Definition: lfi_altm.c:1710
static void lfinum_altm(LFINUM_ARGS_DECL)
Definition: lfi_altm.c:1340
static void lfipos_altm(LFIPOS_ARGS_DECL)
Definition: lfi_altm.c:1259
lfi_grok_t lfi_grok(const character *file, character_len file_len)
Definition: lfi_grok.c:36
struct lfi_altm_fh_aidx_t lfi_altm_fh_aidx_t
void lfideb_dumm(LFIDEB_ARGS_DECL)
lficb_t * cb
Definition: lfi_hndl.h:19
static int check_an_len(const char *CDNOMA, const character_len CDNOMA_len)
Definition: lfi_altm.c:176
char character
Definition: lfi_type.h:18
void lfi_abor(const char *fmt,...)
Definition: lfi_abor.c:21
static lfi_altm_fh_fidx_t getfhw(lfi_altm_fh_t *fh, int new)
Definition: lfi_altm.c:358
void lfiini_dumm(LFIINI_ARGS_DECL)
static void lficas_altm(LFICAS_ARGS_DECL)
Definition: lfi_altm.c:1211
char * lfi_make_relative_path(const char *base, char *path)
Definition: lfi_util.c:207
void lfiomf_dumm(LFIOMF_ARGS_DECL)
character_len lfi_fstrlen(const character *fstr, const character_len len)
Definition: lfi_util.c:20
static void lfisup_altm(LFISUP_ARGS_DECL)
Definition: lfi_altm.c:1496
void lfi_altm_merge_(integer64 *KREP, character *CDNOMF, integer64 *KNNOMF, logical *LDRELATIVE, character_len CDNOMF_len)
Definition: lfi_altm.c:1992
const char * lfi_cleanup_path(char *path)
Definition: lfi_util.c:169
static void lfiouv_altm(LFIOUV_ARGS_DECL)
Definition: lfi_altm.c:1026
void(* lfifer)(LFIFER_ARGS_DECL)
Definition: lfi_call.h:24
static void lfisfm_altm(LFISFM_ARGS_DECL)
Definition: lfi_altm.c:1825
static lfi_altm_fh_t * fh_new(LFIOUV_ARGS_DECL)
Definition: lfi_altm.c:498
static void fh_set_filename(lfi_altm_fh_t *fh, character *CDNOMF, character_len CDNOMF_len)
Definition: lfi_altm.c:405
void * data
Definition: lfi_hndl.h:21
static void lfiomg_altm(LFIOMG_ARGS_DECL)
Definition: lfi_altm.c:1863
struct lfi_altm_t lfi_altm_t
struct lfi_altm_fh_fidx_t lfi_altm_fh_fidx_t
int lfi_fstrcmp(const character *s1, const character *s2, character_len len1, character_len len2)
Definition: lfi_util.c:49
static int lfi_vrb_altm_hndl(lfi_hndl_t *lfi, integer64 *KNUMER)
Definition: lfi_altm.c:1947
lficb_verb_t * cb_verb
Definition: lfi_hndl.h:20
static int lfi_opn_altm_hndl(lfi_hndl_t *lfi, integer64 *KNUMER)
Definition: lfi_altm.c:1940
int lfi_fsmartcopy(const character *cnomf1, const character *cnomf2, int copy, character_len cnomf1_len, character_len cnomf2_len)
Definition: lfi_util.c:132
static void lfioeg_altm(LFIOEG_ARGS_DECL)
Definition: lfi_altm.c:1855
integer64 lfi_fmul_del(lfi_fmul_t **fmul, const integer64 *KNUMER)
Definition: lfi_fmul.c:49
static int seek_rc(lfi_altm_fh_t *fh, int d)
Definition: lfi_altm.c:151
void lfinsg_dumm(LFINSG_ARGS_DECL)
static void lficap_altm(LFICAP_ARGS_DECL)
Definition: lfi_altm.c:1451
int lfi_rmdir(const char *path)
Definition: lfi_util.c:272
static lfi_altm_fh_fidx_t getfhr(lfi_altm_fh_t *fh, int ifh)
Definition: lfi_altm.c:466
static void lfilap_altm(LFILAP_ARGS_DECL)
Definition: lfi_altm.c:1414
INTERFACE SUBROUTINE FACILO KNUMER
Definition: facilo.h:4
static int lookup_rc(lfi_altm_fh_t *fh, character *name, character_len name_len)
Definition: lfi_altm.c:193
static void lfifmd_altm(LFIFMD_ARGS_DECL)
Definition: lfi_altm.c:1758
static void lfiofd_altm(LFIOFD_ARGS_DECL)
Definition: lfi_altm.c:1769
static integer64 iulout(lfi_hndl_t *lfi)
Definition: lfi_verb.c:65
void lfi_altm_remove_(integer64 *KREP, character *CDNOMF, logical *LDFORCE, character_len CDNOMF_len)
Definition: lfi_altm.c:2256
INTERFACE SUBROUTINE FACONO CDNOMA
Definition: facono.h:4
static lfi_altm_fh_t * lfiouv_mult(LFIOUV_ARGS_DECL)
Definition: lfi_altm.c:540
int(* is_open)(struct lfi_hndl_t *, integer64 *)
Definition: lfi_hndl.h:25
static lfi_altm_fh_t * lfiouv_mixed_lfi(void *LFI, integer64 *KREP, integer64 *KNUMER, logical *LDNOMM, character *CDNOMF, integer64 *KNNOMF, character *CDSTTO, logical *LDERFA, logical *LDIMST, integer64 *KNIMES, integer64 *KNBARP, integer64 *KNBARI, logical *LDRELATIVE, character_len CDNOMF_len, character_len CDSTTO_len, int fast, int do_link, int do_copy, int do_unlink)
Definition: lfi_altm.c:749
int rank
Definition: opfla_perfmon.c:19
static void lfioef_altm(LFIOEF_ARGS_DECL)
Definition: lfi_altm.c:1745
int logical
Definition: lfi_type.h:16
lficb_verb_t lficb_verb
Definition: lfi_verb.c:534
void lfi_verb(lfi_hndl_t *lfi, const char *func,...)
Definition: lfi_verb.c:76
lfi_grok_t
Definition: lfi_grok.h:14
static void fh_modified(lfi_altm_fh_t *fh)
Definition: lfi_altm.c:344