X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=coreutils%2Fexpand.c;h=64f2a539dabd277d29c6e73fc21d91fb334be03c;hb=86d5bf4246a7ba68d220bc6c7a7a3be62119dc12;hp=c0133956fc27e4d88969894de632f9ac05c9b97a;hpb=68404f13d4bf4826e3609703dad5375763db28ab;p=oweals%2Fbusybox.git diff --git a/coreutils/expand.c b/coreutils/expand.c index c0133956f..64f2a539d 100644 --- a/coreutils/expand.c +++ b/coreutils/expand.c @@ -3,25 +3,82 @@ * * Copyright (C) 89, 91, 1995-2006 Free Software Foundation, Inc. * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * Licensed under GPLv2 or later, see file LICENSE in this source tree. * * David MacKenzie * * Options for expand: - * -t num --tabs=NUM Convert tabs to num spaces (default 8 spaces). + * -t num --tabs NUM Convert tabs to num spaces (default 8 spaces). * -i --initial Only convert initial tabs on each line to spaces. * * Options for unexpand: * -a --all Convert all blanks, instead of just initial blanks. * -f --first-only Convert only leading sequences of blanks (default). - * -t num --tabs=NUM Have tabs num characters apart instead of 8. + * -t num --tabs NUM Have tabs num characters apart instead of 8. * * Busybox version (C) 2007 by Tito Ragusa * * Caveat: this versions of expand and unexpand don't accept tab lists. */ +//config:config EXPAND +//config: bool "expand (5.8 kb)" +//config: default y +//config: help +//config: By default, convert all tabs to spaces. +//config: +//config:config FEATURE_EXPAND_LONG_OPTIONS +//config: bool "Enable long options" +//config: default y +//config: depends on EXPAND && LONG_OPTS +//config: +//config:config UNEXPAND +//config: bool "unexpand (6 kb)" +//config: default y +//config: help +//config: By default, convert only leading sequences of blanks to tabs. +//config: +//config:config FEATURE_UNEXPAND_LONG_OPTIONS +//config: bool "Enable long options" +//config: default y +//config: depends on UNEXPAND && LONG_OPTS + +//applet:IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, BB_DIR_USR_BIN, BB_SUID_DROP, unexpand)) + +//kbuild:lib-$(CONFIG_EXPAND) += expand.o +//kbuild:lib-$(CONFIG_UNEXPAND) += expand.o + +//usage:#define expand_trivial_usage +//usage: "[-i] [-t N] [FILE]..." +//usage:#define expand_full_usage "\n\n" +//usage: "Convert tabs to spaces, writing to stdout\n" +//usage: IF_FEATURE_EXPAND_LONG_OPTIONS( +//usage: "\n -i,--initial Don't convert tabs after non blanks" +//usage: "\n -t,--tabs N Tabstops every N chars" +//usage: ) +//usage: IF_NOT_FEATURE_EXPAND_LONG_OPTIONS( +//usage: "\n -i Don't convert tabs after non blanks" +//usage: "\n -t Tabstops every N chars" +//usage: ) + +//usage:#define unexpand_trivial_usage +//usage: "[-fa][-t N] [FILE]..." +//usage:#define unexpand_full_usage "\n\n" +//usage: "Convert spaces to tabs, writing to stdout\n" +//usage: IF_FEATURE_UNEXPAND_LONG_OPTIONS( +//usage: "\n -a,--all Convert all blanks" +//usage: "\n -f,--first-only Convert only leading blanks" +//usage: "\n -t,--tabs N Tabstops every N chars" +//usage: ) +//usage: IF_NOT_FEATURE_UNEXPAND_LONG_OPTIONS( +//usage: "\n -a Convert all blanks" +//usage: "\n -f Convert only leading blanks" +//usage: "\n -t N Tabstops every N chars" +//usage: ) #include "libbb.h" +#include "unicode.h" enum { OPT_INITIAL = 1 << 0, @@ -29,104 +86,100 @@ enum { OPT_ALL = 1 << 2, }; -static void xputchar(char c) -{ - if (putchar(c) < 0) - bb_error_msg_and_die(bb_msg_write_error); -} - #if ENABLE_EXPAND static void expand(FILE *file, unsigned tab_size, unsigned opt) { char *line; - char *ptr; - int convert; - int pos; - - /* Increment tab_size by 1 locally.*/ - tab_size++; while ((line = xmalloc_fgets(file)) != NULL) { - convert = 1; - pos = 0; - ptr = line; - while (*line) { - pos++; - if (*line == '\t' && convert) { - for (; pos < tab_size; pos++) { - xputchar(' '); - } - } else { - if ((opt & OPT_INITIAL) && !isblank(*line)) { - convert = 0; - } - xputchar(*line); + unsigned char c; + char *ptr; + char *ptr_strbeg; + + ptr = ptr_strbeg = line; + while ((c = *ptr) != '\0') { + if ((opt & OPT_INITIAL) && !isblank(c)) { + /* not space or tab */ + break; } - if (pos == tab_size) { - pos = 0; + if (c == '\t') { + unsigned len; + *ptr = '\0'; +# if ENABLE_UNICODE_SUPPORT + len = unicode_strwidth(ptr_strbeg); +# else + len = ptr - ptr_strbeg; +# endif + len = tab_size - (len % tab_size); + /*while (ptr[1] == '\t') { ptr++; len += tab_size; } - can handle many tabs at once */ + printf("%s%*s", ptr_strbeg, len, ""); + ptr_strbeg = ptr + 1; } - line++; + ptr++; } - free(ptr); + fputs(ptr_strbeg, stdout); + free(line); } } #endif #if ENABLE_UNEXPAND -static void unexpand(FILE *file, unsigned int tab_size, unsigned opt) +static void unexpand(FILE *file, unsigned tab_size, unsigned opt) { char *line; - char *ptr; - int convert; - int pos; - int i = 0; - int column = 0; while ((line = xmalloc_fgets(file)) != NULL) { - convert = 1; - pos = 0; - ptr = line; - while (*line) { - while ((*line == ' ' || *line == '\t') && convert) { - pos += (*line == ' ') ? 1 : tab_size; - line++; - column++; - if ((opt & OPT_ALL) && column == tab_size) { - column = 0; - goto put_tab; - } + char *ptr = line; + unsigned column = 0; + + while (*ptr) { + unsigned n; + unsigned len = 0; + + while (*ptr == ' ') { + ptr++; + len++; + } + column += len; + if (*ptr == '\t') { + column += tab_size - (column % tab_size); + ptr++; + continue; } - if (pos) { - i = pos / tab_size; - if (i) { - for (; i > 0; i--) { - put_tab: - xputchar('\t'); - } - } else { - for (i = pos % tab_size; i > 0; i--) { - xputchar(' '); - } - } - pos = 0; - } else { - if (opt & OPT_INITIAL) { - convert = 0; - } - if (opt & OPT_ALL) { - column++; - } - xputchar(*line); - line++; + + n = column / tab_size; + if (n) { + len = column = column % tab_size; + while (n--) + putchar('\t'); + } + + if ((opt & OPT_INITIAL) && ptr != line) { + printf("%*s%s", len, "", ptr); + break; + } + n = strcspn(ptr, "\t "); + printf("%*s%.*s", len, "", n, ptr); +# if ENABLE_UNICODE_SUPPORT + { + char c = ptr[n]; + ptr[n] = '\0'; + len = unicode_strwidth(ptr); + ptr[n] = c; } +# else + len = n; +# endif + ptr += n; + column = (column + len) % tab_size; } - free(ptr); + free(line); } } #endif int expand_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int expand_main(int argc ATTRIBUTE_UNUSED, char **argv) +int expand_main(int argc UNUSED_PARAM, char **argv) { /* Default 8 spaces for 1 tab */ const char *opt_t = "8"; @@ -150,12 +203,13 @@ int expand_main(int argc ATTRIBUTE_UNUSED, char **argv) "all\0" No_argument "a" ; #endif + init_unicode(); if (ENABLE_EXPAND && (!ENABLE_UNEXPAND || applet_name[0] == 'e')) { - USE_FEATURE_EXPAND_LONG_OPTIONS(applet_long_options = expand_longopts); + IF_FEATURE_EXPAND_LONG_OPTIONS(applet_long_options = expand_longopts); opt = getopt32(argv, "it:", &opt_t); - } else if (ENABLE_UNEXPAND) { - USE_FEATURE_UNEXPAND_LONG_OPTIONS(applet_long_options = unexpand_longopts); + } else { + IF_FEATURE_UNEXPAND_LONG_OPTIONS(applet_long_options = unexpand_longopts); /* -t NUM sets also -a */ opt_complementary = "ta"; opt = getopt32(argv, "ft:a", &opt_t); @@ -166,32 +220,23 @@ int expand_main(int argc ATTRIBUTE_UNUSED, char **argv) argv += optind; - /* If no args are given, read from stdin */ if (!*argv) { *--argv = (char*)bb_msg_standard_input; - goto use_stdin; } - do { - if (NOT_LONE_CHAR(*argv, '-')) { - file = fopen_or_warn(*argv, "r"); - if (!file) { - exit_status = EXIT_FAILURE; - continue; - } - } else { - use_stdin: - file = stdin; + file = fopen_or_warn_stdin(*argv); + if (!file) { + exit_status = EXIT_FAILURE; + continue; } if (ENABLE_EXPAND && (!ENABLE_UNEXPAND || applet_name[0] == 'e')) - USE_EXPAND(expand(file, tab_size, opt)); - else if (ENABLE_UNEXPAND) - USE_UNEXPAND(unexpand(file, tab_size, opt)); + IF_EXPAND(expand(file, tab_size, opt)); + else + IF_UNEXPAND(unexpand(file, tab_size, opt)); /* Check and close the file */ - /* We do want all of them to execute, thus | instead of || */ - if (ferror(file) | fclose_if_not_stdin(file)) { + if (fclose_if_not_stdin(file)) { bb_simple_perror_msg(*argv); exit_status = EXIT_FAILURE; }