Advertisement
Guest User

Untitled

a guest
Oct 31st, 2014
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.20 KB | None | 0 0
  1. /** \file
  2.  * maquefilereader.c : source pour la lecture des maquefiles
  3.  * \copyright Vincent Loechner, 2014.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #include "maquefilereader.h"
  11.  
  12. /* longueur max d'une ligne du fichier d'entrée */
  13. #define MAXLINESIZE 4000
  14. /* bloc d'allocation de base des commandes (realloc tous les ...) */
  15. #define CMD_ALLOC_SIZE 10
  16.  
  17. /**
  18.  * trouve un noeud dans un graphe d'après le nom de la cible
  19.  * \param [in] g pointeur sur le (Graphe)
  20.  * \param [in] cible nom de la cible cherchée (chaine de caractères)
  21.  * \return pointeur sur le (Noeud) recherché, ou NULL si non trouvé.
  22.  */
  23. Noeud *TrouveNoeud( Graphe *g, char *cible )
  24. {
  25.     for( ; g ; g=g->suiv )
  26.     {
  27.         if( strcmp(g->n->nom, cible) == 0 ) // trouvé !
  28.             return( g->n );
  29.     }
  30.     return( NULL );
  31. }
  32.  
  33. /**
  34.  * ajoute un nouveau noeud dans un graphe
  35.  * \param [inout] g pointeur sur le (Graphe)
  36.  * \param [in] cible nom de la cible à ajouter (chaine de caractères)
  37.  * \return pointeur sur le nouveau (Graphe)
  38.  */
  39. Graphe *AjouteNoeud( Graphe *g, char *cible )
  40. {
  41.     Graphe *nouv;
  42.     // liste de noeuds du graphe +1
  43.     nouv = malloc( sizeof(Graphe) );
  44.     nouv->suiv = g;
  45.     nouv->n = malloc( sizeof( Noeud ) );
  46.  
  47.     nouv->n->commandes = NULL;
  48.     nouv->n->flag = 0;
  49.     strcpy( nouv->n->nom, cible );
  50.     nouv->n->pred = NULL;
  51.     nouv->n->succ = NULL;
  52.  
  53.     return( nouv );
  54. }
  55.  
  56. /**
  57.  * lit un fichier maquefile
  58.  * \param [in] fname nom du fichier (chaine de caractères)
  59.  * \return pointeur sur le nouveau (Graphe)
  60.  */
  61. Graphe *LireMaquefile( char *fname )
  62. {
  63.     FILE *f;
  64.     Graphe *g;
  65.     char *con;
  66.     char s[MAXLINESIZE];
  67.     int lineno = 0;
  68.  
  69.     if( !(f=fopen( fname, "r" )) )
  70.     {
  71.         perror(fname);
  72.         return( NULL );
  73.     }
  74.  
  75.     g = NULL;
  76.  
  77.     con = fgets( s, MAXLINESIZE, f);
  78.     lineno++;
  79.     // lire des règles
  80.     while( con != NULL )
  81.     {
  82.         char *cible, *dep;
  83.         Noeud *nc;
  84.         char *token;
  85.  
  86.         // fgets lit le \n final, je le supprime :
  87.         if( s[strlen(s)-1] == '\n' )
  88.             s[strlen(s)-1] = '\0';
  89.  
  90.         if( strstr( s, ":" ) == NULL )
  91.         // pas une règle, ignore et continue
  92.         {
  93.             cible = strtok_r( s, " \t:", &token );
  94.             if( cible && cible[0]!='#' )
  95.                 fprintf( stderr,
  96.                     "WARNING: not a rule, ignoring line %d\n", lineno );
  97.             if( fgets( s, MAXLINESIZE, f) == NULL )
  98.                 con = 0;
  99.             lineno++;
  100.             continue;
  101.         }
  102.  
  103.         // ignore les espaces et les tabulations :
  104.         cible = strtok_r( s, " \t:", &token );
  105.         if( cible==NULL || cible[0]=='#' )
  106.         // ligne vide ou commentaire, ignore et passe à la suite
  107.         {
  108.             if( fgets( s, MAXLINESIZE, f) == NULL )
  109.                 con = 0;
  110.             continue;
  111.         }
  112.  
  113.         // si ce noeud n'existe pas encore on le crée
  114.         if( (nc = TrouveNoeud( g, cible )) == NULL )
  115.         {
  116.             g = AjouteNoeud( g, cible );
  117.             nc = g->n;
  118.         }
  119.         // n est le noeud cible (nouveau ou existant).
  120.  
  121.         // lit les dépendances
  122.         // séparées par espaces ou tabs
  123.         while( (dep=strtok_r( NULL, " \t", &token )) != NULL )
  124.         {
  125.             Noeud *nd;
  126.             // n'existe pas encore, on le crée
  127.             if( (nd = TrouveNoeud( g, dep )) == NULL )
  128.             {
  129.                 g = AjouteNoeud( g, dep );
  130.                 nd = g->n;
  131.             }
  132.             // ajoute les dépendances :
  133.             // cible dépend de dep
  134.             // et dep succède à cible
  135.             Liste *d;
  136.             // ajoute cible aux successeurs dep
  137.             d = malloc( sizeof(Liste) );
  138.             d->suiv = nd->succ;
  139.             d->n = nc;
  140.             nd->succ = d;
  141.             // ajoute dep aux prédécesseurs de cible
  142.             d = malloc( sizeof(Liste) );
  143.             d->suiv = nc->pred;
  144.             d->n = nd;
  145.             nc->pred = d;
  146.         }
  147.  
  148.         // lit les commandes et les place dans nc->commandes
  149.         int pos = 0;
  150.         if( nc->commandes == NULL )
  151.             nc->commandes = malloc( sizeof(char *)*CMD_ALLOC_SIZE );
  152.         else
  153.         {
  154.             fprintf( stderr,
  155.                 "Warning: duplicate target '%s'. Merging.\n",
  156.                 nc->nom );
  157.             while( nc->commandes[pos] != NULL )
  158.                 pos++;
  159.         }
  160.         while( (con=fgets( s, MAXLINESIZE, f )) != NULL )
  161.         {
  162.             char *posmacro;
  163.             lineno++;
  164.             // les commandes commencent obligatoirement par un <tab>
  165.             if( s[0]!='\t' )
  166.                 break;
  167.                 // s va être lu comme une règle à l'itération suivante.
  168.  
  169.             // fgets lit le '\n' final, je le supprime :
  170.             if( s[strlen(s)-1] == '\n' )
  171.                 s[strlen(s)-1] = '\0';
  172.  
  173.             // remplace $@ et $*
  174.             while( (posmacro=strstr(s,"$@")) != NULL )
  175.             {
  176.                 int i,len=strlen(nc->nom);
  177.                 // copie la fin au bon endroit
  178.                 if( len>2 )
  179.                     for( i=strlen(posmacro) ; i>=2 ; i-- )
  180.                         posmacro[len-2+i] = posmacro[i];
  181.                 else if( len<2 )
  182.                     for( i=2 ; i<strlen(posmacro) ; i++ )
  183.                         posmacro[i-len] = posmacro[i];
  184.                 strncpy( posmacro, nc->nom, len );
  185.             }
  186.             while( (posmacro=strstr(s,"$*")) != NULL )
  187.             {
  188. printf("trouvé $*: '%s'\n", s);
  189.                 char *nom = strdup( nc->nom );
  190.                 int i;
  191.                 for( i=0;i<strlen(nom);i++)
  192.                     if( nom[i]=='.' )
  193.                         nom[i]=0;
  194.                 int len=strlen(nom);
  195.                 // copie la fin au bon endroit
  196.                 if( len>2 )
  197.                     for( i=strlen(posmacro) ; i>=2 ; i-- )
  198.                         posmacro[len-2+i] = posmacro[i];
  199.                 else if( len<2 )
  200.                     for( i=2 ; i<strlen(posmacro) ; i++ )
  201.                         posmacro[i-len] = posmacro[i];
  202.                 strncpy( posmacro, nom, len );
  203.                 free(nom);
  204.             }
  205.  
  206.             nc->commandes[pos] = malloc( sizeof(char)*strlen(s) );
  207.             strcpy( nc->commandes[pos], &s[1] );
  208.             if( (pos+1)%CMD_ALLOC_SIZE == 0 )
  209.                 // je suis arrivé presque au bout du tableau alloué
  210.                 // (ex. pos=9), j'ajoute 10 pointeurs (ex. realloc(20))
  211.                 nc->commandes = realloc( nc->commandes,
  212.                     sizeof(char *)*(pos+CMD_ALLOC_SIZE+1) );
  213.             pos++;
  214.         }
  215.         nc->commandes[pos] = NULL;
  216.     }
  217.  
  218.     fclose( f );
  219.     return( g );
  220. }
  221.  
  222. /**
  223.  * affiche un graphe de dépendances : noeuds, dépendances, commandes.
  224.  * \param [in] g (Graphe) à afficher
  225.  */
  226. void AfficheGraphe( Graphe *g )
  227. {
  228.     for( ; g ; g=g->suiv )
  229.     {
  230.         Noeud *n=g->n;
  231.         Liste *d;
  232.         char **com;
  233.         printf( "cible: '%s'\n", n->nom );
  234.  
  235.         if( n->pred )
  236.         {
  237.             printf( "\tdépend de: " );
  238.             for( d=n->pred; d->suiv; d=d->suiv )
  239.                 printf( "'%s', ", d->n->nom );
  240.             printf( "'%s'\n", d->n->nom );
  241.         }
  242.         else
  243.             printf( "\tne dépend de rien.\n" );
  244.  
  245.         if( n->succ )
  246.         {
  247.             printf( "\tnécessaire à: " );
  248.             for( d=n->succ; d->suiv; d=d->suiv )
  249.                 printf( "'%s', ", d->n->nom );
  250.             printf( "'%s'\n", d->n->nom );
  251.         }
  252.         else
  253.             printf( "\tnécessaire à rien.\n" );
  254.  
  255.         if( n->commandes )
  256.         {
  257.             printf( "\tcommandes pour construire cette règle :\n" );
  258.             for( com=n->commandes ; *com ; com++ )
  259.             {
  260.                 printf( "\t\t'%s'\n", *com );
  261.             }
  262.         }
  263.         else
  264.         {
  265.             printf( "\tFichier source.\n" );
  266.         }
  267.     }
  268. }
  269.  
  270. /**
  271.  * libère la mémoire allouée par une liste
  272.  * \param [in] l pointeur sur une (Liste) à libérer
  273.  */
  274. void FreeListe( Liste *l )
  275. {
  276.     while( l )
  277.     {
  278.         Liste *suiv;
  279.         suiv = l->suiv;
  280.         free( l );
  281.         l = suiv;
  282.     }
  283. }
  284.  
  285. /**
  286.  * libère toute la mémoire allouée par un graphe de dépendances
  287.  * \param [in] g (Graphe) à libérer
  288.  */
  289. void FreeGraphe( Graphe *g )
  290. {
  291.     while( g )
  292.     {
  293.         Graphe *s;
  294.         s = g->suiv;
  295.  
  296.         Noeud *n = g->n;
  297.  
  298.         // libère la mémoire des commandes
  299.         if( n->commandes )
  300.         {
  301.             char **com;
  302.             for( com=n->commandes ; *com ; com++ )
  303.                 free( *com );
  304.             free( n->commandes );
  305.         }
  306.  
  307.         // libère les deux listes des dépendances (pred et succ)
  308.         FreeListe( n->pred );
  309.         FreeListe( n->succ );
  310.  
  311.         // libère le noeud
  312.         free( n );
  313.  
  314.         // et l'élément du graphe
  315.         free( g );
  316.         g = s;
  317.     }
  318. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement