DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T c

⟦948fb4299⟧ TextFile

    Length: 4941 (0x134d)
    Types: TextFile
    Names: »cut.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/cut/cut.c« 

TextFile

/*
 *  This acts the same as SV cut(1), except that the list of numbers
 *  does not have to be assending.
 *
 * John Weald
 */
#include <stdio.h>
#include <ctype.h>

#define MAXLINE	1024		/* The max. length of a line		*/

extern void exit();

main(argc, argv)
int argc;
char *argv[];
{
	extern char *optarg;
	extern int optind;

	static int fields[MAXLINE];/* The field markers. True if this field */
				   /* is to be cut, False otherwise	*/
	FILE *fp;		   /* All the input files or stdin	*/
	char buf[MAXLINE];	   /* The input buffer			*/
	int c;			   /* The command line option		*/
	int err = 0;		   /* True if error in command line	*/
	int fflag = 0;		   /* True if -f on command line	*/
	int cflag = 0;		   /* True if -c on command line	*/
	int suppress = 0;	   /* Suppress lines with no delimitor	*/
	char fs = '\t';		   /* The field separator		*/

	
	while ((c = getopt(argc, argv, "f:d:c:s")) != EOF)
	{
		switch (c)
		{
		   case 'f':
			/* By Field */
			list(fields, optarg);
			fflag++;
			if (cflag)
				err++;
			break;

		   case 'c':
			/* By character */
			list(fields, optarg);
			/* Implied suppress */
			suppress++;
			cflag++;
			if (fflag)
				err++;
			break;

		   case 'd':
			/* A new field spererator */
			fs = *optarg;
			break;

		   case 's':
			suppress++;
			break;

		   default:
			prusage();
		}
	}

	if (!cflag && !fflag)
	{
		fprintf(stderr, "Must have one of -f or -c\n");
		err++;
	}
	if (err)
		prusage();


	/*
	 * Loop on all the files.
	 */
	do {
		if (optind == argc)
			fp = stdin;
		else if ((fp = fopen(argv[optind], "r")) == (FILE *)NULL)
		{
			fprintf(stderr, "Failed to open file %s\n", 
					argv[optind]);
			exit(1);
		}

		/*
		 * Loop on all lines in the file.
		 */
		while (fgets(buf, sizeof(buf), fp) != (char *)NULL)
		{
			cut(buf, fields, fs, suppress, cflag);
		}
		(void)fclose(fp);
	} while (++optind < argc);

	exit(0);
/* NOTREACHED */
}

/*
 * Cut the line. This handles both character and field cutting.
 * For character cutting the f array gives character positions, for
 * fields it gives the field number. It must be indexed by either the
 * character number or the field number.
 */
cut(in, f, fs, sup, c_or_f)
register char *in;		/* The input line			*/
int f[];			/* The field cutting flags		*/
char fs;			/* The field seperator			*/
int sup;			/* Suppress lines with no-delimitor?	*/
int c_or_f;			/* Cut by char. (true), or field (false)*/
{
	char obuf[MAXLINE];	/* Output buffer			*/
	register char *optr = obuf;
	register int i;		/* Character count			*/
	register int fld;	/* The field count			*/
	char *instart = in;	/* To print lines with no delimiters	*/

	for (fld = 0, i = 0; i < MAXLINE; i++)
	{
		if (*in == '\n')
		{
			/* End of the line */

			*optr = '\0';
			/* Any thing to cut? */
			if (optr != obuf)
			{
				/* Get ride of trailing seperator */
				if (*(optr - 1) == fs)
					*(optr - 1) = '\0';
				puts(obuf);
			}
			else if (!sup)
				printf(instart);
			return;
		}

		if (f[c_or_f ? i : fld])
		{
			*optr++ = *in;
		}

		/* End of field? */
		if (*in++ == fs)
			fld++;
	}

	fprintf(stderr, "Line too long, maximum length is %d\n", MAXLINE);
	exit(1);
}

/*
 * Parse the list argument. The format is:
 *	n,n
 * where n is either a number or a range of numbers in the format
 *	m-l
 * m or l  may be absent, indicating the start or end of the lines respectivly.
 * Numbers must be in increasing order for m-l format, but not for n,n.
 * Field numbers start at 1, but index into fields array starts at 0.
 * 
 */
list(f, l)
int f[];		/* The fields				*/
char *l;		/* The list				*/
{
	int range = 0;	/* True if m-l format			 */
	int low, high;	/* the low and high numbers in a m-l pair*/
	int i;

	low = high = 0;

	while (1)
	{
		switch(*l)
		{
		   case '\0':
			/* Is it m-<nothing>EOL? */
			if (range)
			{
				/* Select rest of fields */
				for(i = low - 1; i < MAXLINE; i++)
					f[i]++;
			}
			else
				f[low-1]++;
			return;

		   case ',':
			l++;
			if (!range)
				f[low-1]++;
			range = 0;
			low = 1;
			break;

		   case '-':
			l++;
			range++;
			/* Is it m-<nothing> */
			if (isdigit((int)*l))
			{
				high = atoi(l);
				/* Skip the digits */
				while (isdigit((int) *l))
					l++;
			}
			else
				high = MAXLINE;

			/* Is the range the correct way around? */
			if (low > high)
			{
				fprintf(stderr, "Bad c/f list: %d > %d\n", 
							low, high);
				exit(1);
			}
			/* Set the field flags for the range */
			for(i = low - 1; i < high; i++)
				f[i]++;
			break;

		    default:
			/* either a number or an error */
			if (!isdigit((int) *l))
			{
				fprintf(stderr, "Bad c/f list at %s\n", l);
				exit(1);
			}
			low = atoi(l);
			if (low == 0)
			{
				fprintf(stderr, "Fields start at 1 not 0\n");
				exit(1);
			}
			/* Skip the digits */
			while (isdigit((int) *l))
				l++;
			break;
		}
	}
}

prusage()
{
	fprintf(stderr, "cut [-d<delimitor>] [-s] -c<list>|-f<list> [files]\n");
	exit(1);
}