2007-12-18 15:06:42 +11:00
/*
* Copyright 2007 Jon Loeliger , Freescale Semiconductor , Inc .
*
* 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 2 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 , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA
*/
2010-11-17 15:28:20 -08:00
# define _GNU_SOURCE
# include <stdio.h>
2007-12-18 15:06:42 +11:00
# include "dtc.h"
# include "srcpos.h"
2010-11-17 15:28:20 -08:00
static char * dirname ( const char * path )
{
const char * slash = strrchr ( path , ' / ' ) ;
if ( slash ) {
int len = slash - path ;
char * dir = xmalloc ( len + 1 ) ;
memcpy ( dir , path , len ) ;
dir [ len ] = ' \0 ' ;
return dir ;
}
return NULL ;
}
struct srcfile_state * current_srcfile ; /* = NULL */
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
/* Detect infinite include recursion. */
# define MAX_SRCFILE_DEPTH (100)
static int srcfile_depth ; /* = 0 */
FILE * srcfile_relative_open ( const char * fname , char * * fullnamep )
2007-12-18 15:06:42 +11:00
{
2010-11-17 15:28:20 -08:00
FILE * f ;
2008-08-07 12:24:17 +10:00
char * fullname ;
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
if ( streq ( fname , " - " ) ) {
f = stdin ;
fullname = xstrdup ( " <stdin> " ) ;
2008-08-07 12:24:17 +10:00
} else {
2010-11-17 15:28:20 -08:00
if ( ! current_srcfile | | ! current_srcfile - > dir
| | ( fname [ 0 ] = = ' / ' ) )
fullname = xstrdup ( fname ) ;
else
fullname = join_path ( current_srcfile - > dir , fname ) ;
f = fopen ( fullname , " r " ) ;
if ( ! f )
die ( " Couldn't open \" %s \" : %s \n " , fname ,
strerror ( errno ) ) ;
2008-08-07 12:24:17 +10:00
}
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
if ( fullnamep )
* fullnamep = fullname ;
else
2008-08-07 12:24:17 +10:00
free ( fullname ) ;
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
return f ;
2007-12-18 15:06:42 +11:00
}
2010-11-17 15:28:20 -08:00
void srcfile_push ( const char * fname )
{
struct srcfile_state * srcfile ;
if ( srcfile_depth + + > = MAX_SRCFILE_DEPTH )
die ( " Includes nested too deeply " ) ;
srcfile = xmalloc ( sizeof ( * srcfile ) ) ;
srcfile - > f = srcfile_relative_open ( fname , & srcfile - > name ) ;
srcfile - > dir = dirname ( srcfile - > name ) ;
srcfile - > prev = current_srcfile ;
srcfile - > lineno = 1 ;
srcfile - > colno = 1 ;
current_srcfile = srcfile ;
}
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
int srcfile_pop ( void )
2008-08-07 12:24:17 +10:00
{
2010-11-17 15:28:20 -08:00
struct srcfile_state * srcfile = current_srcfile ;
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
assert ( srcfile ) ;
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
current_srcfile = srcfile - > prev ;
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
if ( fclose ( srcfile - > f ) )
die ( " Error closing \" %s \" : %s \n " , srcfile - > name ,
strerror ( errno ) ) ;
2008-08-07 12:24:17 +10:00
2010-11-17 15:28:20 -08:00
/* FIXME: We allow the srcfile_state structure to leak,
* because it could still be referenced from a location
* variable being carried through the parser somewhere . To
* fix this we could either allocate all the files from a
* table , or use a pool allocator . */
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
return current_srcfile ? 1 : 0 ;
}
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
/*
* The empty source position .
*/
2008-08-07 12:24:17 +10:00
2010-11-17 15:28:20 -08:00
struct srcpos srcpos_empty = {
. first_line = 0 ,
. first_column = 0 ,
. last_line = 0 ,
. last_column = 0 ,
. file = NULL ,
} ;
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
# define TAB_SIZE 8
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
void srcpos_update ( struct srcpos * pos , const char * text , int len )
{
int i ;
pos - > file = current_srcfile ;
pos - > first_line = current_srcfile - > lineno ;
pos - > first_column = current_srcfile - > colno ;
for ( i = 0 ; i < len ; i + + )
if ( text [ i ] = = ' \n ' ) {
current_srcfile - > lineno + + ;
current_srcfile - > colno = 1 ;
} else if ( text [ i ] = = ' \t ' ) {
current_srcfile - > colno =
ALIGN ( current_srcfile - > colno , TAB_SIZE ) ;
} else {
current_srcfile - > colno + + ;
}
pos - > last_line = current_srcfile - > lineno ;
pos - > last_column = current_srcfile - > colno ;
}
2008-08-07 12:24:17 +10:00
2010-11-17 15:28:20 -08:00
struct srcpos *
srcpos_copy ( struct srcpos * pos )
{
struct srcpos * pos_new ;
2008-08-07 12:24:17 +10:00
2010-11-17 15:28:20 -08:00
pos_new = xmalloc ( sizeof ( struct srcpos ) ) ;
memcpy ( pos_new , pos , sizeof ( struct srcpos ) ) ;
return pos_new ;
}
void
srcpos_dump ( struct srcpos * pos )
{
printf ( " file : \" %s \" \n " ,
pos - > file ? ( char * ) pos - > file : " <no file> " ) ;
printf ( " first_line : %d \n " , pos - > first_line ) ;
printf ( " first_column: %d \n " , pos - > first_column ) ;
printf ( " last_line : %d \n " , pos - > last_line ) ;
printf ( " last_column : %d \n " , pos - > last_column ) ;
printf ( " file : %s \n " , pos - > file - > name ) ;
}
2007-12-18 15:06:42 +11:00
2010-11-17 15:28:20 -08:00
char *
srcpos_string ( struct srcpos * pos )
{
const char * fname = " <no-file> " ;
char * pos_str ;
int rc ;
if ( pos )
fname = pos - > file - > name ;
if ( pos - > first_line ! = pos - > last_line )
rc = asprintf ( & pos_str , " %s:%d.%d-%d.%d " , fname ,
pos - > first_line , pos - > first_column ,
pos - > last_line , pos - > last_column ) ;
else if ( pos - > first_column ! = pos - > last_column )
rc = asprintf ( & pos_str , " %s:%d.%d-%d " , fname ,
pos - > first_line , pos - > first_column ,
pos - > last_column ) ;
else
rc = asprintf ( & pos_str , " %s:%d.%d " , fname ,
pos - > first_line , pos - > first_column ) ;
if ( rc = = - 1 )
die ( " Couldn't allocate in srcpos string " ) ;
return pos_str ;
}
void
srcpos_verror ( struct srcpos * pos , char const * fmt , va_list va )
{
const char * srcstr ;
srcstr = srcpos_string ( pos ) ;
fprintf ( stdout , " Error: %s " , srcstr ) ;
vfprintf ( stdout , fmt , va ) ;
fprintf ( stdout , " \n " ) ;
2007-12-18 15:06:42 +11:00
}
2010-11-17 15:28:20 -08:00
void
srcpos_error ( struct srcpos * pos , char const * fmt , . . . )
2007-12-18 15:06:42 +11:00
{
2010-11-17 15:28:20 -08:00
va_list va ;
va_start ( va , fmt ) ;
srcpos_verror ( pos , fmt , va ) ;
va_end ( va ) ;
}
void
srcpos_warn ( struct srcpos * pos , char const * fmt , . . . )
{
const char * srcstr ;
va_list va ;
va_start ( va , fmt ) ;
srcstr = srcpos_string ( pos ) ;
fprintf ( stderr , " Warning: %s " , srcstr ) ;
vfprintf ( stderr , fmt , va ) ;
fprintf ( stderr , " \n " ) ;
2008-08-07 12:24:17 +10:00
2010-11-17 15:28:20 -08:00
va_end ( va ) ;
2007-12-18 15:06:42 +11:00
}