busybox/util-linux/rev.c
<<
>>
Prefs
   1/*
   2 * rev implementation for busybox
   3 *
   4 * Copyright (C) 2010 Marek Polacek <mmpolacek@gmail.com>
   5 *
   6 * Licensed under GPLv2, see file LICENSE in this source tree.
   7 */
   8//config:config REV
   9//config:       bool "rev (4.4 kb)"
  10//config:       default y
  11//config:       help
  12//config:       Reverse lines of a file or files.
  13
  14//applet:IF_REV(APPLET(rev, BB_DIR_BIN, BB_SUID_DROP))
  15
  16//kbuild:lib-$(CONFIG_REV) += rev.o
  17
  18//usage:#define rev_trivial_usage
  19//usage:        "[FILE]..."
  20//usage:#define rev_full_usage "\n\n"
  21//usage:        "Reverse lines of FILE"
  22
  23#include "libbb.h"
  24#include "unicode.h"
  25
  26#undef CHAR_T
  27#if ENABLE_UNICODE_SUPPORT
  28# define CHAR_T wchar_t
  29#else
  30# define CHAR_T char
  31#endif
  32
  33/* In-place invert */
  34static void strrev(CHAR_T *s, int len)
  35{
  36        int i;
  37
  38        if (len != 0) {
  39                len--;
  40                if (len != 0 && s[len] == '\n')
  41                        len--;
  42        }
  43
  44        for (i = 0; i < len; i++, len--) {
  45                CHAR_T c = s[i];
  46                s[i] = s[len];
  47                s[len] = c;
  48        }
  49}
  50
  51int rev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  52int rev_main(int argc UNUSED_PARAM, char **argv)
  53{
  54        int retval;
  55        size_t bufsize;
  56        char *buf;
  57
  58        init_unicode();
  59
  60        getopt32(argv, "");
  61        argv += optind;
  62        if (!argv[0])
  63                argv = (char **)&bb_argv_dash;
  64
  65        retval = EXIT_SUCCESS;
  66        bufsize = 256;
  67        buf = xmalloc(bufsize);
  68        do {
  69                size_t pos;
  70                FILE *fp;
  71
  72                fp = fopen_or_warn_stdin(*argv++);
  73                if (!fp) {
  74                        retval = EXIT_FAILURE;
  75                        continue;
  76                }
  77
  78                pos = 0;
  79                while (1) {
  80                        /* Read one line */
  81                        buf[bufsize - 1] = 1; /* not 0 */
  82                        if (!fgets(buf + pos, bufsize - pos, fp))
  83                                break; /* EOF/error */
  84                        if (buf[bufsize - 1] == '\0' /* fgets filled entire buffer */
  85                         && buf[bufsize - 2] != '\n' /* and did not read '\n' */
  86                         && !feof(fp)
  87                        ) {
  88                                /* Line is too long, extend buffer */
  89                                pos = bufsize - 1;
  90                                bufsize += 64 + bufsize / 8;
  91                                buf = xrealloc(buf, bufsize);
  92                                continue;
  93                        }
  94
  95                        /* Process and print it */
  96#if ENABLE_UNICODE_SUPPORT
  97                        {
  98                                wchar_t *tmp = xmalloc(bufsize * sizeof(wchar_t));
  99                                /* Convert to wchar_t (might error out!) */
 100                                int len  = mbstowcs(tmp, buf, bufsize);
 101                                if (len >= 0) {
 102                                        strrev(tmp, len);
 103                                        /* Convert back to char */
 104                                        wcstombs(buf, tmp, bufsize);
 105                                }
 106                                free(tmp);
 107                        }
 108#else
 109                        strrev(buf, strlen(buf));
 110#endif
 111                        fputs_stdout(buf);
 112                        pos = 0;
 113                }
 114                fclose(fp);
 115        } while (*argv);
 116
 117        if (ENABLE_FEATURE_CLEAN_UP)
 118                free(buf);
 119
 120        fflush_stdout_and_exit(retval);
 121}
 122