Logo Search packages:      
Sourcecode: ksh version File versions  Download package

paste.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*                  Copyright (c) 1992-2005 AT&T Corp.                  *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                            by AT&T Corp.                             *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                  David Korn <dgk@research.att.com>                   *
*                                                                      *
***********************************************************************/
#pragma prototyped
/*
 * David Korn
 * AT&T Bell Laboratories
 *
 * paste [-s] [-d delim] [file] ...
 *
 * paste lines from files together
 */

static const char usage[] =
"[-?\n@(#)$Id: paste (AT&T Labs Research) 1999-06-22 $\n]"
USAGE_LICENSE
"[+NAME?paste - merge lines of files]"
"[+DESCRIPTION?\bpaste\b concatenates the corresponding lines of a "
      "given input file and writes the resulting lines to standard "
      "output.  By default \bpaste\b replaces the newline character of "
      "every line other than the last input file with the TAB character.]"
"[+?Unless the \b-s\b option is specified, if an end-of-file is encountered "
      "on one or more input files, but not all input files, \bpaste\b "
      "behaves as if empty lines were read from the file(s) on which "
      "end-of-file was detected.]"
"[+?Unless the \b-s\b option is specified, \bpaste\b is limited by "
      "the underlying operating system on how many \afile\a operands "
      "can be specified.]"
"[+?If no \afile\a operands are given or if the \afile\a is \b-\b, \bpaste\b "
      "reads from standard input. The start of the file is defined as the "
      "current offset.]"

"[s:serial?Paste the lines of one file at a time rather than one line "
      "from each file.  In this case if the \b-d\b option is "
      "specified the delimiter will be reset to the first in the "
      "list at the beginning of each file.]"
"[d:delimiters]:[list?\alist\a specifies a list of delimiters.  These "
      "delimiters are used circularly instead of TAB to replace "
      "the newline character of the input lines. Unless the \b-s\b "
      "option is specified, the delimiter will be reset to the first "
      "element of \alist\a each time a line is processed from each file.  "
      "The delimiter characters corresponding to \alist\a will be found "
      "by treating \alist\a as an ANSI-C string, except that the \b\\0\b "
      "sequence will insert the empty string instead of the null character.]"
"\n"
"\n[file ...]\n"
"\n"
"[+EXIT STATUS?]{"
      "[+0?All files processed successfully.]"
      "[+>0?An error occurred.]"
"}"
"[+SEE ALSO?\bcut\b(1), \bcat\b(1), \bjoin\b(1)]"
;


#include <cmdlib.h>

/*
 * paste the lines of the <nstreams> defined in <streams> and put results
 * to <out>
 */

static int paste(int nstream,Sfio_t* streams[],Sfio_t *out, register const char *delim,int dlen)
{
      register const char *cp;
      register int d, n, more=1;
      register Sfio_t *fp;
      do
      {
            d = (dlen>0?0:-1);
            for(n=more-1,more=0; n < nstream;)
            {
                  if(fp=streams[n])
                  {
                        if(cp = sfgetr(fp,'\n',0))
                        {
                              if(n==0)
                                    more = 1;
                              else if(!more) /* first stream with output */
                              {
                                    if(dlen==1)
                                          sfnputc(out, *delim, n);
                                    else if(dlen>0)
                                    {
                                          for(d=n; d>dlen; d-=dlen)
                                                sfwrite(out,delim,dlen);
                                          if(d)
                                                sfwrite(out,delim,d);
                                    }
                                    more = n+1;
                              }
                              if(sfwrite(out,cp,sfvalue(fp)-((n+1)<nstream)) < 0)
                                    return(-1);
                        }
                        else
                              streams[n] = 0;
                  }
                  if(++n<nstream && more && d>=0)
                  {
                        register int c;
                        if(d >= dlen)
                              d = 0;
                        if(c=delim[d++])
                              sfputc(out,c);
                  }
                  else if(n==nstream && !streams[n-1] && more)
                        sfputc(out,'\n');
            }
      }
      while(more);
      return(0);
}

/*
 * Handles paste -s, for file <in> to file <out> using delimiters <delim>
 */
static int spaste(Sfio_t *in,register Sfio_t* out,register const char *delim,int dlen)
{
      register const char *cp;
      register int d=0;
      if(cp = sfgetr(in,'\n',0))
      {
            if(sfwrite(out,cp,sfvalue(in)-1) < 0)
                  return(-1);
      }
      while(cp=sfgetr(in, '\n',0)) 
      {
            if(dlen)
            {
                  register int c;
                  if(d >= dlen)
                        d = 0;
                  if(c=delim[d++])
                        sfputc(out,c);
            }
            if(sfwrite(out,cp,sfvalue(in)-1) < 0)
                  return(-1);
      }
      sfputc(out,'\n');
      return(0);
}

int
b_paste(int argc,register char *argv[], void* context)
{
      register int            n, sflag=0;
      register Sfio_t   *fp, **streams;
      register char           *cp, *delim;
      int               dlen;

      static char       defdelim[] = "\t";

      cmdinit(argv, context, ERROR_CATALOG, 0);
      delim = defdelim;
      while (n = optget(argv, usage)) switch (n)
      {
          case 'd':
            delim = opt_info.arg;
            break;
          case 's':
            sflag++;
            break;
          case ':':
            error(2, "%s", opt_info.arg);
            break;
          case '?':
            error(ERROR_usage(2), "%s", opt_info.arg);
            break;
      }
      argv += opt_info.index;
      if(error_info.errors)
            error(ERROR_usage(2),"%s", optusage(NiL));
      dlen = stresc(delim);
      if(cp = *argv)
      {
            n = argc - opt_info.index;
            argv++;
      }
      else
            n = 1;
      if(!sflag)
      {
            if (!(streams = (Sfio_t**)stakalloc(n*sizeof(Sfio_t*))))
                  error(ERROR_exit(1), "out of space");
            n = 0;
      }
      do
      {
            if(!cp || streq(cp,"-"))
                  fp = sfstdin;
            else if(!(fp = sfopen(NiL,cp,"r")))
            {
                  error(ERROR_system(0),"%s: cannot open",cp);
                  error_info.errors = 1;
            }
            if(fp && sflag)
            {
                  if(spaste(fp,sfstdout,delim,dlen) < 0)
                  {
                        error(ERROR_system(0),"write failed");
                        error_info.errors = 1;
                  }
                  if(fp!=sfstdin)
                        sfclose(fp);
            }
            else
                  streams[n++] = fp;
      }
      while(cp= *argv++);
      if(!sflag)
      {
            if(error_info.errors==0 && paste(n,streams,sfstdout,delim,dlen) < 0)
            {
                  error(ERROR_system(0),"write failed");
                  error_info.errors = 1;
            }
            while(--n>=0)
            {
                  if((fp=streams[n]) && fp!=sfstdin)
                        sfclose(fp);
            }
      }
      return(error_info.errors);
}


Generated by  Doxygen 1.6.0   Back to index