2007-04-22 20:03:12 +10:00
/*
Copyright ( C ) 2005 - 2006 Axel Liljencrantz
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation .
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 .
*/
/** \file main.c
The main loop of < tt > fish < / tt > .
*/
# include "config.h"
# include <stdlib.h>
# include <stdio.h>
# include <wchar.h>
# include <string.h>
# include <unistd.h>
# include <errno.h>
# include <unistd.h>
# include <termios.h>
# include <fcntl.h>
# ifdef HAVE_GETOPT_H
# include <getopt.h>
# endif
# include <locale.h>
# include <signal.h>
# include "fallback.h"
# include "util.h"
# include "common.h"
# include "wutil.h"
# include "halloc.h"
# include "halloc_util.h"
# include "tokenizer.h"
# include "print_help.h"
# include "parser_keywords.h"
/**
The string describing the single - character options accepted by the main fish binary
*/
# define GETOPT_STRING "hvi"
void read_file ( FILE * f , string_buffer_t * b )
{
while ( 1 )
{
wint_t c = fgetwc ( f ) ;
if ( c = = WEOF )
{
break ;
}
sb_append_char ( b , c ) ;
}
}
static void insert_tabs ( string_buffer_t * out , int indent )
{
int i ;
for ( i = 0 ; i < indent ; i + + )
{
sb_append ( out , L " \t " ) ;
}
}
static int indent ( string_buffer_t * out , wchar_t * in , int flags )
{
tokenizer tok ;
int res = 0 ;
int is_command = 1 ;
int indent = 0 ;
int do_indent = 1 ;
2007-04-23 04:54:29 +10:00
int prev_type = 0 ;
int prev_prev_type = 0 ;
2007-04-22 20:03:12 +10:00
tok_init ( & tok , in , TOK_SHOW_COMMENTS ) ;
for ( ; tok_has_next ( & tok ) ; tok_next ( & tok ) )
{
int type = tok_last_type ( & tok ) ;
wchar_t * last = tok_last ( & tok ) ;
switch ( type )
{
case TOK_STRING :
{
if ( is_command )
{
int next_indent = indent ;
is_command = 0 ;
wchar_t * unesc = unescape ( last , UNESCAPE_SPECIAL ) ;
if ( parser_keywords_is_block ( unesc ) )
{
next_indent + + ;
}
else if ( wcscmp ( unesc , L " else " ) = = 0 )
{
indent - - ;
}
else if ( wcscmp ( unesc , L " end " ) = = 0 )
{
indent - - ;
next_indent - - ;
}
if ( do_indent & & flags )
{
insert_tabs ( out , indent ) ;
}
2007-04-23 04:54:29 +10:00
sb_printf ( out , L " %ls " , last ) ;
2007-04-22 20:03:12 +10:00
indent = next_indent ;
}
else
{
2007-04-23 04:54:29 +10:00
sb_printf ( out , L " %ls " , last ) ;
2007-04-22 20:03:12 +10:00
}
break ;
}
case TOK_END :
{
2007-04-23 04:54:29 +10:00
if ( prev_type ! = TOK_END | | prev_prev_type ! = TOK_END )
sb_append ( out , L " \n " ) ;
2007-04-22 20:03:12 +10:00
do_indent = 1 ;
is_command = 1 ;
break ;
}
case TOK_PIPE :
{
sb_append ( out , L " | " ) ;
is_command = 1 ;
break ;
}
case TOK_REDIRECT_OUT :
case TOK_REDIRECT_APPEND :
case TOK_REDIRECT_IN :
case TOK_REDIRECT_FD :
{
sb_append ( out , last ) ;
switch ( type )
{
case TOK_REDIRECT_OUT :
sb_append ( out , L " > " ) ;
break ;
case TOK_REDIRECT_APPEND :
sb_append ( out , L " >> " ) ;
break ;
case TOK_REDIRECT_IN :
sb_append ( out , L " < " ) ;
break ;
case TOK_REDIRECT_FD :
sb_append ( out , L " >& " ) ;
break ;
}
break ;
}
case TOK_BACKGROUND :
{
sb_append ( out , L " & \n " ) ;
do_indent = 1 ;
is_command = 1 ;
break ;
}
case TOK_COMMENT :
{
2007-04-23 04:54:29 +10:00
if ( do_indent & & flags )
{
insert_tabs ( out , indent ) ;
}
2007-04-22 20:03:12 +10:00
sb_printf ( out , L " %ls " , last ) ;
do_indent = 1 ;
break ;
}
default :
{
debug ( 0 , L " Unknown wha? %ls " , last ) ;
exit ( 1 ) ;
}
}
2007-04-23 04:54:29 +10:00
prev_prev_type = prev_type ;
prev_type = type ;
2007-04-22 20:03:12 +10:00
}
tok_destroy ( & tok ) ;
return res ;
}
2007-04-23 04:54:29 +10:00
wchar_t * trim ( wchar_t * in )
{
wchar_t * end ;
while ( * in = = L ' \n ' )
{
in + + ;
}
end = in + wcslen ( in ) ;
while ( 1 )
{
if ( end < in + 2 )
break ;
end - - ;
if ( ( * end = = L ' \n ' ) & & ( * ( end - 1 ) = = L ' \n ' ) )
* end = 0 ;
else
break ;
}
return in ;
}
2007-04-22 20:03:12 +10:00
int main ( int argc , char * * argv )
{
string_buffer_t sb_in ;
string_buffer_t sb_out ;
int do_indent = 1 ;
wsetlocale ( LC_ALL , L " " ) ;
program_name = L " fish_indent " ;
while ( 1 )
{
static struct option
long_options [ ] =
{
{
" no-indent " , no_argument , 0 , ' i '
}
,
{
" help " , no_argument , 0 , ' h '
}
,
{
" version " , no_argument , 0 , ' v '
}
,
{
0 , 0 , 0 , 0
}
}
;
int opt_index = 0 ;
int opt = getopt_long ( argc ,
argv ,
GETOPT_STRING ,
long_options ,
& opt_index ) ;
if ( opt = = - 1 )
break ;
switch ( opt )
{
case 0 :
{
break ;
}
case ' h ' :
{
print_help ( " fish_indent " , 1 ) ;
exit ( 0 ) ;
break ;
}
case ' v ' :
{
fwprintf ( stderr ,
_ ( L " %ls, version %s \n " ) ,
program_name ,
PACKAGE_VERSION ) ;
exit ( 0 ) ;
}
case ' i ' :
{
do_indent = 0 ;
break ;
}
case ' ? ' :
{
exit ( 1 ) ;
}
}
}
halloc_util_init ( ) ;
sb_init ( & sb_in ) ;
sb_init ( & sb_out ) ;
read_file ( stdin , & sb_in ) ;
wutil_init ( ) ;
if ( ! indent ( & sb_out , ( wchar_t * ) sb_in . buff , do_indent ) )
{
2007-04-23 04:54:29 +10:00
fwprintf ( stdout , L " %ls " , trim ( ( wchar_t * ) sb_out . buff ) ) ;
2007-04-22 20:03:12 +10:00
}
else
{
/*
Indenting failed - print original input
*/
2007-04-23 04:54:29 +10:00
fwprintf ( stdout , L " %ls " , ( wchar_t * ) sb_in . buff ) ;
2007-04-22 20:03:12 +10:00
}
wutil_destroy ( ) ;
halloc_util_destroy ( ) ;
return 0 ;
}