Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /** \file
- * maquefilereader.c : source pour la lecture des maquefiles
- * \copyright Vincent Loechner, 2014.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "maquefilereader.h"
- /* longueur max d'une ligne du fichier d'entrée */
- #define MAXLINESIZE 4000
- /* bloc d'allocation de base des commandes (realloc tous les ...) */
- #define CMD_ALLOC_SIZE 10
- /**
- * trouve un noeud dans un graphe d'après le nom de la cible
- * \param [in] g pointeur sur le (Graphe)
- * \param [in] cible nom de la cible cherchée (chaine de caractères)
- * \return pointeur sur le (Noeud) recherché, ou NULL si non trouvé.
- */
- Noeud *TrouveNoeud( Graphe *g, char *cible )
- {
- for( ; g ; g=g->suiv )
- {
- if( strcmp(g->n->nom, cible) == 0 ) // trouvé !
- return( g->n );
- }
- return( NULL );
- }
- /**
- * ajoute un nouveau noeud dans un graphe
- * \param [inout] g pointeur sur le (Graphe)
- * \param [in] cible nom de la cible à ajouter (chaine de caractères)
- * \return pointeur sur le nouveau (Graphe)
- */
- Graphe *AjouteNoeud( Graphe *g, char *cible )
- {
- Graphe *nouv;
- // liste de noeuds du graphe +1
- nouv = malloc( sizeof(Graphe) );
- nouv->suiv = g;
- nouv->n = malloc( sizeof( Noeud ) );
- nouv->n->commandes = NULL;
- nouv->n->flag = 0;
- strcpy( nouv->n->nom, cible );
- nouv->n->pred = NULL;
- nouv->n->succ = NULL;
- return( nouv );
- }
- /**
- * lit un fichier maquefile
- * \param [in] fname nom du fichier (chaine de caractères)
- * \return pointeur sur le nouveau (Graphe)
- */
- Graphe *LireMaquefile( char *fname )
- {
- FILE *f;
- Graphe *g;
- char *con;
- char s[MAXLINESIZE];
- int lineno = 0;
- if( !(f=fopen( fname, "r" )) )
- {
- perror(fname);
- return( NULL );
- }
- g = NULL;
- con = fgets( s, MAXLINESIZE, f);
- lineno++;
- // lire des règles
- while( con != NULL )
- {
- char *cible, *dep;
- Noeud *nc;
- char *token;
- // fgets lit le \n final, je le supprime :
- if( s[strlen(s)-1] == '\n' )
- s[strlen(s)-1] = '\0';
- if( strstr( s, ":" ) == NULL )
- // pas une règle, ignore et continue
- {
- cible = strtok_r( s, " \t:", &token );
- if( cible && cible[0]!='#' )
- fprintf( stderr,
- "WARNING: not a rule, ignoring line %d\n", lineno );
- if( fgets( s, MAXLINESIZE, f) == NULL )
- con = 0;
- lineno++;
- continue;
- }
- // ignore les espaces et les tabulations :
- cible = strtok_r( s, " \t:", &token );
- if( cible==NULL || cible[0]=='#' )
- // ligne vide ou commentaire, ignore et passe à la suite
- {
- if( fgets( s, MAXLINESIZE, f) == NULL )
- con = 0;
- continue;
- }
- // si ce noeud n'existe pas encore on le crée
- if( (nc = TrouveNoeud( g, cible )) == NULL )
- {
- g = AjouteNoeud( g, cible );
- nc = g->n;
- }
- // n est le noeud cible (nouveau ou existant).
- // lit les dépendances
- // séparées par espaces ou tabs
- while( (dep=strtok_r( NULL, " \t", &token )) != NULL )
- {
- Noeud *nd;
- // n'existe pas encore, on le crée
- if( (nd = TrouveNoeud( g, dep )) == NULL )
- {
- g = AjouteNoeud( g, dep );
- nd = g->n;
- }
- // ajoute les dépendances :
- // cible dépend de dep
- // et dep succède à cible
- Liste *d;
- // ajoute cible aux successeurs dep
- d = malloc( sizeof(Liste) );
- d->suiv = nd->succ;
- d->n = nc;
- nd->succ = d;
- // ajoute dep aux prédécesseurs de cible
- d = malloc( sizeof(Liste) );
- d->suiv = nc->pred;
- d->n = nd;
- nc->pred = d;
- }
- // lit les commandes et les place dans nc->commandes
- int pos = 0;
- if( nc->commandes == NULL )
- nc->commandes = malloc( sizeof(char *)*CMD_ALLOC_SIZE );
- else
- {
- fprintf( stderr,
- "Warning: duplicate target '%s'. Merging.\n",
- nc->nom );
- while( nc->commandes[pos] != NULL )
- pos++;
- }
- while( (con=fgets( s, MAXLINESIZE, f )) != NULL )
- {
- char *posmacro;
- lineno++;
- // les commandes commencent obligatoirement par un <tab>
- if( s[0]!='\t' )
- break;
- // s va être lu comme une règle à l'itération suivante.
- // fgets lit le '\n' final, je le supprime :
- if( s[strlen(s)-1] == '\n' )
- s[strlen(s)-1] = '\0';
- // remplace $@ et $*
- while( (posmacro=strstr(s,"$@")) != NULL )
- {
- int i,len=strlen(nc->nom);
- // copie la fin au bon endroit
- if( len>2 )
- for( i=strlen(posmacro) ; i>=2 ; i-- )
- posmacro[len-2+i] = posmacro[i];
- else if( len<2 )
- for( i=2 ; i<strlen(posmacro) ; i++ )
- posmacro[i-len] = posmacro[i];
- strncpy( posmacro, nc->nom, len );
- }
- while( (posmacro=strstr(s,"$*")) != NULL )
- {
- printf("trouvé $*: '%s'\n", s);
- char *nom = strdup( nc->nom );
- int i;
- for( i=0;i<strlen(nom);i++)
- if( nom[i]=='.' )
- nom[i]=0;
- int len=strlen(nom);
- // copie la fin au bon endroit
- if( len>2 )
- for( i=strlen(posmacro) ; i>=2 ; i-- )
- posmacro[len-2+i] = posmacro[i];
- else if( len<2 )
- for( i=2 ; i<strlen(posmacro) ; i++ )
- posmacro[i-len] = posmacro[i];
- strncpy( posmacro, nom, len );
- free(nom);
- }
- nc->commandes[pos] = malloc( sizeof(char)*strlen(s) );
- strcpy( nc->commandes[pos], &s[1] );
- if( (pos+1)%CMD_ALLOC_SIZE == 0 )
- // je suis arrivé presque au bout du tableau alloué
- // (ex. pos=9), j'ajoute 10 pointeurs (ex. realloc(20))
- nc->commandes = realloc( nc->commandes,
- sizeof(char *)*(pos+CMD_ALLOC_SIZE+1) );
- pos++;
- }
- nc->commandes[pos] = NULL;
- }
- fclose( f );
- return( g );
- }
- /**
- * affiche un graphe de dépendances : noeuds, dépendances, commandes.
- * \param [in] g (Graphe) à afficher
- */
- void AfficheGraphe( Graphe *g )
- {
- for( ; g ; g=g->suiv )
- {
- Noeud *n=g->n;
- Liste *d;
- char **com;
- printf( "cible: '%s'\n", n->nom );
- if( n->pred )
- {
- printf( "\tdépend de: " );
- for( d=n->pred; d->suiv; d=d->suiv )
- printf( "'%s', ", d->n->nom );
- printf( "'%s'\n", d->n->nom );
- }
- else
- printf( "\tne dépend de rien.\n" );
- if( n->succ )
- {
- printf( "\tnécessaire à: " );
- for( d=n->succ; d->suiv; d=d->suiv )
- printf( "'%s', ", d->n->nom );
- printf( "'%s'\n", d->n->nom );
- }
- else
- printf( "\tnécessaire à rien.\n" );
- if( n->commandes )
- {
- printf( "\tcommandes pour construire cette règle :\n" );
- for( com=n->commandes ; *com ; com++ )
- {
- printf( "\t\t'%s'\n", *com );
- }
- }
- else
- {
- printf( "\tFichier source.\n" );
- }
- }
- }
- /**
- * libère la mémoire allouée par une liste
- * \param [in] l pointeur sur une (Liste) à libérer
- */
- void FreeListe( Liste *l )
- {
- while( l )
- {
- Liste *suiv;
- suiv = l->suiv;
- free( l );
- l = suiv;
- }
- }
- /**
- * libère toute la mémoire allouée par un graphe de dépendances
- * \param [in] g (Graphe) à libérer
- */
- void FreeGraphe( Graphe *g )
- {
- while( g )
- {
- Graphe *s;
- s = g->suiv;
- Noeud *n = g->n;
- // libère la mémoire des commandes
- if( n->commandes )
- {
- char **com;
- for( com=n->commandes ; *com ; com++ )
- free( *com );
- free( n->commandes );
- }
- // libère les deux listes des dépendances (pred et succ)
- FreeListe( n->pred );
- FreeListe( n->succ );
- // libère le noeud
- free( n );
- // et l'élément du graphe
- free( g );
- g = s;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement