"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/paste/paste.c" (20 Aug 2021, 6833 Bytes) of package /linux/privat/schily-2021-09-18.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "paste.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes reports: 2021-08-14_vs_2021-09-18 or 2021-07-29_vs_2021-09-18.

    1 /* @(#)paste.c  1.22 21/08/20 Copyright 1985-2021 J. Schilling */
    2 #include <schily/mconfig.h>
    3 #ifndef lint
    4 static  const char sccsid[] =
    5     "@(#)paste.c    1.22 21/08/20 Copyright 1985-2021 J. Schilling";
    6 #endif
    7 /*
    8  *  Paste some files together
    9  *
   10  *  Copyright (c) 1985-2021 J. Schilling
   11  */
   12 /*
   13  * The contents of this file are subject to the terms of the
   14  * Common Development and Distribution License, Version 1.0 only
   15  * (the "License").  You may not use this file except in compliance
   16  * with the License.
   17  *
   18  * See the file CDDL.Schily.txt in this distribution for details.
   19  * A copy of the CDDL is also available via the Internet at
   20  * http://www.opensource.org/licenses/cddl1.txt
   21  *
   22  * When distributing Covered Code, include this CDDL HEADER in each
   23  * file and include the License file CDDL.Schily.txt from this distribution.
   24  */
   25 
   26 #include <schily/mconfig.h>
   27 #include <schily/stdio.h>
   28 #include <schily/stdlib.h>
   29 #include <schily/unistd.h>  /* For sys/types.h to make off_t available */
   30 #include <schily/standard.h>
   31 #define GT_COMERR       /* #define comerr gtcomerr */
   32 #define GT_ERROR        /* #define error gterror   */
   33 #include <schily/schily.h>
   34 #include <schily/nlsdefs.h>
   35 
   36 #define MIN_LINELEN 4096        /* Min line size  */
   37 #define INCR_LINELEN    4096        /* Increment for line size */
   38 #define MAX_FILES   (256-3)     /* Max # of files */
   39 
   40 LOCAL   BOOL    eofp[MAX_FILES];    /* Files that did hit EOF */
   41 LOCAL   FILE    *filep[MAX_FILES] = {0}; /* Files to work on */
   42 LOCAL   char    *delim;
   43 LOCAL   int delimlen;
   44 LOCAL   int empty;
   45 
   46 LOCAL   char    *line;          /* Output line */
   47 LOCAL   size_t  linelen = MIN_LINELEN;
   48 LOCAL   int linesize = -1;
   49 
   50 LOCAL   void    usage   __PR((int exitcode));
   51 EXPORT  int main    __PR((int ac, char ** av));
   52 LOCAL   void    paste   __PR((int n));
   53 LOCAL   void    spaste  __PR((FILE *f));
   54 LOCAL   int parsedelim __PR((char *d));
   55 
   56 LOCAL void
   57 usage(exitcode)
   58     int exitcode;
   59 {
   60     error("Usage:   paste [options] file1...filen\n");
   61     error("Options:\n");
   62     error("\td=list\t\tuse 'list' as delimiter instead of 'tab'.\n");
   63     error("\t-e\t\tdo not output empty lines.\n");
   64     error("\t-s\t\tpaste lines of one file instead of one line per file.\n");
   65     error("\twidth=#,w=#\tmaximum output linewidth (default infinite).\n");
   66     error("\t-help\t\tPrint this help.\n");
   67     error("\t-version\tPrint version information and exit.\n");
   68     exit(exitcode);
   69 }
   70 
   71 EXPORT int
   72 main(ac, av)
   73     int ac;
   74     char    *av[];
   75 {
   76     int i = 0;          /* Count # of input files */
   77 
   78     char    *options = "help,version,d*,e,s,width#,w#";
   79     int help    = 0;
   80     int prvers  = 0;
   81     int ser = 0;
   82     int cac;
   83     char    * const *cav;
   84 
   85     save_args(ac, av);
   86 
   87     (void) setlocale(LC_ALL, "");
   88 
   89 #ifdef  USE_NLS
   90 #if !defined(TEXT_DOMAIN)   /* Should be defined by cc -D */
   91 #define TEXT_DOMAIN "paste" /* Use this only if it weren't */
   92 #endif
   93     { char  *dir;
   94     dir = searchfileinpath("share/locale", F_OK,
   95                     SIP_ANY_FILE|SIP_NO_PATH, NULL);
   96     if (dir)
   97         (void) bindtextdomain(TEXT_DOMAIN, dir);
   98     else
   99 #if defined(PROTOTYPES) && defined(INS_BASE)
  100     (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
  101 #else
  102     (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
  103 #endif
  104     (void) textdomain(TEXT_DOMAIN);
  105     }
  106 #endif  /* USE_NLS */
  107 
  108     cac = --ac;
  109     cav = ++av;
  110 
  111     if (getallargs(&cac, &cav, options, &help, &prvers,
  112                     &delim, &empty, &ser,
  113                     &linesize, &linesize) < 0) {
  114         errmsgno(EX_BAD, "Bad flag: %s.\n", cav[0]);
  115         usage(EX_BAD);
  116     }
  117     if (help)
  118         usage(0);
  119 
  120     if (prvers) {
  121         /* CSTYLED */
  122         gtprintf("Paste release %s (%s-%s-%s) Copyright (C) 1985-2021 %s\n",
  123                 "1.22",
  124                 HOST_CPU, HOST_VENDOR, HOST_OS,
  125                 _("Jörg Schilling"));
  126         exit(0);
  127     }
  128 
  129     if (delim) {
  130         delimlen = parsedelim(delim);
  131         if (delimlen == 0)
  132             comerrno(EX_BAD, "No delimiter.\n");
  133     } else {
  134         delim = "\t";
  135         delimlen = 1;
  136     }
  137     cac = ac;
  138     cav = av;
  139     for (; getfiles(&cac, &cav, options); cac--, cav++) {
  140         if (i >= MAX_FILES)
  141             comerrno(EX_BAD, "Cannot paste more than %d files.\n",
  142                 MAX_FILES);
  143         if (streql(*cav, "-"))
  144             filep[i++] = stdin;
  145         else if ((filep[i++] = fileopen(*cav, "r")) == (FILE *)NULL)
  146             comerr("Cannot open '%s'.\n", *cav);
  147         if (ser)
  148             spaste(filep[i-1]);
  149     }
  150 
  151     if (i == 0) {
  152         errmsgno(EX_BAD, "No files given.\n");
  153         usage(EX_BAD);
  154     }
  155     if (ser)
  156         return (0);
  157 
  158     if (linesize > 0)
  159         linelen = linesize;
  160     if ((line = malloc(linelen+2)) == NULL)
  161         comerr("Cannot malloc space for line.\n");
  162 
  163     paste(i);
  164     return (0);
  165 }
  166 
  167 LOCAL void
  168 paste(n)
  169     int n;      /* # of files to read from */
  170 {
  171     int k;
  172     register char   *lp;    /* pointer to line */
  173     register char   *ep;    /* pointer to end of line */
  174     register int    c;
  175     register FILE   *fp;
  176     register int    i;
  177 
  178     for (i = 0; i < n; i++)
  179         eofp[i] = FALSE;
  180     ep = &line[linelen];
  181 
  182     for (k = 0; k < n; ) {  /* Stop when all files hit EOF */
  183         lp = line;
  184         for (i = 0; i < n; i++) {
  185             if (!eofp[i]) {     /* No EOF on this file yet? */
  186                 fp = filep[i];
  187             again:
  188                 while ((c = getc(fp)) != EOF &&
  189                     c != '\n' && lp < ep)
  190                     *lp++ = c;
  191 
  192                 if (lp >= ep) {
  193                     char    *new = NULL;
  194                     static  BOOL didwarn = FALSE;
  195 
  196                     if (linesize < 0) {
  197                         /*
  198                          * Use dynamic line length,
  199                          */
  200                         linelen += INCR_LINELEN;
  201                         new = realloc(line,
  202                             linelen+2 + INCR_LINELEN);
  203                     } else {
  204                         didwarn = TRUE;
  205                     }
  206                     if (new == NULL) {
  207                         if (!didwarn)
  208                             errmsg(
  209                     "Cannot realloc space for line.\n");
  210                         didwarn = TRUE;
  211                     } else {
  212                         linelen += INCR_LINELEN;
  213                         lp += new - line;
  214                         ep = &new[linelen];
  215                         line = new;
  216                         goto again;
  217                     }
  218                     while ((c = getc(fp)) != EOF &&
  219                         c != '\n')
  220                         ;
  221                 }
  222             } else {        /* Avoid EOFing twice   */
  223                 c = '\n';   /* so pretend eol.  */
  224             }
  225 
  226             if (c == EOF) {
  227                 eofp[i] = EOF;
  228                 k++;        /* One file less */
  229             }
  230 
  231             if (i == (n-1)) {   /* Last file in line? */
  232                 *lp++ = '\n';
  233                 *lp   = '\0';
  234                 break;      /* Quit loop to print line */
  235             } else {        /* Add field delimiter */
  236                 c = delim[i%delimlen];
  237                 if (c)
  238                     *lp++ = c;
  239             }
  240         }
  241 
  242         /*
  243          * Print only if at least one file did have a line (k <  n).
  244          * With -e, print only lines that have more than delimiters.
  245          */
  246         if (lp-line > n || (!empty && k < n))
  247             filewrite(stdout, line, lp-line);
  248     }
  249 }
  250 
  251 LOCAL void
  252 spaste(f)
  253     FILE    *f;
  254 {
  255     register int    len;
  256     register int    i;
  257     register int    c;
  258 
  259     if ((len = fgetaline(f, &line, &linelen)) > 0) {
  260         for (i = 0; ; i++) {
  261             if (line[len-1] == '\n')
  262                 len--;
  263             filewrite(stdout, line, len);
  264             if ((len = fgetaline(f, &line, &linelen)) <= 0)
  265                 break;
  266             c = delim[i%delimlen];
  267             if (c)
  268                 putchar(c);
  269         }
  270     }
  271     putchar('\n');
  272     fclose(f);
  273 }
  274 
  275 LOCAL int
  276 parsedelim(d)
  277     char    *d;
  278 {
  279     int len = 0;
  280     int c;
  281 static  char    del[MAX_FILES];
  282 
  283     while (*d) {
  284         if ((c = *d++) != '\\') {
  285             del[len++] = c;
  286         } else {
  287             switch (c = *d++) {
  288 
  289             case '0':
  290                 c = 0;
  291                 break;
  292             case 't':
  293                 c = '\t';
  294                 break;
  295             case 'n':
  296                 c = '\n';
  297                 break;
  298             }
  299             del[len++] = c;
  300         }
  301         if (len >= MAX_FILES)
  302             break;
  303     }
  304     delim = del;
  305     return (len);
  306 }