Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

cat.c

Name: Anonymous 2012-02-16 3:42

ITT: make your best, most elegant implementation of cat(1) in C. Doesn't have to be POSIX compliant; for example, mine takes no option arguments because that's how I think it should be, whereas I think that POSIX specifies a few options.

#include <stdio.h>
int main(int argc, char **argv) {
    char b[4096];
    FILE *f = stdin;
    int i;
    size_t s;
    if (argc == 1)
        goto noargs;
    for (i = 1; i < argc; i++) {
        f = fopen(argv[i], "rb");
        if (!f) {
            fprintf(stderr, "%s: failed to open %s\n", argv[0], argv[i]);
            continue;
        }
        noargs:
        while ((s = fread(b, 1, 4096, f)))
            fwrite(b, 1, s, stdout);
    }
    return 0;
}


Why is this the best in my opinion? It is short, simple, fast, serves just the purpose of concatenating files and no more, and even has a clever and elegant trick to handle the special case of no arguments without code duplication.

Name: Anonymous 2012-02-16 3:46

int main(void)
{
    return 1;
}


Mine isn't really POSIX compliant either, but it correctly returns something other than EXIT_SUCCESS when it fails to concatenate the files, so I feel it's still adequate.

Name: Anonymous 2012-02-16 3:47

>>2
Well, I could argue that while yours is adequate, mine is superior because yours has a provably 100% failure rate, while my failure rate is <= 100% depending on external factors.

Name: Anonymous 2012-02-16 3:48

>>1

This is perfect example of why declaring functions within functions with lexical scoping for the variables is a good language feature.

Name: Anonymous 2012-02-16 3:48

>>4
I don't see how this is an example of the necessity of nested functions with lexical scoping. Please elaborate.

Name: Anonymous 2012-02-16 4:05

>>5
I can't do it using standard C, but:

        while ((s = fread(b, 1, 4096, f)))
            fwrite(b, 1, s, stdout);


could be wrapped in a function, and then this function can be called from within the loop, and instead of using a goto to jump into the middle of the loop, you can just call the function.

Or is that correct? When you jump into the middle of the loop there, you expect the loop to terminate right? IE, the catting code is only run once? I don't think i is necessarily initialized when the comparison, i < argc is made.

Name: Anonymous 2012-02-16 4:22

>>6
Thanks for the catch; I can probably move the initialisation of i to the declaration, and leave the first 'trimester' of the for statement empty, so that i is always initialised. I suppose a function could be used, though in a program as trivial as this, there isn't any benefit that I can see.

Name: Anonymous 2012-02-16 4:25

>>6
Why should C need nested lexical scoping when the function could just be passed the FILE* as an argument? Using scoping captures instead of function arguments introduces the same problems as using global variables.
void writeout(FILE *f) {
    char b[4096];
    size_t s;
    while ((s = fread(b, 1, 4096, f)))
        fwrite(b, 1, s, stdout);
}

Name: Anonymous 2012-02-16 4:35

>>3
Your failure rate is also 100%, since there are infinity possible inputs it fails on.

Name: Anonymous 2012-02-16 4:42

>>9
There are also infinity possible inputs it doesn't fail on.

Name: Anonymous 2012-02-16 6:21

>>10
Pick a real number. What's the probability that it's rational?

Name: Anonymous 2012-02-16 6:43

>>11
what does it mean to "pick a real number"?

Name: Anonymous 2012-02-16 6:46


#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    const char *s = argv[0];

    if (!(s && *s))
        return EXIT_FAILURE;

    while (++s) {
        FILE *f;
        if (!(f = fopen(s, "r")))
            return EXIT_FAILURE;
        {
            int c;
            while ((c = fgetc(f)) != EOF)
                putchar(c);
        }
        fclose(f);
    }

    return EXIT_SUCCESS;
}

untested

Name: Anonymous 2012-02-16 7:54

>>11
What's the mantissa for that number?

Name: Anonymous 2012-02-16 9:42

Name: Anonymous 2012-02-16 16:05

>>10
That's not actually true.

Name: Anonymous 2012-02-16 16:10

#include <stdio.h>
#include <string.h>

int main (int argc, char **argv) {
    int i;
    char files=0, c;
    FILE *f;
    for (i=1; i<argc; i++) {
        if (strcmp(argv[i], "-u")) {
            files=1;
            if(!(f=fopen(argv[i], "r"))) return 1;
            while((c=getc(f)) != EOF) putchar(c);
            fclose(f);
        }
    }
    if (!files) while ((c=getchar()) != EOF) putchar(c);
    return 0;
}

Name: Anonymous 2012-02-16 16:33

>>16
Can you enumerate the possible inputs it doesn't fail on?

Name: Anonymous 2012-02-24 4:33

>>7
The program may be small, but even in small programs code duplication can come up, and factoring the duplicated code in a function and then calling it from each duplication point would be the safest way to factor it. And variable initialization is very explicit in function calls. Using gotos to jump into the middle of loops creates many implicit situations amongst the local variables, and very quickly, the only method for finding out is happening becomes manually tracing through it. When this happens, it means the concept of the program is destroyed, and all that remains is code to compute. The only way to recover the conceptual methods employed in the program is to become the computer and then realize what you are doing.

Name: cat.hs 2012-02-24 5:59

main = do
    args <- getArgs
    map (\x -> readFile x >>= putStr) args


. . . Did someone say elegant?

Name: Anonymous 2012-02-24 6:24

You can always just use redirects ...

#include <stdio.h>

int main(void)
{
        int c;

        while ((c = getchar()) != EOF)
                putchar(c);
        return 0;
}

Name: Anonymous 2012-02-24 6:29

dubs.c
return 'em;

Name: Anonymous 2012-02-24 7:27

>>20
Except that's neither elegant, nor efficient.

Name: Anonymous 2012-02-24 7:34

>>23
It achieves cat function in very little code. I suppose if you wanted to include the error message, it'll be a bit longer. I'm not sure how one could achieve a denser solution than in any other practical language.

Name: Anonymous 2012-02-24 7:43

>>24
Elegant =/= dense.

Name: Anonymous 2012-02-24 8:05

>>21
One function call per byte is [b][i]SLOW AS FUCK[/i][/b]

Name: Anonymous 2012-02-24 8:25

>>26
EXPERT BBCODE PROGRAMMER

Name: Anonymous 2012-02-24 10:58

>>20
haskell
elegant

(Show a, Show b, Show c) => Show (a, b, c)    
(Show a, Show b, Show c, Show d) => Show (a, b, c, d)    
(Show a, Show b, Show c, Show d, Show e) => Show (a, b, c, d, e)    
(Show a, Show b, Show c, Show d, Show e, Show f) => Show (a, b, c, d, e, f)    
(Show a, Show b, Show c, Show d, Show e, Show f, Show g) => Show (a, b, c, d, e, f, g)    
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h) => Show (a, b, c, d, e, f, g, h)    
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i) => Show (a, b, c, d, e, f, g, h, i)    
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j) => Show (a, b, c, d, e, f, g, h, i, j)    
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k) => Show (a, b, c, d, e, f, g, h, i, j, k)    
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l) => Show (a, b, c, d, e, f, g, h, i, j, k, l)    
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m) => Show (a, b, c, d, e, f, g, h, i, j, k, l, m)    
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m, Show n) => Show (a, b, c, d, e, f, g, h, i, j, k, l, m, n)    
(Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m, Show n, Show o) => Show (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)

Name: Anonymous 2012-02-24 11:06

>>28
Yeah, they could've had better semantics for tuples at the type/kind level. Maybe a future version will clean up that rust spot.

Nobody actually uses big tuples anyway, because records are just better even if they're still shit.

Name: Anonymous 2012-02-24 11:11

>>29
You think with all the academics pouting over haskell night and day that it's just some silly implementation problem that can be fixed in a new version? It's a design issue that clashes with the entire foundation of the language -- short of significant theoretical advances it won't ever be fixed.

Name: Anonymous 2012-02-24 11:12

>>29
You have no idea how programming languages work you no talent bitch.

Name: Anonymous 2012-02-24 11:16

>>11
The probability of the number being rational is 0.

Name: Anonymous 2012-02-24 11:18

>>30
No academics care about Haskell, only retarded children do.

Name: Anonymous 2012-02-24 11:37

>>32
And yet it happens...

Name: Anonymous 2012-02-24 12:08

>>34

It doesn't. (Think again.)

Name: Anonymous 2012-02-24 12:25

>>35
As we would say in statistics, the event "number is rational" happens almost never.

Name: Anonymous 2012-02-24 12:44

>>36

Exactly. However, as the problem is framed, one can never hope to expect a rational number being output from such a generator in practice, albeit every number (even rational ones) have the same probability to occur. Despite, the practicality of an experiment of this sort is indeed rather dubious.

Name: Anonymous 2012-02-24 15:25

>>36,37
It never happens, the probability is exactly zero.

This has to do with the cardinality of the rational numbers versus the cardinality of the irrational numbers.

Try doing the (lebesgue) integral of the probability distribution over any real interval that extends over more than a single real number.

Name: Anonymous 2012-02-24 15:30

>>38
the probability is exactly zero.
Read the definition of the term in >>36.  Its probability is zero, but it CAN happen, the same way P(x = sqrt(2)) = 0 but it obviously can occur.

Name: Anonymous 2012-02-24 15:34

This is pathetic.

Name: Anonymous 2012-02-24 15:37

>>38
Probability will be zero for any specific number you choose or any enumerable set - such as computable reals or algebraic numbers and so on. Reals themselves are not enumerable, hence why it's 0. However, that doesn't mean it doesn't "happen" (given the right set theoretic axioms).

Name: Anonymous 2012-02-24 16:11

>>39
No it's exactly zero, it can't happen.
Learn mathematics.

Name: Anonymous 2012-02-24 16:25

>>42
Are you 12?

Educate yourself http://en.wikipedia.org/wiki/Almost_surely

Name: Anonymous 2012-02-24 16:57

>>43
Are you 12?
Yes, and I am writing my first ANSI-C compiler.
No wonder you're jelly.

Name: Anonymous 2012-02-24 17:38

>>44
Good luck with that. You have much to learn, but a great future ahead of yourself.

I'm not jelly, I'm proud.

Name: Anonymous 2012-02-24 17:54

>>28
What the fuck is that supposed to be?

>>24
It does include the error message; readFile throws an exception of the file doesn't exist.

Name: Anonymous 2012-02-24 17:57

>>44,45
C is undefined shit, nothing to be proud of.

Write an x86 assembler instead, one that doesn't complain if you write mov eax, label | 0x3.

Name: Anonymous 2012-02-24 18:13

>>47
The 8008's A register became AX which then became EAX which AMD turned into RAX. The 8008 is a single-chip version of the Datapoint 2200 terminal processor. Intel's own Jew designs are all shit, so they're having better luck extending a 70's 8-bit embedded Goyish terminal chip. It's like if Ford kept adding more and more crap onto the Model T in the year 2012 even though all other car companies are selling modern cars.

Name: Anonymous 2012-02-24 18:24

>>48
You know, Ford still sells its powerful V8 which was designed in the 1960s. Car metaphors are never accurate.

Name: Anonymous 2012-02-24 19:32

>>49
What?!! V8 wasn't designed by Google Inc.?

Name: Anonymous 2012-02-24 21:48

GNU QUALITY


/* cat -- concatenate files and print on the standard output.
   Copyright (C) 1988, 1990-1991, 1995-2011 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>;.  */

/* Differences from the Unix cat:
   * Always unbuffered, -u is ignored.
   * Usually much faster than other versions of cat, the difference
   is especially apparent when using the -v option.

   By tege@sics.se, Torbjorn Granlund, advised by rms, Richard Stallman.  */

#include <config.h>

#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>

#if HAVE_STROPTS_H
# include <stropts.h>
#endif
#include <sys/ioctl.h>

#include "system.h"
#include "error.h"
#include "fadvise.h"
#include "full-write.h"
#include "quote.h"
#include "safe-read.h"
#include "xfreopen.h"

/* The official name of this program (e.g., no `g' prefix).  */
#define PROGRAM_NAME "cat"

#define AUTHORS \
  proper_name_utf8 ("Torbjorn Granlund", "Torbj\303\266rn Granlund"), \
  proper_name ("Richard M. Stallman")

/* Name of input file.  May be "-".  */
static char const *infile;

/* Descriptor on which input file is open.  */
static int input_desc;

/* Buffer for line numbers.
   An 11 digit counter may overflow within an hour on a P2/466,
   an 18 digit counter needs about 1000y */
#define LINE_COUNTER_BUF_LEN 20
static char line_buf[LINE_COUNTER_BUF_LEN] =
  {
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0',
    '\t', '\0'
  };

/* Position in `line_buf' where printing starts.  This will not change
   unless the number of lines is larger than 999999.  */
static char *line_num_print = line_buf + LINE_COUNTER_BUF_LEN - 8;

/* Position of the first digit in `line_buf'.  */
static char *line_num_start = line_buf + LINE_COUNTER_BUF_LEN - 3;

/* Position of the last digit in `line_buf'.  */
static char *line_num_end = line_buf + LINE_COUNTER_BUF_LEN - 3;

/* Preserves the `cat' function's local `newlines' between invocations.  */
static int newlines2 = 0;

void
usage (int status)
{
  if (status != EXIT_SUCCESS)
    fprintf (stderr, _("Try `%s --help' for more information.\n"),
             program_name);
  else
    {
      printf (_("\
Usage: %s [OPTION]... [FILE]...\n\
"),
              program_name);
      fputs (_("\
Concatenate FILE(s), or standard input, to standard output.\n\
\n\
  -A, --show-all           equivalent to -vET\n\
  -b, --number-nonblank    number nonempty output lines, overrides -n\n\
  -e                       equivalent to -vE\n\
  -E, --show-ends          display $ at end of each line\n\
  -n, --number             number all output lines\n\
  -s, --squeeze-blank      suppress repeated empty output lines\n\
"), stdout);
      fputs (_("\
  -t                       equivalent to -vT\n\
  -T, --show-tabs          display TAB characters as ^I\n\
  -u                       (ignored)\n\
  -v, --show-nonprinting   use ^ and M- notation, except for LFD and TAB\n\
"), stdout);
      fputs (HELP_OPTION_DESCRIPTION, stdout);
      fputs (VERSION_OPTION_DESCRIPTION, stdout);
      fputs (_("\
\n\
With no FILE, or when FILE is -, read standard input.\n\
"), stdout);
      printf (_("\
\n\
Examples:\n\
  %s f - g  Output f's contents, then standard input, then g's contents.\n\
  %s        Copy standard input to standard output.\n\
"),
              program_name, program_name);
      emit_ancillary_info ();
    }
  exit (status);
}

/* Compute the next line number.  */

static void
next_line_num (void)
{
  char *endp = line_num_end;
  do
    {
      if ((*endp)++ < '9')
        return;
      *endp-- = '0';
    }
  while (endp >= line_num_start);
  if (line_num_start > line_buf)
    *--line_num_start = '1';
  else
    *line_buf = '>';
  if (line_num_start < line_num_print)
    line_num_print--;
}

/* Plain cat.  Copies the file behind `input_desc' to STDOUT_FILENO.
   Return true if successful.  */

static bool
simple_cat (
     /* Pointer to the buffer, used by reads and writes.  */
     char *buf,

     /* Number of characters preferably read or written by each read and write
        call.  */
     size_t bufsize)
{
  /* Actual number of characters read, and therefore written.  */
  size_t n_read;

  /* Loop until the end of the file.  */

  while (true)
    {
      /* Read a block of input.  */

      n_read = safe_read (input_desc, buf, bufsize);
      if (n_read == SAFE_READ_ERROR)
        {
          error (0, errno, "%s", infile);
          return false;
        }

      /* End of this file?  */

      if (n_read == 0)
        return true;

      /* Write this block out.  */

      {
        /* The following is ok, since we know that 0 < n_read.  */
        size_t n = n_read;
        if (full_write (STDOUT_FILENO, buf, n) != n)
          error (EXIT_FAILURE, errno, _("write error"));
      }
    }
}

/* Write any pending output to STDOUT_FILENO.
   Pending is defined to be the *BPOUT - OUTBUF bytes starting at OUTBUF.
   Then set *BPOUT to OUTPUT if it's not already that value.  */

static inline void
write_pending (char *outbuf, char **bpout)
{
  size_t n_write = *bpout - outbuf;
  if (0 < n_write)
    {
      if (full_write (STDOUT_FILENO, outbuf, n_write) != n_write)
        error (EXIT_FAILURE, errno, _("write error"));
      *bpout = outbuf;
    }
}

/* Cat the file behind INPUT_DESC to the file behind OUTPUT_DESC.
   Return true if successful.
   Called if any option more than -u was specified.

   A newline character is always put at the end of the buffer, to make
   an explicit test for buffer end unnecessary.  */

static bool
cat (
     /* Pointer to the beginning of the input buffer.  */
     char *inbuf,

     /* Number of characters read in each read call.  */
     size_t insize,

     /* Pointer to the beginning of the output buffer.  */
     char *outbuf,

     /* Number of characters written by each write call.  */
     size_t outsize,

     /* Variables that have values according to the specified options.  */
     bool show_nonprinting,
     bool show_tabs,
     bool number,
     bool number_nonblank,
     bool show_ends,
     bool squeeze_blank)
{
  /* Last character read from the input buffer.  */
  unsigned char ch;

  /* Pointer to the next character in the input buffer.  */
  char *bpin;

  /* Pointer to the first non-valid byte in the input buffer, i.e. the
     current end of the buffer.  */
  char *eob;

  /* Pointer to the position where the next character shall be written.  */
  char *bpout;

  /* Number of characters read by the last read call.  */
  size_t n_read;

  /* Determines how many consecutive newlines there have been in the
     input.  0 newlines makes NEWLINES -1, 1 newline makes NEWLINES 1,
     etc.  Initially 0 to indicate that we are at the beginning of a
     new line.  The "state" of the procedure is determined by
     NEWLINES.  */
  int newlines = newlines2;

#ifdef FIONREAD
  /* If nonzero, use the FIONREAD ioctl, as an optimization.
     (On Ultrix, it is not supported on NFS file systems.)  */
  bool use_fionread = true;
#endif

  /* The inbuf pointers are initialized so that BPIN > EOB, and thereby input
     is read immediately.  */

  eob = inbuf;
  bpin = eob + 1;

  bpout = outbuf;

Name: Anonymous 2012-02-24 21:49

>>51

  while (true)
    {
      do
        {
          /* Write if there are at least OUTSIZE bytes in OUTBUF.  */

          if (outbuf + outsize <= bpout)
            {
              char *wp = outbuf;
              size_t remaining_bytes;
              do
                {
                  if (full_write (STDOUT_FILENO, wp, outsize) != outsize)
                    error (EXIT_FAILURE, errno, _("write error"));
                  wp += outsize;
                  remaining_bytes = bpout - wp;
                }
              while (outsize <= remaining_bytes);

              /* Move the remaining bytes to the beginning of the
                 buffer.  */

              memmove (outbuf, wp, remaining_bytes);
              bpout = outbuf + remaining_bytes;
            }

          /* Is INBUF empty?  */

          if (bpin > eob)
            {
              bool input_pending = false;
#ifdef FIONREAD
              int n_to_read = 0;

              /* Is there any input to read immediately?
                 If not, we are about to wait,
                 so write all buffered output before waiting.  */

              if (use_fionread
                  && ioctl (input_desc, FIONREAD, &n_to_read) < 0)
                {
                  /* Ultrix returns EOPNOTSUPP on NFS;
                     HP-UX returns ENOTTY on pipes.
                     SunOS returns EINVAL and
                     More/BSD returns ENODEV on special files
                     like /dev/null.
                     Irix-5 returns ENOSYS on pipes.  */
                  if (errno == EOPNOTSUPP || errno == ENOTTY
                      || errno == EINVAL || errno == ENODEV
                      || errno == ENOSYS)
                    use_fionread = false;
                  else
                    {
                      error (0, errno, _("cannot do ioctl on %s"),
                             quote (infile));
                      newlines2 = newlines;
                      return false;
                    }
                }
              if (n_to_read != 0)
                input_pending = true;
#endif

              if (!input_pending)
                write_pending (outbuf, &bpout);

              /* Read more input into INBUF.  */

              n_read = safe_read (input_desc, inbuf, insize);
              if (n_read == SAFE_READ_ERROR)
                {
                  error (0, errno, "%s", infile);
                  write_pending (outbuf, &bpout);
                  newlines2 = newlines;
                  return false;
                }
              if (n_read == 0)
                {
                  write_pending (outbuf, &bpout);
                  newlines2 = newlines;
                  return true;
                }

              /* Update the pointers and insert a sentinel at the buffer
                 end.  */

              bpin = inbuf;
              eob = bpin + n_read;
              *eob = '\n';
            }
          else
            {
              /* It was a real (not a sentinel) newline.  */

              /* Was the last line empty?
                 (i.e. have two or more consecutive newlines been read?)  */

              if (++newlines > 0)
                {
                  if (newlines >= 2)
                    {
                      /* Limit this to 2 here.  Otherwise, with lots of
                         consecutive newlines, the counter could wrap
                         around at INT_MAX.  */
                      newlines = 2;

                      /* Are multiple adjacent empty lines to be substituted
                         by single ditto (-s), and this was the second empty
                         line?  */
                      if (squeeze_blank)
                        {
                          ch = *bpin++;
                          continue;
                        }
                    }

                  /* Are line numbers to be written at empty lines (-n)?  */

                  if (number && !number_nonblank)
                    {
                      next_line_num ();
                      bpout = stpcpy (bpout, line_num_print);
                    }
                }

              /* Output a currency symbol if requested (-e).  */

              if (show_ends)
                *bpout++ = '$';

              /* Output the newline.  */

              *bpout++ = '\n';
            }
          ch = *bpin++;
        }
      while (ch == '\n');

      /* Are we at the beginning of a line, and line numbers are requested?  */

      if (newlines >= 0 && number)
        {
          next_line_num ();
          bpout = stpcpy (bpout, line_num_print);
        }

      /* Here CH cannot contain a newline character.  */

      /* The loops below continue until a newline character is found,
         which means that the buffer is empty or that a proper newline
         has been found.  */

      /* If quoting, i.e. at least one of -v, -e, or -t specified,
         scan for chars that need conversion.  */
      if (show_nonprinting)
        {
          while (true)
            {
              if (ch >= 32)
                {
                  if (ch < 127)
                    *bpout++ = ch;
                  else if (ch == 127)
                    {
                      *bpout++ = '^';
                      *bpout++ = '?';
                    }
                  else
                    {
                      *bpout++ = 'M';
                      *bpout++ = '-';
                      if (ch >= 128 + 32)
                        {
                          if (ch < 128 + 127)
                            *bpout++ = ch - 128;
                          else
                            {
                              *bpout++ = '^';
                              *bpout++ = '?';
                            }
                        }
                      else
                        {
                          *bpout++ = '^';
                          *bpout++ = ch - 128 + 64;
                        }
                    }
                }
              else if (ch == '\t' && !show_tabs)
                *bpout++ = '\t';
              else if (ch == '\n')
                {
                  newlines = -1;
                  break;
                }
              else
                {
                  *bpout++ = '^';
                  *bpout++ = ch + 64;
                }

              ch = *bpin++;
            }
        }

Name: Anonymous 2012-02-24 21:49

>>52

      else
        {
          /* Not quoting, neither of -v, -e, or -t specified.  */
          while (true)
            {
              if (ch == '\t' && show_tabs)
                {
                  *bpout++ = '^';
                  *bpout++ = ch + 64;
                }
              else if (ch != '\n')
                *bpout++ = ch;
              else
                {
                  newlines = -1;
                  break;
                }

              ch = *bpin++;
            }
        }
    }
}

int
main (int argc, char **argv)
{
  /* Optimal size of i/o operations of output.  */
  size_t outsize;

  /* Optimal size of i/o operations of input.  */
  size_t insize;

  size_t page_size = getpagesize ();

  /* Pointer to the input buffer.  */
  char *inbuf;

  /* Pointer to the output buffer.  */
  char *outbuf;

  bool ok = true;
  int c;

  /* Index in argv to processed argument.  */
  int argind;

  /* Device number of the output (file or whatever).  */
  dev_t out_dev;

  /* I-node number of the output.  */
  ino_t out_ino;

  /* True if the output file should not be the same as any input file.  */
  bool check_redirection = true;

  /* Nonzero if we have ever read standard input.  */
  bool have_read_stdin = false;

  struct stat stat_buf;

  /* Variables that are set according to the specified options.  */
  bool number = false;
  bool number_nonblank = false;
  bool squeeze_blank = false;
  bool show_ends = false;
  bool show_nonprinting = false;
  bool show_tabs = false;
  int file_open_mode = O_RDONLY;

  static struct option const long_options[] =
  {
    {"number-nonblank", no_argument, NULL, 'b'},
    {"number", no_argument, NULL, 'n'},
    {"squeeze-blank", no_argument, NULL, 's'},
    {"show-nonprinting", no_argument, NULL, 'v'},
    {"show-ends", no_argument, NULL, 'E'},
    {"show-tabs", no_argument, NULL, 'T'},
    {"show-all", no_argument, NULL, 'A'},
    {GETOPT_HELP_OPTION_DECL},
    {GETOPT_VERSION_OPTION_DECL},
    {NULL, 0, NULL, 0}
  };

  initialize_main (&argc, &argv);
  set_program_name (argv[0]);
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  /* Arrange to close stdout if we exit via the
     case_GETOPT_HELP_CHAR or case_GETOPT_VERSION_CHAR code.
     Normally STDOUT_FILENO is used rather than stdout, so
     close_stdout does nothing.  */
  atexit (close_stdout);

  /* Parse command line options.  */

  while ((c = getopt_long (argc, argv, "benstuvAET", long_options, NULL))
         != -1)
    {
      switch (c)
        {
        case 'b':
          number = true;
          number_nonblank = true;
          break;

        case 'e':
          show_ends = true;
          show_nonprinting = true;
          break;

        case 'n':
          number = true;
          break;

        case 's':
          squeeze_blank = true;
          break;

        case 't':
          show_tabs = true;
          show_nonprinting = true;
          break;

        case 'u':
          /* We provide the -u feature unconditionally.  */
          break;

        case 'v':
          show_nonprinting = true;
          break;

        case 'A':
          show_nonprinting = true;
          show_ends = true;
          show_tabs = true;
          break;

        case 'E':
          show_ends = true;
          break;

        case 'T':
          show_tabs = true;
          break;

        case_GETOPT_HELP_CHAR;

        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);

        default:
          usage (EXIT_FAILURE);
        }
    }

  /* Get device, i-node number, and optimal blocksize of output.  */

  if (fstat (STDOUT_FILENO, &stat_buf) < 0)
    error (EXIT_FAILURE, errno, _("standard output"));

  outsize = io_blksize (stat_buf);
  /* Input file can be output file for non-regular files.
     fstat on pipes returns S_IFSOCK on some systems, S_IFIFO
     on others, so the checking should not be done for those types,
     and to allow things like cat < /dev/tty > /dev/tty, checking
     is not done for device files either.  */

  if (S_ISREG (stat_buf.st_mode))
    {
      out_dev = stat_buf.st_dev;
      out_ino = stat_buf.st_ino;
    }
  else
    {
      check_redirection = false;
#ifdef lint  /* Suppress `used before initialized' warning.  */
      out_dev = 0;
      out_ino = 0;
#endif
    }

  if (! (number || show_ends || squeeze_blank))
    {
      file_open_mode |= O_BINARY;
      if (O_BINARY && ! isatty (STDOUT_FILENO))
        xfreopen (NULL, "wb", stdout);
    }

  /* Check if any of the input files are the same as the output file.  */

  /* Main loop.  */

  infile = "-";
  argind = optind;

  do
    {
      if (argind < argc)
        infile = argv[argind];

      if (STREQ (infile, "-"))
        {
          have_read_stdin = true;
          input_desc = STDIN_FILENO;
          if ((file_open_mode & O_BINARY) && ! isatty (STDIN_FILENO))
            xfreopen (NULL, "rb", stdin);
        }
      else
        {
          input_desc = open (infile, file_open_mode);
          if (input_desc < 0)
            {
              error (0, errno, "%s", infile);
              ok = false;
              continue;
            }
        }

      if (fstat (input_desc, &stat_buf) < 0)
        {
          error (0, errno, "%s", infile);
          ok = false;
          goto contin;
        }
      insize = io_blksize (stat_buf);

      fdadvise (input_desc, 0, 0, FADVISE_SEQUENTIAL);

      /* Compare the device and i-node numbers of this input file with
         the corresponding values of the (output file associated with)
         stdout, and skip this input file if they coincide.  Input
         files cannot be redirected to themselves.  */

      if (check_redirection
          && stat_buf.st_dev == out_dev && stat_buf.st_ino == out_ino
          && (input_desc != STDIN_FILENO))
        {
          error (0, 0, _("%s: input file is output file"), infile);
          ok = false;
          goto contin;
        }

      /* Select which version of `cat' to use.  If any format-oriented
         options were given use `cat'; otherwise use `simple_cat'.  */

      if (! (number || show_ends || show_nonprinting
             || show_tabs || squeeze_blank))
        {
          insize = MAX (insize, outsize);
          inbuf = xmalloc (insize + page_size - 1);

          ok &= simple_cat (ptr_align (inbuf, page_size), insize);
        }
      else
        {
          inbuf = xmalloc (insize + 1 + page_size - 1);

          /* Why are
             (OUTSIZE - 1 + INSIZE * 4 + LINE_COUNTER_BUF_LEN + PAGE_SIZE - 1)
             bytes allocated for the output buffer?

             A test whether output needs to be written is done when the input
             buffer empties or when a newline appears in the input.  After
             output is written, at most (OUTSIZE - 1) bytes will remain in the
             buffer.  Now INSIZE bytes of input is read.  Each input character
             may grow by a factor of 4 (by the prepending of M-^).  If all
             characters do, and no newlines appear in this block of input, we
             will have at most (OUTSIZE - 1 + INSIZE * 4) bytes in the buffer.
             If the last character in the preceding block of input was a
             newline, a line number may be written (according to the given
             options) as the first thing in the output buffer. (Done after the
             new input is read, but before processing of the input begins.)
             A line number requires seldom more than LINE_COUNTER_BUF_LEN
             positions.

             Align the output buffer to a page size boundary, for efficency on
             some paging implementations, so add PAGE_SIZE - 1 bytes to the
             request to make room for the alignment.  */

          outbuf = xmalloc (outsize - 1 + insize * 4 + LINE_COUNTER_BUF_LEN
                            + page_size - 1);

          ok &= cat (ptr_align (inbuf, page_size), insize,
                     ptr_align (outbuf, page_size), outsize, show_nonprinting,
                     show_tabs, number, number_nonblank, show_ends,
                     squeeze_blank);

          free (outbuf);
        }

      free (inbuf);

    contin:
      if (!STREQ (infile, "-") && close (input_desc) < 0)
        {
          error (0, errno, "%s", infile);
          ok = false;
        }
    }
  while (++argind < argc);

  if (have_read_stdin && close (STDIN_FILENO) < 0)
    error (EXIT_FAILURE, errno, _("closing standard input"));

  exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}

Name: Anonymous 2012-02-24 21:57

PLAN 9 :3


#include <u.h>
#include <libc.h>

void
cat(int f, char *s)
{
    char buf[8192];
    long n;

    while((n=read(f, buf, (long)sizeof buf))>0)
        if(write(1, buf, n)!=n)
            sysfatal("write error copying %s: %r", s);
    if(n < 0)
        sysfatal("error reading %s: %r", s);
}

void
main(int argc, char *argv[])
{
    int f, i;

    argv0 = "cat";
    if(argc == 1)
        cat(0, "<stdin>");
    else for(i=1; i<argc; i++){
        f = open(argv[i], OREAD);
        if(f < 0)
            sysfatal("can't open %s: %r", argv[i]);
        else{
            cat(f, argv[i]);
            close(f);
        }
    }
    exits(0);
}

Name: Cudder !MhMRSATORI!FBeUS42x4uM+kgp 2012-02-25 4:25

/* @cat.c */
/* NOTE: GNU's cat will not cat a file into itself. Should we check for this?
   Possibility of infinite loop here. POSIX doesn't specify what happens if
   standard input happens to be standard output (cat to temp. file and then
   write that to the output? don't write what was already written?) */
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define CATBUF_SIZE 65536 /* increase this if you want OMG MOAR SPEED! */

char catbuf[CATBUF_SIZE];

int main(int argc, char** argv) {
 int uflag = 0, retval = 0, i = 1, c;
 FILE *input;

 while((c=getopt(argc,argv,"u"))!=-1)
  if(c=='u') {
   uflag=1;
   retval=setvbuf(stdout,NULL,_IONBF,0);
  } else {
   fprintf(stderr,"usage: %s [-u] file...\n",argv[0]);
   return 1;
  }
 if(optind>=argc) { /* catting stdin */
  input=stdin;
  goto cat_stdin;
 }
 i=optind;
 while(argv[i]) {
  int l;
  if(strcmp(argv[i],"-")) {
   if(!(input=fopen(argv[i++],"rb"))) {
    fprintf(stderr,"%s: could not open %s: %s\n",argv[0],argv[i-1],strerror(errno));
    retval=1;
    continue;
   }
  } else {
   input=stdin;
   i++;
  }
 cat_stdin:
  if(uflag)
   retval|=setvbuf(input, NULL, _IONBF, 0);

  while(l=fread(catbuf,1,CATBUF_SIZE,input)) {
   if(fwrite(catbuf,1,l,stdout)!=l) {
    fprintf(stderr,"%s: error writing to stdout: %s\n",argv[0],strerror(errno));
    retval=1;
    break;
   }
  }
  if(ferror(input))
   fprintf(stderr,"%s: error reading %s: %s\n",argv[0],argv[i-1],strerror(errno));
  if(input!=stdin)
   retval|=fclose(input);
 }
 return retval;
}


meow.

Name: Anonymous 2012-02-25 7:24

,[.,]

Name: Anonymous 2012-02-25 12:56

>>20
That doesn't even work, faggot.

main = getArgs >>= mapM_ ((>>= putStr) . readFile)

Name: Anonymous 2012-02-25 15:17

lolol is ur cat ded

Don't change these.
Name: Email:
Entire Thread Thread List