diff options
author | ridiculousfish <corydoras@ridiculousfish.com> | 2011-12-26 19:11:54 -0800 |
---|---|---|
committer | ridiculousfish <corydoras@ridiculousfish.com> | 2011-12-26 19:11:54 -0800 |
commit | 3f16ace6784caab54fb054836ee93902e9701913 (patch) | |
tree | 6ae6170f86bd45ce7fd0dae4a4242bb8dc67c505 /fish_indent.cpp | |
parent | 834ea94eb97d37c65fcbf2fcc3b69303f6fb7e24 (diff) |
Initial C++ conversion
Diffstat (limited to 'fish_indent.cpp')
-rw-r--r-- | fish_indent.cpp | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/fish_indent.cpp b/fish_indent.cpp new file mode 100644 index 00000000..14cf5a6c --- /dev/null +++ b/fish_indent.cpp @@ -0,0 +1,408 @@ +/* +Copyright (C) 2005-2008 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 fish_indent.c + The fish_indent proegram. +*/ + +#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" + +/** + Read the entire contents of a file into the specified string_Buffer_t + */ +static void read_file( FILE *f, string_buffer_t *b ) +{ + while( 1 ) + { + errno=0; + wint_t c = fgetwc( f ); + if( c == WEOF ) + { + if( errno ) + { + wperror(L"fgetwc"); + exit(1); + } + + break; + } + + sb_append_char( b, c ); + } +} + +/** + Insert the specified number of tabe into the output buffer + */ +static void insert_tabs( string_buffer_t *out, int indent ) +{ + int i; + + for( i=0; i<indent; i++ ) + { + sb_append( out, L"\t" ); + } + +} + +/** + Indent the specified input + */ +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; + int prev_type = 0; + int prev_prev_type = 0; + + 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--; + } + /* case should have the same indent level as switch*/ + else if( wcscmp( unesc, L"case" ) == 0 ) + { + indent--; + } + else if( wcscmp( unesc, L"end" ) == 0 ) + { + indent--; + next_indent--; + } + + + if( do_indent && flags && prev_type != TOK_PIPE ) + { + insert_tabs( out, indent ); + } + + sb_printf( out, L"%ls", last ); + + indent = next_indent; + + } + else + { + if ( prev_type != TOK_REDIRECT_FD ) + sb_append( out, L" " ); + sb_append( out, last ); + } + + break; + } + + case TOK_END: + { + if( prev_type != TOK_END || prev_prev_type != TOK_END ) + sb_append( out, L"\n" ); + do_indent = 1; + is_command = 1; + break; + } + + case TOK_PIPE: + { + 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">" ); + } + sb_append( out, L"| " ); + is_command = 1; + break; + } + + case TOK_REDIRECT_OUT: + { + 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 ); + sb_append( out, L">" ); + } + break; + } + + case TOK_REDIRECT_APPEND: + { + 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 ); + sb_append( out, L">>" ); + } + break; + } + + case TOK_REDIRECT_IN: + { + sb_append( out, L" " ); + if ( wcscmp( last, L"0" ) != 0 ) + sb_append( out, last ); + sb_append( out, L"<" ); + break; + } + + case TOK_REDIRECT_FD: + { + sb_append( out, L" " ); + if ( wcscmp( last, L"1" ) != 0 ) + sb_append( out, last ); + sb_append( out, L">&" ); + break; + } + + case TOK_BACKGROUND: + { + sb_append( out, L"&\n" ); + do_indent = 1; + is_command = 1; + break; + } + + case TOK_COMMENT: + { + if( do_indent && flags) + { + insert_tabs( out, indent ); + } + + sb_printf( out, L"%ls", last ); + do_indent = 1; + break; + } + + default: + { + debug( 0, L"Unknown token '%ls'", last ); + exit(1); + } + } + + prev_prev_type = prev_type; + prev_type = type; + + } + + tok_destroy( &tok ); + + return res; +} + +/** + 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 ) +{ + 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; +} + + +/** + The main mathod. Run the program. + */ +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 ) ) + { + fwprintf( stdout, L"%ls", trim( (wchar_t *)sb_out.buff) ); + } + else + { + /* + Indenting failed - print original input + */ + fwprintf( stdout, L"%ls", (wchar_t *)sb_in.buff ); + } + + + wutil_destroy(); + + halloc_util_destroy(); + + return 0; +} |