
#include "RobboLito.h"
#include "RobboTotalBase.h"
#include "RobboTripleBase.h"

#define VERBOSO FALSE

#define CHECK_BYTE(x, y) \
  if ((x) != (y)) \
    { SEND ("Bad DynamicLoad watermark %5s %d %d\n", rtb->string, x, y); \
      return; }

static uint32 fgetI (FILE* F)
{
  int i;
  uint32 r = 0;
  for (i = 0; i < 4; i++)
    r |= (fgetc (F) << (8 * i));
  return r;
}

static void RobboDynamicLoadSetUp (RobboTripleBase* rtb, FILE* F)
{
  uint64 sz = rtb->size;
  uint64 heaps = (sz >> 30) + 1;
  int u, v, i, j, b, uc, hsz, uu;
  LOAD_COUNT++;
  CHECK_BYTE (fgetc (F), 0x53);
  CHECK_BYTE (fgetc (F), 0xa1);
  CHECK_BYTE (fgetc (F), 0x78);
  CHECK_BYTE (fgetc (F), 0x0e);
  u = fgetc (F);
  v = fgetc (F);
  rtb->prop_ind = u | (v << 8);
  if (u != 0x40)
    SEND ("Dynamic Load requires 64 byte canals. Bytes %d\n", u);
  u = fgetc (F);
  if (u != 18)
    SEND ("Dynamic Load requires shift of 18. Shift %d\n", u);
  u = fgetc (F);
  if (u != heaps)
    SEND ("Heap count corrupted in DynamicLoad %d %d %s " TYPE_64_BIT "\n",
	  u, heaps, rtb->string, rtb->size);
  u = fgetI (F); /* NULL bytes 0xc:0xf */
  for (i = 0; i < heaps; i++)
    {
      uu = fgetI (F);
      u = uu & 0xfffffff;
      u &= 0xfffffff;
      b = 0;
      uc = u;
      while (uc >>= 1)
	b++;
      rtb->packet_count[i] = u;
      rtb->bs_split[i] = b - 1;
      rtb->ind_split[i] = malloc ((2 << b) * sizeof (uint32));
      rtb->packet_offset[i] = malloc (u * sizeof (uint32));
      for (j = 0; j < u; j++)
	rtb->ind_split[i][j] = fgetI (F);
      for (j = u; j < (2 << b); j++)
	rtb->ind_split[i][j] = (0x3fffffffULL << 2) | 0;
      for (j = 0; j < u; j++)
	rtb->packet_offset[i][j] = fgetI (F);
      if (uu & 0x10000000) /* (omit) */
	{
	  CHECK_BYTE (fgetc (F), 0x93);
	  CHECK_BYTE (fgetc (F), 0x06);
	  CHECK_BYTE (fgetc (F), 0xe1);
	  CHECK_BYTE (fgetc (F), 0x88);
	  hsz = fgetI (F);
	  MEMALIGN (rtb->huffman_table[i], 0x40, hsz * sizeof (uint32));
	  for (j = 0; j < hsz; j++)
	    rtb->huffman_table[i][j] = fgetI (F);
	}
    }
}

void OpenTripleFile (RobboTripleBase*); /* declare */

void DetachDirectDynamicLoad (RobboTripleBase* rtb)
{
  int heap;
  if (!rtb->direct)
    return;
  if (!(rtb->variant & ROBBO_DYNAMIC_LOAD))
    return;
  if (rtb->w[2] == 0) /* occur */
    return;
  rtb->direct = FALSE;
  for (heap = 0; heap < 1 + (rtb->size >> 30); heap++)
    {
      ALIGNED_FREE (rtb->direct_cache[heap].INDEX);
      ALIGNED_FREE (rtb->direct_cache[heap].DATA);
    }      
  BULK_COUNT--;
  BULK_BYTES -= rtb->by;
  BULK_IND -= rtb->index;
}

void IncurDirectDynamicLoad (RobboTripleBase* rtb)
{
  int heap, slice, ind, bytes, ind_sz, byte_sz, SLICES;
  if (rtb->direct) /* in the all ready */
    return;
  rtb->direct = TRUE;
  BULK_COUNT++;
  if (!rtb->disk)
    OpenTripleFile (rtb);
  rtb->index = rtb->by = 0;
  for (heap = 0; heap < 1 + (rtb->size >> 30); heap++)
    {
      ind_sz = byte_sz = 0;
      SLICES = rtb->packet_count[heap];
      fseek (rtb->disk, rtb->packet_offset[heap][SLICES - 1], SEEK_SET);
      CHECK_BYTE (fgetc (rtb->disk), 0xf2);
      CHECK_BYTE (fgetc (rtb->disk), 0x77);
      CHECK_BYTE (fgetc (rtb->disk), 0x83);
      CHECK_BYTE (fgetc (rtb->disk), 0x83);
      fread (&ind, 4, 1, rtb->disk);
      fread (&bytes, 4, 1, rtb->disk); /* ENDIAN ? */
      ind = (0x1220 * (SLICES - 1) + ind);
      if (ind & 0xf)
	ind += 0x10 - (ind & 0xf);
      MEMALIGN (rtb->direct_cache[heap].INDEX, 0x40, ind * sizeof (uint32));
      bytes = (0x40000 * (SLICES - 1) + bytes);
      if (bytes & 0x3f)
	bytes += 0x40 - (ind & 0x3f);
      MEMALIGN (rtb->direct_cache[heap].DATA, 0x40, bytes);
      for (slice = 0; slice < SLICES; slice++)
	{
	  fseek (rtb->disk, rtb->packet_offset[heap][slice], SEEK_SET);
	  CHECK_BYTE (fgetc (rtb->disk), 0xf2);
	  CHECK_BYTE (fgetc (rtb->disk), 0x77);
	  CHECK_BYTE (fgetc (rtb->disk), 0x83);
	  CHECK_BYTE (fgetc (rtb->disk), 0x83);
	  fread (&ind, 4, 1, rtb->disk);
	  fread (&bytes, 4, 1, rtb->disk);
	  fread (rtb->direct_cache[heap].INDEX + ind_sz, 4, ind, rtb->disk);
	  fread (rtb->direct_cache[heap].DATA + byte_sz, 1, bytes, rtb->disk);
	  ind_sz += ind;
	  byte_sz += bytes;
	  BULK_BYTES += bytes;
	  BULK_IND += ind;
	}
      rtb->index += ind_sz;
      rtb->by += byte_sz;
    }
  fclose (rtb->disk);
  rtb->disk = NULL; /* for the import */ /* FCLOSE_NULL (rtb->disk); */
}

void ReFactorDirectoryNaming (char*); /* pre define */
uint64 bytesTRIPLE = 0, indTRIPLE = 0, indTRIPLEx = 0;
void load_triple (char *fnin, char *DIR)
{
  int u, i, by, n, j, PR, ni, s;
  char FN[1024], NOME[1024];
  RobboTripleBase* triple;
  FILE* F;
  char TEMP[1024];
  strcpy (NOME, fnin);
  for (i = 0; NOME[i] != '.'; i++) ;
  strcpy (TEMP, fnin + 1 + i); /* HACK */
  if (TEMP[0] == 'K' || TEMP[0] == 'k')
    un_windows_triple (TEMP);
  s = strlen (TEMP);
  sprintf (FN, "%s/%s%s", DIR, TRIPLE_PREFISSO, NOME);
  F = fopen (FN, "rb");
  if (F == NULL)
    {
      printf ("No File %s\n", FN);
      return;
    }
  if (VERBOSO)
    printf ("RobboTriple %d %s ", NUM_TRIPLE_BASES, FN);
  for (i = 1; i <= 4; i++)
    TEMP[s + i] = 0;
  triple = TABLE_TRIPLE_BASES + NUM_TRIPLE_BASES;
  robbo_triple_utilita (triple, TEMP);
  strcpy (triple->DIR_NOME, DIR);
#ifndef WINDOWS
  strcat (triple->DIR_NOME, "/");
#else
  strcat (triple->DIR_NOME, "\\");
#endif
  ReFactorDirectoryNaming (triple->DIR_NOME); /* HACK */
  strcpy (triple->string, NOME + 2);
  sprintf (triple->path, "%s%s", TRIPLE_PREFISSO, NOME);
  triple->direct = FALSE;
  triple->data = NULL;
  triple->ind = NULL;
  triple->disk = NULL;
  triple->size = triple->pawns ? 1806 : 462;
  triple->weak = triple->hit = 0; /* count */
  triple->scacco = FALSE; /* unless impelled */
  for (i = 0; i < 4; i++)
    if (triple->p[i])
      TRIPLE_MAX_USAGE = MAX (TRIPLE_MAX_USAGE, (i + 3));
  for (i = 0; i < 4; i++)
    triple->size *= triple->m[i];
  for (i = 1; i <= 3; i++)
    {
      u = fgetc (F); /* 3 results */
      triple->w[i] = u;
    }
  if (triple->w[2] == 0)
    {
      triple->direct = TRUE; /* HACK */
      triple->w[3] = 0; /* fixed */
      fclose (F);
      F = 0;
      if (VERBOSO)
	printf ("una resulta %s %d\n", FN, triple->w[1]);
      TRIVIALLY_COUNT++;
      return;
    }
  for (i = 1; i <= 3; i++)
    triple->wi[triple->w[i]] = i;
  if (VERBOSO)
    printf ("w: %d/%d/%d  ", triple->w[1], triple->w[2], triple->w[3]);
  u = fgetc (F); /* dummy byte */ /* holder indicative */
  triple->variant = u;
  if (u & ROBBO_SCACCO_KNOW_BIT)
    triple->scacco = ((u & ROBBO_SCACCO_BIT) != 0); /* SCACCO */
  else
    triple->scacco = (triple->p[2] != 0); /* constrain old 5 piece */
  if (u & ROBBO_DYNAMIC_LOAD)
    {
      RobboDynamicLoadSetUp (triple, F);
      fclose (F);
      if (0 && u & ROBBO_DIRECT_DYNAMIC_BIT) /* for the off */
	IncurDirectDynamicLoad (triple);
      return;
    }    
  triple->direct = TRUE; /* HACK */
  by = 0;
  for (i = 0; i < 4; i++)
    by += (fgetc (F) << (8 * i)); /* bytes */
  if (VERBOSO)
    printf ("%d by  ", by);
  n = 0;
  for (i = 0; i < 4; i++)
    n += (fgetc (F) << (8 * i)); /* stored impulse size */
  if (VERBOSO)
    printf ("%d arch  ", n);
  PR = 0;
  for (i = 0; i < 2; i++)
    PR += (fgetc (F) << (8 * i)); /* bytes per index */
  if (VERBOSO)
    printf ("PR %d  ", PR);
  for (i = 0; i < 2; i++)
    fgetc (F); /* dummy bytes (2) */
  ni = by / PR; /* index count for total bytes over byte size */
  triple->prop_ind = PR;
  u = ni;
  i = 0;
  while (u >>= 1)
    i++;
  triple->bs = i - 1;
  triple->index = (2 << i) - 1; /* lopside */
  triple->ind = malloc ((triple->index + 1) * sizeof (int));
  for (i = 0; i < ni; i++)
    {
      u = 0;
      for (j = 0; j < 4; j++)
	u += (fgetc (F) << (8 * j)); /* index */
      triple->ind[i] = u;
    }
  for (i = ni; i < triple->index + 1; i++) /* HACK */
    triple->ind[i] = (n * 4);
  DIRECT_COUNT++;
  triple->by = by;
  bytesTRIPLE += by;
  indTRIPLE += triple->index + 1;
  indTRIPLEx += ni;
  triple->data = malloc (PR * ni);
  fread (triple->data, 1, PR * ni, F); /* data bytes */
  if (VERBOSO)
    {
      printf ("data (10): ");
      for (i = 0; i < 10; i++)
	printf ("%x ", triple->data[i]);
    }
  if (VERBOSO)
    printf ("\n");
  fclose (F);
}

void triple_statistica ()
{
  SEND ("info string %d RobboTripleBases (%dmb): " TYPE_64_BIT " data "
	TYPE_64_BIT "+" TYPE_64_BIT " indici\n",
	NUM_TRIPLE_BASES, 1 + (NUM_TRIPLE_BASES / 256) +
	(int) ((bytesTRIPLE + (indTRIPLE * 4)) >> 20),
	bytesTRIPLE, indTRIPLE, indTRIPLEx);
}

void TripleEmit ()
{
  SEND ("info string Now %d RobboTripleBases in all\n", NUM_TRIPLE_BASES);
  SEND ("info string %d CompleteDirect (%dmb) plus %d BulkDynamic (%dmb)\n",
	DIRECT_COUNT, (int) ((bytesTRIPLE + (indTRIPLE * 4)) >> 20),
	BULK_COUNT, (int) ((BULK_BYTES + (BULK_IND * 4)) >> 20));	
  SEND ("info string Loadable are %d more RobboTripleBases" " "
	"Plus: %d buy the trivially!\n", LOAD_COUNT - BULK_COUNT, TRIVIALLY_COUNT);
}

#ifndef WINDOWS
void ReFactorDirectoryNaming (char* S) /* demur multiple  slashes, end with slash */
{
  char T[1024];
  int i, j = 0;
  for (i = 0; S[i]; i++)
    {
      if (i > 0 && S[i - 1] == '/' && S[i] == '/')
	continue;
      T[j++] = S[i];
    }
  if (T[j - 1] != '/')
    T[j++] = '/';
  T[j] = 0;
  strcpy (S, T);
}
#else
void ReFactorDirectoryNaming (char* S) 
{
  char T[1024];
  int i, j = 0;
  for (i = 0; S[i]; i++)
    if (S[i] =='/')
      S[i] = '\\'; /* PeterPan */
  for (i = 0; S[i]; i++)
    {
      if (i > 0 && S[i - 1] == '\\' && S[i] == '\\')
	continue;
      T[j++] = S[i];
    }
  if (T[j - 1] != '\\')
    T[j++] = '\\';
  T[j] = 0;
  strcpy (S, T);
}
#endif

void BulkLoadDirectory (char* T)
{
  int i;
  char S[4096];
  strcpy (S, T);
  ReFactorDirectoryNaming (S);
  SEND ("info string RobboBulkLoad for registered TripleBases with directory %s\n",S);
  for (i = 0; i < NUM_TRIPLE_BASES; i++)
    if (!strcmp (S, (TABLE_TRIPLE_BASES + i)->DIR_NOME))
      IncurDirectDynamicLoad (TABLE_TRIPLE_BASES + i);
}

int RobboBulkDirectory ()
{
  char TEMP[4096];
  char* p;
  strcpy (TEMP, ROBBO_BULK_DIRECTORY);
  ReFactorDirectoryNaming (TEMP);
  for (p = strtok (TEMP, "|"); p != NULL; p = strtok (NULL, "|"))
    BulkLoadDirectory (p);
  TripleEmit ();
  return TRUE;
}

void BulkLoadOne (char* S)
{
  RobboTripleBase* triple;
  triple = LookupTriple (S);
  if (triple == NULL)
    {
      SEND ("info string Unfound string in BulkLoad %s\n", S);
      return FALSE; /* indicative */
    }
  if (triple->efgh1 != -1 && strcspn (S, "EFGHefghIJijUVWX") == strlen (S))
    {
      int i;
      for (i = 0; i < 4; i++)
	IncurDirectDynamicLoad (TABLE_TRIPLE_BASES + (triple->efgh[i]));
    }
  else
    IncurDirectDynamicLoad (triple);
}

int RobboBulkLoad ()
{
  char TEMP[4096];
  char* p;
  strcpy (TEMP, ROBBO_BULK_NAME);
  for (p = strtok (TEMP, "|"); p != NULL; p = strtok (NULL, "|"))
    BulkLoadOne (p);
  TripleEmit ();
  return TRUE;
}

void BulkDetachOne (char* S)
{
  RobboTripleBase* triple;
  triple = LookupTriple (S);
  if (triple == NULL)
    {
      SEND ("info string Unfound string in BulkDetach %s\n", S);
      return FALSE; /* indicative */
    }
  if (triple->efgh1 != -1 && strcspn (S, "EFGHefghIJijUVWX") == strlen (S))
    {
      int i;
      for (i = 0; i < 4; i++)
	DetachDirectDynamicLoad (TABLE_TRIPLE_BASES + (triple->efgh[i]));
    }
  else
    DetachDirectDynamicLoad (triple);
}

int RobboBulkDetach ()
{
  char TEMP[4096];
  char* p;
  strcpy (TEMP, ROBBO_BULK_NAME);
  for (p = strtok (TEMP, "|"); p != NULL; p = strtok (NULL, "|"))
    BulkDetachOne (p);
  TripleEmit ();
  return TRUE;
}

void BulkDetachDirectory (char* T)
{
  int i;
  char S[4096];
  strcpy (S, T);
  ReFactorDirectoryNaming (S);
  SEND ("info string RobboBulkLoad for registered TripleBases with directory %s\n",S);
  for (i = 0; i < NUM_TRIPLE_BASES; i++)
    if (!strcmp (S, (TABLE_TRIPLE_BASES + i)->DIR_NOME))
      DetachDirectDynamicLoad (TABLE_TRIPLE_BASES + i);
}

int RobboBulkDirectoryDetach ()
{
  char TEMP[4096];
  char* p;
  strcpy (TEMP, ROBBO_BULK_DIRECTORY);
  ReFactorDirectoryNaming (TEMP);
  for (p = strtok (TEMP, "|"); p != NULL; p = strtok (NULL, "|"))
    BulkDetachDirectory (p);
  TripleEmit ();
  return TRUE;
}


#define WINDOWS_TRIPLE_PREFISSO "triple"
static void add_nome_triple (char* NOME, char *DIR)
{
  int n = strlen (TRIPLE_PREFISSO);
  if (strstr (NOME, "TRIPLE_") || strstr (NOME, "triple_"))
    return;
  if (strstr (NOME, "bz2") || strstr (NOME, "00") || strstr (NOME, "tar"))
    return;
  if (memcmp (NOME, TRIPLE_PREFISSO, n) && memcmp (NOME, WINDOWS_TRIPLE_PREFISSO,n))
    return;
  load_triple (NOME + n, DIR);
}

/********/ /********/ /********/ /********/ /********/ /********/ /********/

void hack_windows_triple (char* NOME);
static void BlockTripleIndexRegister (char* DIR, FILE* F) /* for the TEST? */
{
  char NOME[16], TEMP[16], TEMP2[16];
  uint8 A[4];
  unsigned char B[16];
  RobboTripleBase* triple;
  int i, heaps, h, j;
  boolean IS_OK;
  char NOME_FILE[1024], PATH[128];
  NOME[4] = 0;
  while (fread (B, 1, 4, F)) /* 0x09 0x36 0xf4 0x2b */
    {
      if (B[0] != 0x09 || B[1] != 0x36 || B[2] != 0xf4 || B[3] != 0x2b)
        {
          SEND ("BlockIndex mask failure!\n");
          return;
        }
      fread (NOME, 1, 4, F); /* initials of file */
      if (NOME[2] == 0)
	{
	  strcpy (TEMP, NOME);
	  sprintf (NOME_FILE, "%s/TRIPLE0.%s", DIR, TEMP);
	  if (STAT (NOME_FILE) == -1)
	    {
	      if (TEMP[0]=='K' || TEMP[0]=='k')
		un_windows (TEMP);
	      else
		hack_windows_triple (TEMP);
	      sprintf (NOME_FILE, "%s/TRIPLE0.%s", DIR, TEMP);
	      if (STAT (NOME_FILE) == -1)
		continue;
	    }
	  strcpy (TEMP2, "0.");
	  strcat (TEMP2, TEMP);
	  load_triple (TEMP2, DIR); /* HACK */
	  continue;
	}
      fread (A, 1, 4, F); /* results and variant */
      if (A[1] == 0) /* onely result */
	{
	  triple = TABLE_TRIPLE_BASES + NUM_TRIPLE_BASES;
	  robbo_triple_utilita (triple, NOME);
	  triple->direct = TRUE;
	  triple->w[1] = A[0];
	  triple->w[2] = triple->w[3] = 0;
	  TRIVIALLY_COUNT++;
	  continue;
	}
      strcpy (TEMP, NOME);
#ifdef NOME_WINDOWS
      hack_windows_triple (TEMP);
#endif
      sprintf (PATH, "TRIPLE%c.%s", NOME[3] ? '2' : '3', TEMP);
      sprintf (NOME_FILE, "%s/%s", DIR, PATH);
      if (STAT (NOME_FILE) == -1)
	{
	  if (TEMP[0]=='K' || TEMP[0]=='k')
	    un_windows (TEMP);
	  else
	    hack_windows_triple (TEMP);
	  sprintf (PATH, "TRIPLE%c.%s", NOME[3] ? '2' : '3', TEMP);
	  sprintf (NOME_FILE, "%s/%s", DIR, PATH);
	  if (STAT (NOME_FILE) == -1)
	    IS_OK = FALSE;
	  else
	    IS_OK = TRUE;
	}
      else
	IS_OK = TRUE;
      triple = TABLE_TRIPLE_BASES + NUM_TRIPLE_BASES; /* HACK */
      if (IS_OK)
	{
	  robbo_triple_utilita (triple, NOME);
	  strcpy (triple->DIR_NOME, DIR);
#ifndef WINDOWS
	  strcat (triple->DIR_NOME, "/");
#else
	  strcat (triple->DIR_NOME, "\\");
#endif
	  ReFactorDirectoryNaming (triple->DIR_NOME); /* HACK */
	  strcpy (triple->string, NOME);
	  strcpy (triple->path, PATH);
	}
      triple->direct = FALSE;
      triple->data = NULL;
      triple->ind = NULL;
      triple->disk = NULL;
      triple->size = triple->pawns ? 1806 : 462;
      triple->weak = triple->hit = 0; /* count */
      triple->scacco = FALSE; /* unless impelled */
      for (i = 1; i <= 3; i++)
	triple->w[i] = A[i - 1];
      for (i = 1; i <= 3; i++)
	triple->wi[triple->w[i]] = i;
      triple->variant = A[3];
      for (i = 0; i < 4; i++)
	if (triple->p[i] && IS_OK)
	  TRIPLE_MAX_USAGE = MAX (TRIPLE_MAX_USAGE, (i + 3));
      for (i = 0; i < 4; i++)
	triple->size *= triple->m[i];
      fread (A, 1, 4, F);
      heaps = A[3]; /* HACK */
      for (h = 0; h < heaps; h++)
	{
	  int u = fgetI (F);
	  int t = u;
	  int b = 0;
	  while (t >>= 1)
	    b++;
	  triple->packet_count[h] = u;
	  triple->bs_split[h] = b - 1;
	  triple->ind_split[h] = malloc ((2 << b) * sizeof (uint32));
	  triple->packet_offset[h] = malloc (u * sizeof (uint32));
	  for (j = 0; j < u; j++)
	    triple->ind_split[h][j] = fgetI (F);
	  for (j = u; j < (2 << b); j++)
	    triple->ind_split[h][j] = (0x3fffffffULL << 2) | 0;
	  for (j = 0; j < u; j++)
	    triple->packet_offset[h][j] = fgetI (F);	    
	}
      if (!IS_OK)
	{
	  for (h = 0; h < heaps; h++)
	    free (triple->ind_split[h]);
	  for (h = 0; h < heaps; h++)
	    free (triple->packet_offset[h]);
	}
      else
	LOAD_COUNT++;
    }
  TripleEmit ();
}

static boolean HasTripleBlockIndex (char* DIR)
{
  FILE* F;
  char NAME[256];
  sprintf (NAME, "%s/BLOCK_TRIPLE.INDEX", DIR);
  F = fopen (NAME, "rb");
  if (!F)
    return FALSE;
  SEND ("Using BLOCK_TRIPLE.INDEX for %s\n", DIR);
  BlockTripleIndexRegister (DIR, F);
  fclose (F);
  return TRUE;
}

#ifdef WINDOWS
void GetTripleBase (char* A)
{
  char B[1024];
  WIN32_FIND_DATA ffd;
  HANDLE hFind = INVALID_HANDLE_VALUE;

  if (HasTripleBlockIndex (A))
    return;
  SEND ("info string Reading directory %s\n", A);
  strcpy (B, A);
  strcat (B, "\\*");
  hFind = FindFirstFile (B, &ffd);
  if (hFind == INVALID_HANDLE_VALUE)
    {
      SEND ("info string Directory %s not found\n", A);
      return;
    }
  do
    {
      if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        add_nome_triple (ffd.cFileName, A);
    }
  while (FindNextFile (hFind, &ffd));
  FindClose (hFind);
  TripleEmit ();
}
#else
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>

void GetTripleBase (char* A)
{
  DIR* DIR;
  struct dirent DE[1], *ptr;
  if (HasTripleBlockIndex (A))
    return;
  SEND ("info string Reading directory %s\n", A);
  DIR = opendir (A);
  if (!DIR)
    {
      SEND ("info string Directory %s not found\n", A);
      return;
    }
  while (1)
    {
      readdir_r (DIR, DE, &ptr);
      if (!ptr) break;
      add_nome_triple (DE->d_name, A);
    }
  closedir (DIR);
  TripleEmit ();
}
#endif
