/*--------------------------------------------------------------------
 * FICHERO:    GeneMake.c
 * OBJETIVO:   Definir la funcin GeneraMakefile()
 * AUTOR:      Pedro Reina
 * FECHA:      L.17.7.1995
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * Ficheros de cabecera
 *------------------------------------------------------------------*/

#include "Zeus.h"

/*--------------------------------------------------------------------
 * Definicin de macros constantes
 *------------------------------------------------------------------*/

#define DISTANCIA 12
#define TOPE      65

/*--------------------------------------------------------------------
 * Variables globales
 *------------------------------------------------------------------*/

char NombreObjeto [LONG_NOMBRE];
char IdObjeto [LONG_FICH_CORTO];
char AbrevObjeto [LONG_FICH_CORTO];

/*--------------------------------------------------------------------
 * Declaracin de funciones
 *------------------------------------------------------------------*/

void LeeDescripcion();
void CambiaIdentificador();
void AlmacenaRequisito();
void AlmacenaFuente();
void AlmacenaObjeto();
void AlmacenaCabecera();
void EstudiaRequisito();
void EstudiaObjeto();
void EscribeMakefile();
void EscribeObjeto();
void EscribeFuente();
void EscribeCabecera();
void EscribeLista();
void EscribeListaObjeto();

/*--------------------------------------------------------------------
 * Definicin de funciones
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * FUNCION:  GeneraMakefile()
 * OBJETIVO: Generar el makefile de un objeto
 * ENTRADAS: La abreviatura del objeto
 * SALIDAS:  Ninguna. El programa puede abortar
 *------------------------------------------------------------------*/
void GeneraMakefile (Abreviatura)
char *Abreviatura;
  {
  PresentaOpcion ("Generacin de makefile");

  TotalRequisito = 0;
  TotalFuente = 0;
  TotalCabecera = 0;
  TotalObjeto = 0;

  LeeDescripcion (Abreviatura);
  printf ("\nEstudiando el objeto %s",NombreObjeto);

  EstudiaRequisito();
  EstudiaObjeto();
  EscribeMakefile();
  EscribeLista();
  }

/*--------------------------------------------------------------------
 * Definicin de funciones
 *------------------------------------------------------------------*/

/*--------------------------------------------------------------------
 * FUNCION:  LeeDescripcion()
 * OBJETIVO: Leer el fichero de descripcin de un objeto
 * ENTRADAS: La abreviatura del objeto
 * SALIDAS:  Ninguna. El programa aborta si no se puede leer
 *------------------------------------------------------------------*/
void LeeDescripcion (Abreviatura)
char *Abreviatura;
  {
  char Sigue;
  FILE *Entrada;
  char Nombre[LONG_FICH_LARGO], Aux[LONG_PALABRA];

  strcpy (Nombre,Abreviatura);
  strcat (Nombre,".des");
  ArreglaSeparador (Nombre);

  Entrada = AbreFicheroLeer (Nombre);
  printf ("\nLeyendo %s",Nombre);

  LeePalabra (Entrada,NombreObjeto);
  LeePalabra (Entrada,IdObjeto);
  LeePalabra (Entrada,AbrevObjeto);
  CambiaIdentificador();
  AlmacenaFuente (IdObjeto);

  LeePalabra (Entrada,Aux); /* Se lee la palabra "Requisitos" */

  Sigue = 1;
  while ( Sigue )
    {
    LeePalabra (Entrada,Aux);
    if ( !strcmp (Aux,"Fuente") )
      { Sigue = 0; }
    else
      { AlmacenaRequisito (Aux); }
    }

  Sigue = 1;
  while ( Sigue )
    {
    LeePalabra (Entrada,Aux);
    if ( !strcmp (Aux,"Cabecera") )
      { Sigue = 0; }
    else
      { AlmacenaFuente (Aux); }
    }

  Sigue = 1;
  while ( Sigue )
    {
    if ( !LeePalabra (Entrada,Aux) )
      { Sigue = 0; }
    else
      { AlmacenaCabecera (Aux); }
    }

  fclose (Entrada);
  }

/*--------------------------------------------------------------------
 * FUNCION:  CambiaIdentificador()
 * OBJETIVO: Reescribir el identificador del objeto
 * ENTRADAS: Se toma una variable global
 * SALIDAS:  Ninguna.
 *------------------------------------------------------------------*/
void CambiaIdentificador()
  {
  short i;

  for ( i=4 ; i ; i-- )
    { IdObjeto[i] = IdObjeto[i-1]; }
  IdObjeto[0] = 'V';
  IdObjeto[1] = tolower(IdObjeto[1]);
  }

/*--------------------------------------------------------------------
 * FUNCION:  AlmacenaRequisito()
 * OBJETIVO: Almacenar un requisito
 * ENTRADAS: El nombre del requisito
 * SALIDAS:  Ninguna. El programa puede abortar si no hay espacio.
 *           La variable TotalRequisito queda modificada
 *------------------------------------------------------------------*/
void AlmacenaRequisito (Nombre)
char *Nombre;
  {
  char  Visto=0;
  short i;

  if ( TotalRequisito == MAX_REQUISITO )
    { ErrorFatal ("Demasiados requisitos"); }
  else
    {
    for ( i=0 ; i<TotalRequisito && !Visto ; i++ )
      { Visto = !strcmp (Requisito[i],Nombre); }
    if ( !Visto )  { strcpy (Requisito[TotalRequisito++],Nombre); }
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  AlmacenaFuente()
 * OBJETIVO: Almacenar un fuente
 * ENTRADAS: El nombre del fuente
 * SALIDAS:  Ninguna. El programa puede abortar si no hay espacio.
 *           La variable TotalFuente queda modificada
 *------------------------------------------------------------------*/
void AlmacenaFuente (Nombre)
char *Nombre;
  {
  if ( TotalFuente == MAX_FUENTE )
    { ErrorFatal ("Demasiados fuentes"); }
  else
    { strcpy (Fuente[TotalFuente++],Nombre); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  AlmacenaObjeto()
 * OBJETIVO: Almacenar un fichero objeto
 * ENTRADAS: El nombre del fichero objeto
 * SALIDAS:  Ninguna. El programa puede abortar si no hay espacio.
 *           La variable TotalObjeto queda modificada
 *------------------------------------------------------------------*/
void AlmacenaObjeto (Nombre)
char *Nombre;
  {
  if ( TotalObjeto == MAX_OBJETO )
    { ErrorFatal ("Demasiados ficheros objeto"); }
  else
    { strcpy (Objeto[TotalObjeto++],Nombre); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  AlmacenaCabecera()
 * OBJETIVO: Almacenar una cabecera
 * ENTRADAS: El nombre de la cabecera
 * SALIDAS:  Ninguna. El programa puede abortar si no hay espacio.
 *           La variable TotalCabecera queda modificada
 *------------------------------------------------------------------*/
void AlmacenaCabecera (Nombre)
char *Nombre;
  {
  if ( TotalCabecera == MAX_CABECERA )
    { ErrorFatal ("Demasiadas cabeceras"); }
  else
    { strcpy (Cabecera[TotalCabecera++],Nombre); }
  }

/*--------------------------------------------------------------------
 * FUNCION:  EstudiaRequisito()
 * OBJETIVO: Recoger todos los requisitos necesarios para este objeto
 * ENTRADAS: Ninguna
 * SALIDAS:  Ninguna
 *------------------------------------------------------------------*/
void EstudiaRequisito()
  {
  char  Sigue;
  char  Aux[LONG_PALABRA], NombreFichero[LONG_FICH_LARGO];
  short i;
  FILE *Fichero;

  for ( i=0 ; i<TotalRequisito ; i++ )
    {
    strcpy (NombreFichero,Requisito[i]);
    strcat (NombreFichero,".des");
    ArreglaSeparador (NombreFichero);
    Fichero = AbreFicheroLeer (NombreFichero);
    Sigue = 1;
    while ( Sigue )
      {
      LeePalabra (Fichero,Aux);
      Sigue = strcmp (Aux,"Requisito");
      }

    Sigue = 1;
    while ( Sigue )
      {
      LeePalabra (Fichero,Aux);
      if ( !strcmp (Aux,"Fuente") )
        { Sigue = 0; }
      else
        { AlmacenaRequisito (Aux); }
      }
    fclose (Fichero);
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  EstudiaObjeto()
 * OBJETIVO: Recoger todos los ficheros objeto necesarios para este objeto
 * ENTRADAS: Ninguna
 * SALIDAS:  Ninguna
 *------------------------------------------------------------------*/
void EstudiaObjeto()
  {
  char  Sigue;
  char  Aux[LONG_PALABRA], NombreFichero[LONG_FICH_LARGO];
  short i;
  FILE *Fichero;

  for ( i=0 ; i<TotalFuente ; i++ )
    { AlmacenaObjeto (Fuente[i]); }

  for ( i=0 ; i<TotalRequisito ; i++ )
    {
    strcpy (NombreFichero,Requisito[i]);
    strcat (NombreFichero,".des");
    ArreglaSeparador (NombreFichero);
    Fichero = AbreFicheroLeer (NombreFichero);
    Sigue = 1;
    while ( Sigue )
      {
      LeePalabra (Fichero,Aux);
      Sigue = strcmp (Aux,"Fuente");
      }

    Sigue = 1;
    while ( Sigue )
      {
      LeePalabra (Fichero,Aux);
      if ( !strcmp (Aux,"Cabecera") )
        { Sigue = 0; }
      else
        { AlmacenaObjeto (Aux); }
      }
    fclose (Fichero);
    }
  }

/*--------------------------------------------------------------------
 * FUNCION:  EscribeMakefile()
 * OBJETIVO: Escribir el makefile final
 * ENTRADAS: Ninguna
 * SALIDAS:  El programa puede abortar si no se puede escribir
 *------------------------------------------------------------------*/
void EscribeMakefile()
  {
  FILE *Salida;
  char NombreFichero[LONG_FICH_LARGO];

  strcpy (NombreFichero, AbrevObjeto);
  strcat (NombreFichero,".mak");
  ArreglaSeparador (NombreFichero);
  printf ("\nEscribiendo %s",NombreFichero);

  Salida = AbreFicheroGrabar (NombreFichero);
  fprintf (Salida,"# Makefile para el objeto %s\n\n",NombreObjeto);

#ifdef PC
  fprintf (Salida,"Compilador = TCC\n");
#endif
#ifdef QL
  fprintf (Salida,"Compilador = CC\n");
#endif

  fprintf (Salida,"Opciones   = -c\n");
  strcpy (NombreFichero,IdObjeto);
  strcat (NombreFichero,".exe");
  ArreglaSeparador (NombreFichero);
  fprintf (Salida,"Objetivo   = %s\n",NombreFichero);

  fprintf (Salida,"Objeto     =");
  EscribeObjeto (Salida);

  fprintf (Salida,"Fuente     =");
  EscribeFuente (Salida);

  fprintf (Salida,"Cabecera   =");
  EscribeCabecera (Salida);

#ifdef PC
  fprintf (Salida,"\n.c.obj:\n");
  fprintf (Salida,"  $(Compilador) $(Opciones) {$< }\n");
#endif

  fprintf (Salida,"\n$(Objetivo) : $(Objeto)\n");
#ifdef PC
  fprintf (Salida,"  $(Compilador) @%s.lst\n",AbrevObjeto);
#endif
#ifdef QL
  fprintf (Salida,"  $(Compilador) -bufp200 -o%s_exe -lm \\\n",IdObjeto);
  EscribeListaObjeto (Salida);
#endif

  fprintf (Salida,"\n$(Objeto) : $(Cabecera)\n");

  fclose (Salida);
  }

/*--------------------------------------------------------------------
 * FUNCION:  EscribeObjeto()
 * OBJETIVO: Escribir los ficheros objeto
 * ENTRADAS: El fichero donde escribirlos
 * SALIDAS:  Ninguna
 *------------------------------------------------------------------*/
void EscribeObjeto (Fichero)
FILE *Fichero;
  {
  short i, Acumulado;
  char NombreFichero[LONG_FICH_LARGO];

  Acumulado = DISTANCIA;
  for ( i=0 ; i<TotalFuente ; i++ )
    {
    strcpy (NombreFichero,Fuente[i]);
#ifdef PC
    strcat (NombreFichero,".obj");
#endif
#ifdef QL
    strcat (NombreFichero,"_o");
#endif
    fprintf (Fichero, " %s", NombreFichero);
    Acumulado += strlen(NombreFichero)+1;
    if ( Acumulado>TOPE && i<TotalFuente-1 )
      {
      fprintf (Fichero," \\\n");
      fprintf (Fichero,"            ");
      Acumulado = DISTANCIA;
      }
    }
  fprintf (Fichero,"\n");
  }

/*--------------------------------------------------------------------
 * FUNCION:  EscribeFuente()
 * OBJETIVO: Escribir los fuentes
 * ENTRADAS: El fichero donde escribirlos
 * SALIDAS:  Ninguna
 *------------------------------------------------------------------*/
void EscribeFuente (Fichero)
FILE *Fichero;
  {
  short i, Acumulado;
  char NombreFichero[LONG_FICH_LARGO];

  Acumulado = DISTANCIA;
  for ( i=0 ; i<TotalFuente ; i++ )
    {
    strcpy (NombreFichero,Fuente[i]);
    strcat (NombreFichero,".c");
    ArreglaSeparador (NombreFichero);
    fprintf (Fichero, " %s", NombreFichero);
    Acumulado += strlen(NombreFichero)+1;
    if ( Acumulado>TOPE && i<TotalFuente-1 )
      {
      fprintf (Fichero," \\\n");
      fprintf (Fichero,"            ");
      Acumulado = DISTANCIA;
      }
    }
  fprintf (Fichero,"\n");
  }

/*--------------------------------------------------------------------
 * FUNCION:  EscribeCabecera()
 * OBJETIVO: Escribir las cabeceras
 * ENTRADAS: El fichero donde escribirlas
 * SALIDAS:  Ninguna
 *------------------------------------------------------------------*/
void EscribeCabecera (Fichero)
FILE *Fichero;
  {
  short i;
  char NombreFichero[LONG_FICH_LARGO];

  for ( i=0 ; i<TotalCabecera ; i++ )
    {
    strcpy (NombreFichero,AbrevObjeto);
    strcat (NombreFichero,".");
    strcat (NombreFichero,Cabecera[i]);
    ArreglaSeparador (NombreFichero);
    fprintf (Fichero, " %s", NombreFichero);
    }
  fprintf (Fichero,"\n");
  }

/*--------------------------------------------------------------------
 * FUNCION:  EscribeLista()
 * OBJETIVO: Escribir en el PC una lista con los todos los ficheros
 *           objeto, incluidos los de los requisitos
 * ENTRADAS: Ninguna
 * SALIDAS:  El programa puede abortar si no se puede escribir
 *------------------------------------------------------------------*/
void EscribeLista()
  {
#ifdef PC
  FILE *Salida;
  short i;
  char  NombreFichero[LONG_FICH_LARGO];

  strcpy (NombreFichero, AbrevObjeto);
  strcat (NombreFichero,".lst");
  printf ("\nEscribiendo %s",NombreFichero);

  Salida = AbreFicheroGrabar (NombreFichero);
  for ( i=0 ; i<TotalObjeto ; i++ )
    {
    strcpy (NombreFichero,Objeto[i]);
    strcat (NombreFichero,".obj");
    fprintf (Salida, "%s\n", NombreFichero);
    }
  fclose (Salida);
#endif
  }

/*--------------------------------------------------------------------
 * FUNCION:  EscribeListaObjeto()
 * OBJETIVO: Escribir todos los ficheros objeto necesarios para compilar
 * ENTRADAS: El fichero donde escribirlos
 * SALIDAS:  Ninguna
 *------------------------------------------------------------------*/
void EscribeListaObjeto (Fichero)
FILE *Fichero;
  {
  short i, Acumulado;
  char  NombreFichero[LONG_FICH_LARGO];

  fprintf (Fichero,"     ");
  Acumulado = 5;
  for ( i=0 ; i<TotalObjeto ; i++ )
    {
    strcpy (NombreFichero,Objeto[i]);
    strcat (NombreFichero,"_o");
    fprintf (Fichero, " %s", NombreFichero);
    Acumulado += strlen(NombreFichero)+1;
    if ( Acumulado>TOPE && i<TotalObjeto-1 )
      {
      fprintf (Fichero," \\\n");
      fprintf (Fichero,"     ");
      Acumulado = 5;
      }
    }
  fprintf (Fichero,"\n");
  }
