<repo_name>s6-debs/s6-portable-utils<file_sep>/src/skaembutils/s6-sort.c
/* ISC license. */

#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <errno.h>
#include <skalibs/allreadwrite.h>
#include <skalibs/sgetopt.h>
#include <skalibs/buffer.h>
#include <skalibs/strerr2.h>
#include <skalibs/stralloc.h>
#include <skalibs/genalloc.h>
#include <skalibs/djbunix.h>
#include <skalibs/skamisc.h>

#define USAGE "s6-sort [ -bcfru0 ]"

typedef int strncmp_t (char const *, char const *, size_t) ;
typedef strncmp_t *strncmp_t_ref ;
typedef int qsortcmp_t (void const *, void const *) ;
typedef qsortcmp_t *qsortcmp_t_ref ;

static int flagnoblanks = 0, flagreverse = 0, flaguniq = 0 ;

static strncmp_t_ref comp = &strncmp ;

static int compit (char const *s1, size_t n1, char const *s2, size_t n2)
{
  int r ;
  if (flagnoblanks)
  {
    while ((*s1 == ' ') || (*s1 == '\t')) (s1++, n1--) ;
    while ((*s2 == ' ') || (*s2 == '\t')) (s2++, n2--) ;
  }
  r = (*comp)(s1, s2, n1 < n2 ? n1 : n2) ;
  if (!r) r = n1 - n2 ;
  return flagreverse ? -r : r ;
}

static int sacmp (stralloc const *a, stralloc const *b)
{
  return compit(a->s, a->len - 1, b->s, b->len - 1) ;
}

static ssize_t slurplines (genalloc *lines, char sep)
{
  ssize_t i = 0 ;
  for (;; i++)
  {
    stralloc sa = STRALLOC_ZERO ;
    int r = skagetln(buffer_0, &sa, sep) ;
    if (!r) break ;
    if ((r < 0) && ((errno != EPIPE) || !stralloc_catb(&sa, &sep, 1)))
      return -1 ;
    stralloc_shrink(&sa) ;
    if (!genalloc_append(stralloc, lines, &sa)) return -1 ;
  }
  return i ;
}

static void uniq (genalloc *lines)
{
  size_t len = genalloc_len(stralloc, lines) ;
  stralloc *s = genalloc_s(stralloc, lines) ;
  size_t i = 1 ;
  for (; i < len ; i++)
    if (!sacmp(s+i-1, s+i)) stralloc_free(s+i-1) ;
}

static ssize_t outputlines (stralloc const *s, size_t len)
{
  size_t i = 0 ;
  for (; i < len ; i++)
    if (buffer_put(buffer_1, s[i].s, s[i].len) < 0) return 0 ;
  return buffer_flush(buffer_1) ;
}

static int check (stralloc const *s, size_t len)
{
  size_t i = 1 ;
  for (; i < len ; i++)
    if (sacmp(s+i-1, s+i) >= !flaguniq) return 0 ;
  return 1 ;
}

int main (int argc, char const *const *argv)
{
  genalloc lines = GENALLOC_ZERO ; /* array of stralloc */
  char sep = '\n' ;
  int flagcheck = 0 ;
  PROG = "s6-sort" ;
  {
    subgetopt l = SUBGETOPT_ZERO ;
    for (;;)
    {
      int opt = subgetopt_r(argc, argv, "bcfru0", &l) ;
      if (opt == -1) break ;
      switch (opt)
      {
        case 'b' : flagnoblanks = 1 ; break ;
        case 'c' : flagcheck = 1 ; break ;
        case 'f' : comp = &strncasecmp ; break ;
        case 'r' : flagreverse = 1 ; break ;
        case 'u' : flaguniq = 1 ; break ;
        case '0' : sep = '\0' ; break ;
        default : strerr_dieusage(100, USAGE) ;
      }
    }
    argc -= l.ind ; argv += l.ind ;
  }

  if (slurplines(&lines, sep) < 0) strerr_diefu1sys(111, "read from stdin") ;
  if (flagcheck) return !check(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines)) ;
  qsort(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines), sizeof(stralloc), (qsortcmp_t_ref)&sacmp) ;
  if (flaguniq) uniq(&lines) ;
  if (!outputlines(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines)))
    strerr_diefu1sys(111, "write to stdout") ;
  return 0 ;
}
<file_sep>/package/deps.mak
#
# This file has been generated by tools/gen-deps.sh
#

src/skaembutils/s6-basename.o src/skaembutils/s6-basename.lo: src/skaembutils/s6-basename.c
src/skaembutils/s6-cat.o src/skaembutils/s6-cat.lo: src/skaembutils/s6-cat.c
src/skaembutils/s6-chmod.o src/skaembutils/s6-chmod.lo: src/skaembutils/s6-chmod.c
src/skaembutils/s6-chown.o src/skaembutils/s6-chown.lo: src/skaembutils/s6-chown.c
src/skaembutils/s6-clock.o src/skaembutils/s6-clock.lo: src/skaembutils/s6-clock.c
src/skaembutils/s6-cut.o src/skaembutils/s6-cut.lo: src/skaembutils/s6-cut.c
src/skaembutils/s6-dirname.o src/skaembutils/s6-dirname.lo: src/skaembutils/s6-dirname.c
src/skaembutils/s6-dumpenv.o src/skaembutils/s6-dumpenv.lo: src/skaembutils/s6-dumpenv.c
src/skaembutils/s6-echo.o src/skaembutils/s6-echo.lo: src/skaembutils/s6-echo.c
src/skaembutils/s6-env.o src/skaembutils/s6-env.lo: src/skaembutils/s6-env.c src/include/s6-portable-utils/config.h
src/skaembutils/s6-expr.o src/skaembutils/s6-expr.lo: src/skaembutils/s6-expr.c
src/skaembutils/s6-false.o src/skaembutils/s6-false.lo: src/skaembutils/s6-false.c
src/skaembutils/s6-format-filter.o src/skaembutils/s6-format-filter.lo: src/skaembutils/s6-format-filter.c
src/skaembutils/s6-grep.o src/skaembutils/s6-grep.lo: src/skaembutils/s6-grep.c
src/skaembutils/s6-head.o src/skaembutils/s6-head.lo: src/skaembutils/s6-head.c
src/skaembutils/s6-hiercopy.o src/skaembutils/s6-hiercopy.lo: src/skaembutils/s6-hiercopy.c
src/skaembutils/s6-linkname.o src/skaembutils/s6-linkname.lo: src/skaembutils/s6-linkname.c
src/skaembutils/s6-ln.o src/skaembutils/s6-ln.lo: src/skaembutils/s6-ln.c
src/skaembutils/s6-ls.o src/skaembutils/s6-ls.lo: src/skaembutils/s6-ls.c
src/skaembutils/s6-maximumtime.o src/skaembutils/s6-maximumtime.lo: src/skaembutils/s6-maximumtime.c
src/skaembutils/s6-mkdir.o src/skaembutils/s6-mkdir.lo: src/skaembutils/s6-mkdir.c
src/skaembutils/s6-mkfifo.o src/skaembutils/s6-mkfifo.lo: src/skaembutils/s6-mkfifo.c
src/skaembutils/s6-nice.o src/skaembutils/s6-nice.lo: src/skaembutils/s6-nice.c
src/skaembutils/s6-nuke.o src/skaembutils/s6-nuke.lo: src/skaembutils/s6-nuke.c
src/skaembutils/s6-pause.o src/skaembutils/s6-pause.lo: src/skaembutils/s6-pause.c
src/skaembutils/s6-printenv.o src/skaembutils/s6-printenv.lo: src/skaembutils/s6-printenv.c
src/skaembutils/s6-quote-filter.o src/skaembutils/s6-quote-filter.lo: src/skaembutils/s6-quote-filter.c
src/skaembutils/s6-quote.o src/skaembutils/s6-quote.lo: src/skaembutils/s6-quote.c
src/skaembutils/s6-rename.o src/skaembutils/s6-rename.lo: src/skaembutils/s6-rename.c
src/skaembutils/s6-rmrf.o src/skaembutils/s6-rmrf.lo: src/skaembutils/s6-rmrf.c
src/skaembutils/s6-seq.o src/skaembutils/s6-seq.lo: src/skaembutils/s6-seq.c
src/skaembutils/s6-sleep.o src/skaembutils/s6-sleep.lo: src/skaembutils/s6-sleep.c
src/skaembutils/s6-sort.o src/skaembutils/s6-sort.lo: src/skaembutils/s6-sort.c
src/skaembutils/s6-sync.o src/skaembutils/s6-sync.lo: src/skaembutils/s6-sync.c
src/skaembutils/s6-tai64ndiff.o src/skaembutils/s6-tai64ndiff.lo: src/skaembutils/s6-tai64ndiff.c
src/skaembutils/s6-tail.o src/skaembutils/s6-tail.lo: src/skaembutils/s6-tail.c
src/skaembutils/s6-test.o src/skaembutils/s6-test.lo: src/skaembutils/s6-test.c
src/skaembutils/s6-touch.o src/skaembutils/s6-touch.lo: src/skaembutils/s6-touch.c
src/skaembutils/s6-true.o src/skaembutils/s6-true.lo: src/skaembutils/s6-true.c
src/skaembutils/s6-uniquename.o src/skaembutils/s6-uniquename.lo: src/skaembutils/s6-uniquename.c
src/skaembutils/s6-unquote-filter.o src/skaembutils/s6-unquote-filter.lo: src/skaembutils/s6-unquote-filter.c
src/skaembutils/s6-unquote.o src/skaembutils/s6-unquote.lo: src/skaembutils/s6-unquote.c
src/skaembutils/s6-update-symlinks.o src/skaembutils/s6-update-symlinks.lo: src/skaembutils/s6-update-symlinks.c
src/skaembutils/seekablepipe.o src/skaembutils/seekablepipe.lo: src/skaembutils/seekablepipe.c

s6-basename: EXTRA_LIBS := -lskarnet
s6-basename: src/skaembutils/s6-basename.o
s6-cat: EXTRA_LIBS := -lskarnet
s6-cat: src/skaembutils/s6-cat.o
s6-chmod: EXTRA_LIBS := -lskarnet
s6-chmod: src/skaembutils/s6-chmod.o
s6-chown: EXTRA_LIBS := -lskarnet
s6-chown: src/skaembutils/s6-chown.o
s6-clock: EXTRA_LIBS := -lskarnet ${SYSCLOCK_LIB}
s6-clock: src/skaembutils/s6-clock.o
s6-cut: EXTRA_LIBS := -lskarnet
s6-cut: src/skaembutils/s6-cut.o
s6-dirname: EXTRA_LIBS := -lskarnet
s6-dirname: src/skaembutils/s6-dirname.o
s6-dumpenv: EXTRA_LIBS := -lskarnet
s6-dumpenv: src/skaembutils/s6-dumpenv.o
s6-echo: EXTRA_LIBS := -lskarnet
s6-echo: src/skaembutils/s6-echo.o
s6-env: EXTRA_LIBS := -lskarnet
s6-env: src/skaembutils/s6-env.o
s6-expr: EXTRA_LIBS := -lskarnet
s6-expr: src/skaembutils/s6-expr.o
s6-false: EXTRA_LIBS :=
s6-false: src/skaembutils/s6-false.o
s6-format-filter: EXTRA_LIBS := -lskarnet
s6-format-filter: src/skaembutils/s6-format-filter.o
s6-grep: EXTRA_LIBS := -lskarnet
s6-grep: src/skaembutils/s6-grep.o
s6-head: EXTRA_LIBS := -lskarnet
s6-head: src/skaembutils/s6-head.o
s6-hiercopy: EXTRA_LIBS := -lskarnet
s6-hiercopy: src/skaembutils/s6-hiercopy.o
s6-linkname: EXTRA_LIBS := -lskarnet
s6-linkname: src/skaembutils/s6-linkname.o
s6-ln: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
s6-ln: src/skaembutils/s6-ln.o
s6-ls: EXTRA_LIBS := -lskarnet
s6-ls: src/skaembutils/s6-ls.o
s6-maximumtime: EXTRA_LIBS := -lskarnet ${SYSCLOCK_LIB} ${SPAWN_LIB}
s6-maximumtime: src/skaembutils/s6-maximumtime.o
s6-mkdir: EXTRA_LIBS := -lskarnet
s6-mkdir: src/skaembutils/s6-mkdir.o
s6-mkfifo: EXTRA_LIBS := -lskarnet
s6-mkfifo: src/skaembutils/s6-mkfifo.o
s6-nice: EXTRA_LIBS := -lskarnet
s6-nice: src/skaembutils/s6-nice.o
s6-nuke: EXTRA_LIBS := -lskarnet
s6-nuke: src/skaembutils/s6-nuke.o
s6-pause: EXTRA_LIBS := -lskarnet
s6-pause: src/skaembutils/s6-pause.o
s6-printenv: EXTRA_LIBS := -lskarnet
s6-printenv: src/skaembutils/s6-printenv.o
s6-quote: EXTRA_LIBS := -lskarnet
s6-quote: src/skaembutils/s6-quote.o
s6-quote-filter: EXTRA_LIBS := -lskarnet
s6-quote-filter: src/skaembutils/s6-quote-filter.o
s6-rename: EXTRA_LIBS := -lskarnet
s6-rename: src/skaembutils/s6-rename.o
s6-rmrf: EXTRA_LIBS := -lskarnet
s6-rmrf: src/skaembutils/s6-rmrf.o
s6-seq: EXTRA_LIBS := -lskarnet
s6-seq: src/skaembutils/s6-seq.o
s6-sleep: EXTRA_LIBS := -lskarnet ${SYSCLOCK_LIB}
s6-sleep: src/skaembutils/s6-sleep.o
s6-sort: EXTRA_LIBS := -lskarnet
s6-sort: src/skaembutils/s6-sort.o
s6-sync: EXTRA_LIBS :=
s6-sync: src/skaembutils/s6-sync.o
s6-tai64ndiff: EXTRA_LIBS := -lskarnet
s6-tai64ndiff: src/skaembutils/s6-tai64ndiff.o
s6-tail: EXTRA_LIBS := -lskarnet
s6-tail: src/skaembutils/s6-tail.o
s6-test: EXTRA_LIBS := -lskarnet
s6-test: src/skaembutils/s6-test.o
s6-touch: EXTRA_LIBS := -lskarnet
s6-touch: src/skaembutils/s6-touch.o
s6-true: EXTRA_LIBS :=
s6-true: src/skaembutils/s6-true.o
s6-uniquename: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
s6-uniquename: src/skaembutils/s6-uniquename.o
s6-unquote: EXTRA_LIBS := -lskarnet
s6-unquote: src/skaembutils/s6-unquote.o
s6-unquote-filter: EXTRA_LIBS := -lskarnet
s6-unquote-filter: src/skaembutils/s6-unquote-filter.o
s6-update-symlinks: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
s6-update-symlinks: src/skaembutils/s6-update-symlinks.o
seekablepipe: EXTRA_LIBS := -lskarnet
seekablepipe: src/skaembutils/seekablepipe.o
<file_sep>/package/targets.mak
BIN_TARGETS := \
s6-basename \
s6-cat \
s6-chmod \
s6-chown \
s6-clock \
s6-cut \
s6-dirname \
s6-dumpenv \
s6-echo \
s6-env \
s6-expr \
s6-false \
s6-format-filter \
s6-grep \
s6-head \
s6-hiercopy \
s6-linkname \
s6-ln \
s6-ls \
s6-maximumtime \
s6-mkdir \
s6-mkfifo \
s6-nice \
s6-nuke \
s6-pause \
s6-printenv \
s6-quote \
s6-quote-filter \
s6-rename \
s6-rmrf \
s6-seq \
s6-sleep \
s6-sort \
s6-sync \
s6-tai64ndiff \
s6-tail \
s6-test \
s6-touch \
s6-true \
s6-uniquename \
s6-unquote \
s6-unquote-filter \
s6-update-symlinks \
seekablepipe

LIBEXEC_TARGETS :=
