#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAXLIGNE 1024
#define MAX 32
int DEB = 0, DOT = 0, ENS = 0;
int NUM = 0;

typedef char CHAINE[MAX];

typedef struct pers_ {
  CHAINE nom, prenom;
  char sexe;
  int  jour, mois, an;
  struct pers_ *pere, *mere;
  CHAINE nom_pere, pre_pere;
  CHAINE nom_mere, pre_mere;
  int node; 
} PERSONNE;

typedef struct ens_ {
     PERSONNE *premier;
  struct ens_ *reste;
  int node;
} ENRENS, *ENSEMBLE;


PERSONNE* persligne( char ligne[MAX] )
{ PERSONNE* res;
  CHAINE n, p, np, nm, pp, pm;
  char s;
  int j, m, a;
  if ( sscanf(ligne, "%s %s %c %d %d %d %s %s %s %s", p, n, &s, &j, &m, &a, pp, np, pm, nm) != 10 )
     return NULL;
  res = ( PERSONNE* ) malloc( sizeof(PERSONNE) );
  strcpy(res->nom, n);
  strcpy(res->prenom, p); 
  res->sexe = toupper(s);
  res->jour = j;
  res->mois = m;
  res->an   = a;
  strcpy(res->nom_pere, np); 
  strcpy(res->nom_mere, nm);
  strcpy(res->pre_pere, pp); 
  strcpy(res->pre_mere, pm);
  res->pere = NULL;
  res->mere = NULL;
  res->node = NUM++;
  return res;
}

void printpers( PERSONNE* p )
{
  printf("\nnom :%s\nprenom:%s (%c) %d/%d/%d", p->nom, p->prenom, p->sexe, p->jour, p->mois, p->an);
  printf("\npere:%s %s", p->nom_pere, p->pre_pere); 
  printf("\nmere:%s %s", p->nom_mere, p->pre_mere);
}

void dotpers( PERSONNE* p )
{
  if (  *(p->pre_pere) != '*' ) 
     printf("\n%s -> %s", p->prenom, p->pre_pere); 
  if (  *(p->pre_mere) != '*' ) 
     printf("\n%s -> %s", p->prenom, p->pre_mere);
}

void freepers(PERSONNE* p)
{
  free( p );
}

void  Lecture( FILE *src)
{
 char ligne[MAXLIGNE];
  PERSONNE* pers;
  int nbligne=0;
  while ( ! feof( src) ) {
      fgets( ligne, MAXLIGNE, src );
      nbligne++;
      printf("\nLIGNE %d=%s", nbligne, ligne);
      pers = persligne( ligne );
      if ( pers ) {
        printpers( pers );
        freepers(  pers );
      } else fgetc( src );
  }
}

void  FormatDot( FILE *src)
{
 char ligne[MAXLIGNE];
 PERSONNE* pers;
    printf("\ndigraph {");
    printf("\n ratio=\"auto\"");  
    printf("\n size=\"16,8\""); 
    printf("\n  node [shape = circle];" );
    
    while ( ! feof( src) ) {
      fgets( ligne, MAXLIGNE, src );
      pers = persligne( ligne );
      if ( pers ) {
       dotpers( pers);
       freepers( pers );
      } else fgetc( src );
    }
    printf("\n}");
}

ENSEMBLE LireEnsemble( FILE *src) 
{ char ligne[MAXLIGNE];
  PERSONNE* pers;
  ENSEMBLE aux, res = NULL;
  while ( ! feof( src) ) {
      fgets( ligne, MAXLIGNE, src );
      pers = persligne( ligne );
      if ( pers ) {
	aux = ( ENSEMBLE) malloc( sizeof(ENRENS) );
	aux->premier= pers;
        aux->reste  = res;
	aux->node = NUM++;
	res = aux;
      } else fgetc( src );
    }
  return res;
}

void printnode( ENSEMBLE ens)
{  
  while ( ens != NULL ) {
    printf("\n\"node%d\" [ color=red , label = \"<f0>%p|<f1>%p\", shape = \"record\" ];", ens->node, ens->premier, ens->reste);
    printf("\n\"node%d\" [ label = \"<g0>%s", ens->premier->node, ens->premier->prenom);
    printf("|%c|%d-%d-%d|<pere>%p|<mere>%p\", shape = \"record\" ];", ens->premier->sexe, ens->premier->jour,ens->premier->mois, ens->premier->an, ens->premier->pere, ens->premier->mere);
    ens = ens->reste;
    } 

}

void printsvt( ENSEMBLE ens)
{  
  while ( ens->reste != NULL ) {
    printf("\n\"node%d\":f1 -> \"node%d\":f0 ;", ens->node, ens->reste->node);
    ens = ens->reste;
    } 

}
void printarc( ENSEMBLE ens)
{  
  while ( ens ) {
    printf("\n\"node%d\":f0 -> \"node%d\":g0 ;", ens->node, ens->premier->node);
    ens = ens->reste;
    } 

}

void printfil( ENSEMBLE ens)
{  
  while ( ens ) {
    if ( ens->premier->pere ) 
      printf("\n\"node%d\":pere -> \"node%d\":g0 ;", ens->premier->node, ens->premier->pere->node);  
    if ( ens->premier->pere ) 
      printf("\n\"node%d\":mere -> \"node%d\":g0 ;", ens->premier->node, ens->premier->mere->node);
    ens = ens->reste;
    } 

}

PERSONNE* idpers( char *nom, char *pre, ENSEMBLE ens)
{ while ( ens ) {
    if ( strcmp( nom, ens->premier->nom) == 0 )
      if ( strcmp( pre, ens->premier->prenom) == 0 )
	return ens->premier;
    ens = ens->reste;
    } 
  return NULL;
}

void arbre( ENSEMBLE ens)
{ ENSEMBLE aux = ens;
  while ( ens ) {
    ens->premier->pere = idpers( ens->premier->nom_pere, ens->premier->pre_pere, aux) ; 
    ens->premier->mere = idpers( ens->premier->nom_mere, ens->premier->pre_mere, aux) ;
    ens = ens->reste;
    } 

}

int main( int argc, char* argv[] )
{
  FILE *src;
  ENSEMBLE ens;
  src = fopen( argv[1] , "r");
  if ( ! src ) {
    printf("\nFichier %s : introuvable!\n", argv[1]);
    return(1);
  }
  if ( argv[2] ) 
    switch( argv[2][0] ) {
      case 'd' : DEB = 1; break;
      case 'g' : DOT = 1;   break;
      case 'e' : ENS = 1;   break;
    }
 
  if ( DEB ) Lecture( src );
  if ( DOT )   FormatDot( src );

  if ( ENS ) {
    ens = LireEnsemble( src ); 
    arbre( ens );
    printf("\ndigraph {");
    printf("\n graph [ \n  rankdir = \"LR\" ];");
    printf("\n node [ fontsize = \"16\" shape = \"ellipse\" ];");
    printf("\n size=\"18,10\""); 
    arbre( ens ); 
    printnode( ens );
    printsvt( ens );
    printarc( ens );
    printfil( ens );
    printf("\n}");
  }
  fclose(src);
  return 0;
}
