123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /* expand - convert tabs to spaces
- * unexpand - convert spaces to tabs
- *
- * Copyright (C) 89, 91, 1995-2006 Free Software Foundation, Inc.
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- *
- * David MacKenzie <djm@gnu.ai.mit.edu>
- *
- * Options for expand:
- * -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.
- *
- * Busybox version (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
- *
- * Caveat: this versions of expand and unexpand don't accept tab lists.
- */
- #include "libbb.h"
- enum {
- OPT_INITIAL = 1 << 0,
- OPT_TABS = 1 << 1,
- 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;
- unsigned 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);
- }
- if (pos == tab_size) {
- pos = 0;
- }
- line++;
- }
- free(ptr);
- }
- }
- #endif
- #if ENABLE_UNEXPAND
- static void unexpand(FILE *file, unsigned int tab_size, unsigned opt)
- {
- char *line;
- char *ptr;
- int convert;
- int pos;
- int i = 0;
- unsigned 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;
- }
- }
- 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++;
- }
- }
- free(ptr);
- }
- }
- #endif
- int expand_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
- int expand_main(int argc ATTRIBUTE_UNUSED, char **argv)
- {
- /* Default 8 spaces for 1 tab */
- const char *opt_t = "8";
- FILE *file;
- unsigned tab_size;
- unsigned opt;
- int exit_status = EXIT_SUCCESS;
- #if ENABLE_FEATURE_EXPAND_LONG_OPTIONS
- static const char expand_longopts[] ALIGN1 =
- /* name, has_arg, val */
- "initial\0" No_argument "i"
- "tabs\0" Required_argument "t"
- ;
- #endif
- #if ENABLE_FEATURE_UNEXPAND_LONG_OPTIONS
- static const char unexpand_longopts[] ALIGN1 =
- /* name, has_arg, val */
- "first-only\0" No_argument "i"
- "tabs\0" Required_argument "t"
- "all\0" No_argument "a"
- ;
- #endif
- if (ENABLE_EXPAND && (!ENABLE_UNEXPAND || applet_name[0] == 'e')) {
- USE_FEATURE_EXPAND_LONG_OPTIONS(applet_long_options = expand_longopts);
- opt = getopt32(argv, "it:", &opt_t);
- } else {
- USE_FEATURE_UNEXPAND_LONG_OPTIONS(applet_long_options = unexpand_longopts);
- /* -t NUM sets also -a */
- opt_complementary = "ta";
- opt = getopt32(argv, "ft:a", &opt_t);
- /* -f --first-only is the default */
- if (!(opt & OPT_ALL)) opt |= OPT_INITIAL;
- }
- tab_size = xatou_range(opt_t, 1, UINT_MAX);
- argv += optind;
- if (!*argv) {
- *--argv = (char*)bb_msg_standard_input;
- }
- do {
- 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
- USE_UNEXPAND(unexpand(file, tab_size, opt));
- /* Check and close the file */
- if (fclose_if_not_stdin(file)) {
- bb_simple_perror_msg(*argv);
- exit_status = EXIT_FAILURE;
- }
- /* If stdin also clear EOF */
- if (file == stdin)
- clearerr(file);
- } while (*++argv);
- /* Now close stdin also */
- /* (if we didn't read from it, it's a no-op) */
- if (fclose(stdin))
- bb_perror_msg_and_die(bb_msg_standard_input);
- fflush_stdout_and_exit(exit_status);
- }
|