2007-04-22 20:03:12 +10:00
/*
2008-01-13 05:18:48 +10:00
Copyright ( C ) 2005 - 2008 Axel Liljencrantz
2007-04-22 20:03:12 +10:00
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 .
*/
2008-01-14 02:47:47 +10:00
/** \file fish_indent.c
2007-08-02 03:38:01 +10:00
The fish_indent proegram .
2007-04-22 20:03:12 +10:00
*/
# include "config.h"
# include <stdlib.h>
# include <stdio.h>
# include <wchar.h>
# include <string.h>
# include <errno.h>
# include <unistd.h>
# ifdef HAVE_GETOPT_H
# include <getopt.h>
# endif
# include <locale.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"
2008-01-14 02:47:47 +10:00
/**
Read the entire contents of a file into the specified string_Buffer_t
*/
static void read_file ( FILE * f , string_buffer_t * b )
2007-04-22 20:03:12 +10:00
{
while ( 1 )
{
2008-01-14 02:49:05 +10:00
errno = 0 ;
2007-04-22 20:03:12 +10:00
wint_t c = fgetwc ( f ) ;
if ( c = = WEOF )
{
2008-01-14 02:49:05 +10:00
if ( errno )
{
wperror ( L " fgetwc " ) ;
exit ( 1 ) ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
break ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
sb_append_char ( b , c ) ;
}
}
2008-01-14 02:47:47 +10:00
/**
Insert the specified number of tabe into the output buffer
*/
2007-04-22 20:03:12 +10:00
static void insert_tabs ( string_buffer_t * out , int indent )
{
int i ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
for ( i = 0 ; i < indent ; i + + )
{
sb_append ( out , L " \t " ) ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
}
2008-01-14 02:47:47 +10:00
/**
Indent the specified input
*/
2007-04-22 20:03:12 +10:00
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 ) ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
for ( ; tok_has_next ( & tok ) ; tok_next ( & tok ) )
{
int type = tok_last_type ( & tok ) ;
wchar_t * last = tok_last ( & tok ) ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
switch ( type )
{
case TOK_STRING :
{
if ( is_command )
{
int next_indent = indent ;
is_command = 0 ;
wchar_t * unesc = unescape ( last , UNESCAPE_SPECIAL ) ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
if ( parser_keywords_is_block ( unesc ) )
{
next_indent + + ;
}
else if ( wcscmp ( unesc , L " else " ) = = 0 )
{
indent - - ;
}
2010-12-02 23:42:48 +08:00
/* case should have the same indent level as switch*/
else if ( wcscmp ( unesc , L " case " ) = = 0 )
{
indent - - ;
}
2007-04-22 20:03:12 +10:00
else if ( wcscmp ( unesc , L " end " ) = = 0 )
{
indent - - ;
next_indent - - ;
}
2011-12-26 19:18:46 -08:00
2010-12-02 23:42:24 +08:00
if ( do_indent & & flags & & prev_type ! = TOK_PIPE )
2007-04-22 20:03:12 +10:00
{
insert_tabs ( out , indent ) ;
}
2011-12-26 19:18:46 -08:00
2007-04-23 04:54:29 +10:00
sb_printf ( out , L " %ls " , last ) ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
indent = next_indent ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
}
else
{
2010-12-01 13:05:10 +08:00
if ( prev_type ! = TOK_REDIRECT_FD )
sb_append ( out , L " " ) ;
sb_append ( out , last ) ;
2007-04-22 20:03:12 +10:00
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
break ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
case TOK_END :
{
2011-12-26 19:18:46 -08:00
if ( prev_type ! = TOK_END | | prev_prev_type ! = TOK_END )
2007-04-23 04:54:29 +10:00
sb_append ( out , L " \n " ) ;
2007-04-22 20:03:12 +10:00
do_indent = 1 ;
is_command = 1 ;
break ;
}
case TOK_PIPE :
{
2010-12-01 13:05:10 +08:00
sb_append ( out , L " " ) ;
if ( last [ 0 ] = = ' 2 ' & & ! last [ 1 ] ) {
sb_append ( out , L " ^ " ) ;
} else if ( last [ 0 ] ! = ' 1 ' | | last [ 1 ] ) {
sb_append ( out , last , L " > " ) ;
}
2011-12-26 19:18:46 -08:00
sb_append ( out , L " | " ) ;
2007-04-22 20:03:12 +10:00
is_command = 1 ;
break ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
case TOK_REDIRECT_OUT :
{
2010-12-01 13:05:10 +08:00
sb_append ( out , L " " ) ;
if ( wcscmp ( last , L " 2 " ) = = 0 ) {
sb_append ( out , L " ^ " ) ;
} else {
if ( wcscmp ( last , L " 1 " ) ! = 0 )
2011-12-26 19:18:46 -08:00
sb_append ( out , last ) ;
sb_append ( out , L " > " ) ;
2010-12-01 13:05:10 +08:00
}
2011-12-26 19:18:46 -08:00
break ;
2010-12-01 13:05:10 +08:00
}
2011-12-26 19:18:46 -08:00
case TOK_REDIRECT_APPEND :
2010-12-01 13:05:10 +08:00
{
sb_append ( out , L " " ) ;
if ( wcscmp ( last , L " 2 " ) = = 0 ) {
sb_append ( out , L " ^^ " ) ;
} else {
if ( wcscmp ( last , L " 1 " ) ! = 0 )
sb_append ( out , last ) ;
2011-12-26 19:18:46 -08:00
sb_append ( out , L " >> " ) ;
2007-04-22 20:03:12 +10:00
}
2011-12-26 19:18:46 -08:00
break ;
2007-04-22 20:03:12 +10:00
}
2011-12-26 19:18:46 -08:00
case TOK_REDIRECT_IN :
2010-12-01 13:05:10 +08:00
{
sb_append ( out , L " " ) ;
if ( wcscmp ( last , L " 0 " ) ! = 0 )
sb_append ( out , last ) ;
2011-12-26 19:18:46 -08:00
sb_append ( out , L " < " ) ;
break ;
2010-12-01 13:05:10 +08:00
}
2011-12-26 19:18:46 -08:00
case TOK_REDIRECT_FD :
2010-12-01 13:05:10 +08:00
{
sb_append ( out , L " " ) ;
if ( wcscmp ( last , L " 1 " ) ! = 0 )
sb_append ( out , last ) ;
2011-12-26 19:18:46 -08:00
sb_append ( out , L " >& " ) ;
break ;
}
2007-04-22 20:03:12 +10:00
case TOK_BACKGROUND :
{
sb_append ( out , L " & \n " ) ;
do_indent = 1 ;
is_command = 1 ;
break ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
case TOK_COMMENT :
{
2007-04-23 04:54:29 +10:00
if ( do_indent & & flags )
{
insert_tabs ( out , indent ) ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
sb_printf ( out , L " %ls " , last ) ;
do_indent = 1 ;
2011-12-26 19:18:46 -08:00
break ;
2007-04-22 20:03:12 +10:00
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
default :
{
2007-09-22 00:07:52 +10:00
debug ( 0 , L " Unknown token '%ls' " , last ) ;
2007-04-22 20:03:12 +10:00
exit ( 1 ) ;
2011-12-26 19:18:46 -08:00
}
2007-04-22 20:03:12 +10:00
}
2011-12-26 19:18:46 -08:00
2007-04-23 04:54:29 +10:00
prev_prev_type = prev_type ;
prev_type = type ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
tok_destroy ( & tok ) ;
return res ;
}
2008-01-14 02:47:47 +10:00
/**
Remove any prefix and suffix newlines from the specified
string . Does not allocete a new string , edits the string in place
and returns a pointer somewhere into the string .
*/
static wchar_t * trim ( wchar_t * in )
2007-04-23 04:54:29 +10:00
{
wchar_t * end ;
2011-12-26 19:18:46 -08:00
2007-04-23 04:54:29 +10:00
while ( * in = = L ' \n ' )
{
in + + ;
}
2011-12-26 19:18:46 -08:00
2007-04-23 04:54:29 +10:00
end = in + wcslen ( in ) ;
2011-12-26 19:18:46 -08:00
2007-04-23 04:54:29 +10:00
while ( 1 )
{
if ( end < in + 2 )
break ;
end - - ;
2011-12-26 19:18:46 -08:00
2007-04-23 04:54:29 +10:00
if ( ( * end = = L ' \n ' ) & & ( * ( end - 1 ) = = L ' \n ' ) )
* end = 0 ;
else
break ;
}
2011-12-26 19:18:46 -08:00
2007-04-23 04:54:29 +10:00
return in ;
}
2008-01-14 02:47:47 +10:00
/**
The main mathod . Run the program .
*/
2007-04-22 20:03:12 +10:00
int main ( int argc , char * * argv )
{
string_buffer_t sb_in ;
string_buffer_t sb_out ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
int do_indent = 1 ;
2012-01-05 13:58:48 -08:00
set_main_thread ( ) ;
2007-04-22 20:03:12 +10:00
wsetlocale ( LC_ALL , L " " ) ;
program_name = L " fish_indent " ;
while ( 1 )
{
static struct option
long_options [ ] =
{
{
2011-12-26 19:18:46 -08:00
" no-indent " , no_argument , 0 , ' i '
2007-04-22 20:03:12 +10:00
}
,
{
2011-12-26 19:18:46 -08:00
" help " , no_argument , 0 , ' h '
2007-04-22 20:03:12 +10:00
}
,
{
2011-12-26 19:18:46 -08:00
" version " , no_argument , 0 , ' v '
2007-04-22 20:03:12 +10:00
}
,
2011-12-26 19:18:46 -08:00
{
0 , 0 , 0 , 0
2007-04-22 20:03:12 +10:00
}
}
;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
int opt_index = 0 ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
int opt = getopt_long ( argc ,
2011-12-26 19:18:46 -08:00
argv ,
2007-09-22 00:07:52 +10:00
GETOPT_STRING ,
2011-12-26 19:18:46 -08:00
long_options ,
2007-09-22 00:07:52 +10:00
& opt_index ) ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
if ( opt = = - 1 )
break ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
switch ( opt )
{
case 0 :
{
break ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
case ' h ' :
{
print_help ( " fish_indent " , 1 ) ;
2011-12-26 19:18:46 -08:00
exit ( 0 ) ;
2007-04-22 20:03:12 +10:00
break ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
case ' v ' :
{
2011-12-26 19:18:46 -08:00
fwprintf ( stderr ,
_ ( L " %ls, version %s \n " ) ,
2007-04-22 20:03:12 +10:00
program_name ,
PACKAGE_VERSION ) ;
2011-12-26 19:18:46 -08:00
exit ( 0 ) ;
2007-04-22 20:03:12 +10:00
}
case ' i ' :
{
do_indent = 0 ;
break ;
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
case ' ? ' :
{
exit ( 1 ) ;
}
2011-12-26 19:18:46 -08:00
}
2007-04-22 20:03:12 +10:00
}
2011-12-26 19:18:46 -08:00
halloc_util_init ( ) ;
2007-04-22 20:03:12 +10:00
sb_init ( & sb_in ) ;
sb_init ( & sb_out ) ;
read_file ( stdin , & sb_in ) ;
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
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
}
2011-12-26 19:18:46 -08:00
2007-04-22 20:03:12 +10:00
wutil_destroy ( ) ;
halloc_util_destroy ( ) ;
return 0 ;
}