//*******************************************************************************
//error.c
//*******************************************************************************
//This file is part of the Orb compiler,
//Copyright (C) 2007 Adrian Fraga Fernandez
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//*******************************************************************************

/***********************************************************************/
/* Manejo de errores                                                   */
/***********************************************************************/

#include <stdio.h>
#include <stdarg.h>
#include "error.h"

/***********************************************************************/
/* Seguimiento de posiciones dentro del fichero fuente                 */
/***********************************************************************/
	
void e_copiaPosicion(E_POSICION *destino,E_POSICION *origen){
	destino->lineaInicio=origen->lineaInicio;
	destino->lineaFin=origen->lineaFin;
	destino->fichero=origen->fichero;
}

void e_unionPosiciones(E_POSICION *destino,E_POSICION *inicio,E_POSICION *fin){
	destino->lineaInicio=inicio->lineaInicio;
	destino->lineaFin=fin->lineaFin;
	destino->fichero=inicio->fichero;
}

/***********************************************************************/
/* Conteo de errores                                                   */
/***********************************************************************/

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

static int errores,warnings;

	/*************/
	/* Interfaz  */
	/*************/

int e_errores(void){return errores;}
int e_warnings(void){return warnings;}

/***********************************************************************/
/* Salida por pantalla                                                 */
/***********************************************************************/

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

static FILE *errorStream;	/* buffer de salida de mensajes de error */


static char e_temp[2048+4];	/* buffer temporal de salida */
				
	/************************/
	/* Funciones auxiliares */
	/************************/

		/* salida de mensajes (generico) */
		
static void e_generico(E_POSICION *p,FILE *stream,char *cabecera,...){	
int i,j,margen;
va_list ap;
	
	va_start(ap,cabecera);
	margen=0;
	if (p!=NULL){
		if (p->fichero!=NULL) margen+=fprintf(stream,"%s:",p->fichero);
		if (p->lineaInicio>=0){
			margen+=fprintf(stream,"%d",p->lineaInicio);
			if (p->lineaInicio==p->lineaFin || p->lineaFin<0) margen+=fprintf(stream,": ");
			else margen+=fprintf(stream,"-%d: ",p->lineaFin);
		}
	}
	margen+=vfprintf(stream,cabecera,ap);
	va_end(ap);
	
	for(i=0;i<2048 && e_temp[i]!=0;i++){
		if (e_temp[i]!='\n') fprintf(stream,"%c",e_temp[i]);
		else{
			fprintf(stream,"\n");
			for(j=0;j<margen;j++) fprintf(stream," ");
		}
	}
	fprintf(stream,"\n");
}
		
	/************************/
	/* Warnings (avisos)    */
	/************************/
		
void e_warning(E_POSICION *p,char *msg,...){
va_list ap;
	va_start(ap,msg);
	vsnprintf(e_temp,2048,msg,ap);
	va_end(ap);
	warnings++;
	e_generico(p,errorStream,"(aviso) ");
	if (warnings>MAX_WARNINGS)
		e_fatal(p,"Demasiados avisos (>%d)",MAX_WARNINGS);
}

	/************************/
	/* Errores              */
	/************************/

void e_error(E_POSICION *p,char *msg,...){	
va_list ap;
	va_start(ap,msg);
	vsnprintf(e_temp,2048,msg,ap);
	va_end(ap);
	errores++;
	e_generico(p,errorStream,"");
	if (errores>MAX_ERRORES)
		e_fatal(p,"Demasiados errores (>%d)",MAX_ERRORES);
}

	/************************/
	/* Errores fatales      */
	/************************/

void e_fatal(E_POSICION *p,char *msg,...){	
va_list ap;
	va_start(ap,msg);
	vsnprintf(e_temp,2048,msg,ap);
	va_end(ap);
	e_generico(p,errorStream,"(fatal) ");
	exit(1);
}

/***********************************************************************/
/* Inicializacion                                                      */
/***********************************************************************/

void e_init(FILE *errorstream){			
	errores=warnings=0;
	errorStream=errorstream;
	e_temp[2048]  ='.';
	e_temp[2048+1]='.';
	e_temp[2048+2]='.';
	e_temp[2048+3]=0;
}

void e_close(void){
}



