builtin-stripspace.con commit git-tag: Fix -l option to use better shell style globs. (18e32b5)
   1#include "builtin.h"
   2#include "cache.h"
   3
   4/*
   5 * Returns the length of a line, without trailing spaces.
   6 *
   7 * If the line ends with newline, it will be removed too.
   8 */
   9static size_t cleanup(char *line, size_t len)
  10{
  11        if (len) {
  12                if (line[len - 1] == '\n')
  13                        len--;
  14
  15                while (len) {
  16                        unsigned char c = line[len - 1];
  17                        if (!isspace(c))
  18                                break;
  19                        len--;
  20                }
  21        }
  22        return len;
  23}
  24
  25/*
  26 * Remove empty lines from the beginning and end
  27 * and also trailing spaces from every line.
  28 *
  29 * Note that the buffer will not be NUL-terminated.
  30 *
  31 * Turn multiple consecutive empty lines between paragraphs
  32 * into just one empty line.
  33 *
  34 * If the input has only empty lines and spaces,
  35 * no output will be produced.
  36 *
  37 * If last line has a newline at the end, it will be removed.
  38 *
  39 * Enable skip_comments to skip every line starting with "#".
  40 */
  41size_t stripspace(char *buffer, size_t length, int skip_comments)
  42{
  43        int empties = -1;
  44        size_t i, j, len, newlen;
  45        char *eol;
  46
  47        for (i = j = 0; i < length; i += len, j += newlen) {
  48                eol = memchr(buffer + i, '\n', length - i);
  49                len = eol ? eol - (buffer + i) + 1 : length - i;
  50
  51                if (skip_comments && len && buffer[i] == '#') {
  52                        newlen = 0;
  53                        continue;
  54                }
  55                newlen = cleanup(buffer + i, len);
  56
  57                /* Not just an empty line? */
  58                if (newlen) {
  59                        if (empties != -1)
  60                                buffer[j++] = '\n';
  61                        if (empties > 0)
  62                                buffer[j++] = '\n';
  63                        empties = 0;
  64                        memmove(buffer + j, buffer + i, newlen);
  65                        continue;
  66                }
  67                if (empties < 0)
  68                        continue;
  69                empties++;
  70        }
  71
  72        return j;
  73}
  74
  75int cmd_stripspace(int argc, const char **argv, const char *prefix)
  76{
  77        char *buffer;
  78        unsigned long size;
  79        int strip_comments = 0;
  80
  81        if (argc > 1 && (!strcmp(argv[1], "-s") ||
  82                                !strcmp(argv[1], "--strip-comments")))
  83                strip_comments = 1;
  84
  85        size = 1024;
  86        buffer = xmalloc(size);
  87        if (read_fd(0, &buffer, &size)) {
  88                free(buffer);
  89                die("could not read the input");
  90        }
  91
  92        size = stripspace(buffer, size, strip_comments);
  93        write_or_die(1, buffer, size);
  94        if (size)
  95                putc('\n', stdout);
  96
  97        free(buffer);
  98        return 0;
  99}