cut.c revision da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Copyright (c) 1992-2007 AT&T Knowledge Ventures *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* by AT&T Knowledge Ventures *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Bell Laboratories
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * cut [-sN] [-f flist] [-c clist] [-d delim] [-D delim] [-r reclen] [file] ...
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * cut fields or columns from fields from a file
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[-?\n@(#)$Id: cut (AT&T Research) 2007-01-23 $\n]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinUSAGE_LICENSE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+NAME?cut - cut out selected columns or fields of each line of a file]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+DESCRIPTION?\bcut\b bytes, characters, or character-delimited fields "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "from one or more files, contatenating them on standard output.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+?The option argument \alist\a is a comma-separated or blank-separated "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "list of positive numbers and ranges. Ranges can be of three "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "forms. The first is two positive integers separated by a hyphen "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "(\alow\a\b-\b\ahigh\a), which represents all fields from \alow\a to "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "\ahigh\a. The second is a positive number preceded by a hyphen "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "(\b-\b\ahigh\a), which represents all fields from field \b1\b to "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "\ahigh\a. The last is a positive number followed by a hyphen "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "(\alow\a\b-\b), which represents all fields from \alow\a to the "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "last field, inclusive. Elements in the \alist\a can be repeated, "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "can overlap, and can appear in any order. The order of the "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "output is that of the input.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+?One and only one of \b-b\b, \b-c\b, or \b-f\b must be specified.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bcut\b "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "cuts from standard input. The start of the file is defined "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "as the current offset.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[b:bytes]:[list?\bcut\b based on a list of bytes.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[c:characters]:[list?\bcut\b based on a list of characters.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[d:delimiter]:[delim?The field character for the \b-f\b option is set "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "to \adelim\a. The default is the \btab\b character.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[f:fields]:[list?\bcut\b based on fields separated by the delimiter "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "character specified with the \b-d\b optiion.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[n:nosplit?Do not split characters. Currently ignored.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[R|r:reclen]#[reclen?If \areclen\a > 0, the input will be read as fixed length "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "records of length \areclen\a when used with the \b-b\b or \b-c\b "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "option.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[s:suppress|only-delimited?Suppress lines with no delimiter characters, "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "when used with the \b-f\b option. By default, lines with no "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "delimiters will be passsed in untouched.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[D:line-delimeter|output-delimiter]:[ldelim?The line delimiter character for "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "the \b-f\b option is set to \aldelim\a. The default is the "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "\bnewline\b character.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[N:nonewline?Do not output new-lines at end of each record when used "
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "with the \b-b\b or \b-c\b option.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n[file ...]\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+EXIT STATUS?]{"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "[+0?All files processed successfully.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "[+>0?One or more files failed to open or could not be read.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"}"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+SEE ALSO?\bpaste\b(1), \bgrep\b(1)]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <cmd.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ctype.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct Last_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int seqno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int seq;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int wdelim;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int ldelim;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Last_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct Cut_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int cflag;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int sflag;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int nlflag;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int wdelim;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int ldelim;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int seqno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int reclen;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signed char space[UCHAR_MAX];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Last_t last;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int list[2]; /* NOTE: must be last member */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Cut_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define HUGE (1<<14)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BLOCK 8*1024
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define C_BYTES 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define C_CHARS 2
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define C_FIELDS 4
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define C_SUPRESS 8
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define C_NOCHOP 16
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define C_NONEWLINE 32
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * compare the first of an array of integers
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int mycomp(register const void *a,register const void *b)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(*((int*)a) - *((int*)b));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic Cut_t *cutinit(int mode,char *str,int wdelim,int ldelim,size_t reclen)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int *lp, c, n=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int range = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp = str;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Cut_t *cuthdr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(cuthdr = (Cut_t*)stakalloc(sizeof(Cut_t)+strlen(cp)*sizeof(int))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1), "out of space");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memset(cuthdr->space, 0, sizeof(cuthdr->space));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->last.seqno = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->last.seq = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->last.wdelim = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->last.ldelim = '\n';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->cflag = ((mode&C_CHARS)!=0 && mbwide());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->sflag = ((mode&C_SUPRESS)!=0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->nlflag = ((mode&C_NONEWLINE)!=0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->wdelim = wdelim;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->ldelim = ldelim;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->reclen = reclen;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->seqno = ++cuthdr->last.seqno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lp = cuthdr->list;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(1) switch(c= *cp++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ' ':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\t':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(*cp==' ' || *cp=='\t')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ',':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(range)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin --range;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((n = (n==0?HUGE:n-range)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1),"invalid range for c/f option");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *lp++ = range;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *lp++ = n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *lp++ = --n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *lp++ = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int *dp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *lp = HUGE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 1 + (lp-cuthdr->list)/2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin qsort(lp=cuthdr->list,n,2*sizeof(*lp),mycomp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* eliminate overlapping regions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(n=0,range= -2,dp=lp; *lp!=HUGE; lp+=2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(lp[0] <= range)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(lp[1]==HUGE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dp[-1] = HUGE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((c = lp[0]+lp[1]-range)>0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin range += c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dp[-1] += c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin range = *dp++ = lp[0];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(lp[1]==HUGE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *dp++ = HUGE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin range += (*dp++ = lp[1]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *dp = HUGE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lp = cuthdr->list;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* convert ranges into gaps */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(n=0; *lp!=HUGE; lp+=2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = *lp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *lp -= n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = c+lp[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(cuthdr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = range = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '-':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(range)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1),"bad list for c/f option");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin range = n?n:1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!isdigit(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_exit(1),"bad list for c/f option");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 10*n + (c-'0');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* NOTREACHED */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * advance <cp> by <n> multi-byte characters
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int advance(const char *str, register int n, register int inlen)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int size, len=inlen;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const char *cp=str;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(len>0 && n-->0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = mblen(cp, len);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp += size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin len -= size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n>0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(inlen+1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(cp-str);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * cut each line of file <fdin> and put results to <fdout> using list <list>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int cutcols(Cut_t *cuthdr,Sfio_t *fdin,Sfio_t *fdout)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c, ncol=0,len;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const int *lp = cuthdr->list;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *inp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int skip; /* non-zero for don't copy */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(len = cuthdr->reclen)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin inp = sfreserve(fdin, len, -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin inp = sfgetr(fdin, '\n', 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!inp && !(inp = sfgetr(fdin, 0, SF_LASTR)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin len = sfvalue(fdin);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((ncol = skip = *(lp = cuthdr->list)) == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ncol = *++lp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((c=(cuthdr->cflag?advance(inp,ncol,len):ncol)) > len)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = len;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c==len && !skip)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ncol++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ncol -= c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!skip && sfwrite(fdout,(char*)inp,c)<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin inp += c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(ncol)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin len -= c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ncol = *++lp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin skip = !skip;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cuthdr->nlflag && (skip || cuthdr->reclen))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(fdout,cuthdr->ldelim);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * cut each line of file <fdin> and put results to <fdout> using list <list>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * stream <fdin> must be line buffered
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define endline(c) (((signed char)-1)<0?(c)<0:(c)==((char)-1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int cutfields(Cut_t *cuthdr,Sfio_t *fdin,Sfio_t *fdout)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c, nfields;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const int *lp = cuthdr->list;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char *copy;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int nodelim, empty, inword=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char *endbuff;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char *inbuff, *first;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int lastchar;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t *fdtmp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long offset = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(cuthdr->seqno != cuthdr->last.seq)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->space[cuthdr->last.ldelim] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->space[cuthdr->last.wdelim] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->space[cuthdr->last.wdelim=cuthdr->wdelim] = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->space[cuthdr->last.ldelim=cuthdr->ldelim] = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr->last.seq = cuthdr->seqno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* process each buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while ((inbuff = (unsigned char*)sfreserve(fdin, SF_UNBOUND, 0)) && (c = sfvalue(fdin)) > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = inbuff;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin endbuff = cp + --c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((lastchar = cp[c]) != cuthdr->ldelim)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *endbuff = cuthdr->ldelim;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* process each line in the buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(cp <= endbuff)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin first = cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!inword)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nodelim = empty = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin copy = cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(nfields = *(lp = cuthdr->list))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin copy = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nfields = *++lp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(copy)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin copy = cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin inword = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(!inword)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip over non-delimiter characters */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(!(c=cuthdr->space[*cp++]));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for end-of-line */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(endline(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(cp<=endbuff)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((c=cuthdr->space[lastchar]),endline(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore cuthdr->last. character */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(lastchar != cuthdr->ldelim)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *endbuff = lastchar;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin inword++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nodelim = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(--nfields >0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nfields = *++lp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(copy)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin empty = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((c=(cp-1)-copy)>0 && sfwrite(fdout,(char*)copy,c)< 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto failed;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin copy = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set to delimiter unless the first field */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin copy = cp -!empty;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!inword)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!copy)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(nodelim)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cuthdr->sflag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(offset)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfseek(fdtmp,(Sfoff_t)0,SEEK_SET);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfmove(fdtmp,fdout,offset,-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin copy = first;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(fdout,'\n');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(offset)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfseek(fdtmp,offset=0,SEEK_SET);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(copy && (c=cp-copy)>0 && (!nodelim || !cuthdr->sflag) && sfwrite(fdout,(char*)copy,c)< 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto failed;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see whether to save in tmp file */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(nodelim && inword && !cuthdr->sflag && (c=cp-first)>0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* copy line to tmpfile in case no fields */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!fdtmp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fdtmp = sftmp(BLOCK);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfwrite(fdtmp,(char*)first,c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin offset +=c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinfailed:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fdtmp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose(fdtmp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinb_cut(int argc,char *argv[], void* context)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Sfio_t *fp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Cut_t *cuthdr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int mode = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int wdelim = '\t';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int ldelim = '\n';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size_t reclen = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cmdinit(argc, argv, context, ERROR_CATALOG, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (n = optget(argv, usage)) switch (n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'b':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'c':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(mode&C_FIELDS)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "f option already specified");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = opt_info.arg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n=='b')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode |= C_BYTES;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode |= C_CHARS;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'D':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ldelim = *(unsigned char*)opt_info.arg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'd':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin wdelim = *(unsigned char*)opt_info.arg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'f':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(mode&(C_CHARS|C_BYTES))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "c option already specified");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = opt_info.arg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode |= C_FIELDS;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode |= C_NOCHOP;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'N':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode |= C_NONEWLINE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'R':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'r':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(opt_info.num>0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reclen = opt_info.num;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 's':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode |= C_SUPRESS;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ':':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '?':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_usage(2), "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv += opt_info.index;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (error_info.errors)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_usage(2), "%s",optusage(NiL));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "b, c or f option must be specified");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_usage(2), "%s", optusage(NiL));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!*cp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(3, "non-empty b, c or f option must be specified");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((mode & (C_FIELDS|C_SUPRESS)) == C_SUPRESS)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(3, "s option requires f option");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cuthdr = cutinit(mode,cp,wdelim,ldelim,reclen);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(cp = *argv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cp || streq(cp,"-"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fp = sfstdin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(!(fp = sfopen(NiL,cp,"r")))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_system(0),"%s: cannot open",cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(mode&C_FIELDS)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cutfields(cuthdr,fp,sfstdout);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cutcols(cuthdr,fp,sfstdout);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fp!=sfstdin)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose(fp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(cp= *argv++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(error_info.errors?1:0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}