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 p

⟦436ec65f8⟧ TextFile

    Length: 4780 (0x12ac)
    Types: TextFile
    Names: »paste.c«

Derivation

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

TextFile

/*
 * A version of paste. This is compatable with AT&T paste command SVR2.
 *
 * John Weald
 *
 */
#include <stdio.h>

#define MAXLINE   1024			/* Max. allowed line length	*/
#define MAXFILES  12			/* Max. number of input files   */

extern void exit();

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

	int c;				/* For getopt()			*/
	char conchars[MAXFILES];	/* The concatination characters */
	int nconchars = 1;		/* The number of conchars[]	*/
	int serial = 0;			/* True if old type paste "-s"	*/

	conchars[0] = '\t';

	while ((c = getopt(argc, argv, "sd:")) != EOF)
	{
		switch(c)
		{
		   case 's':
			/* Concatinate the same file serially */
			serial++;
			break;

		   case 'd':
			/* Use other than a single tab */
			nconchars = setconcat(conchars, optarg);
			break;

		   default:
			/* Does not return */
			prusage();
		}
	}


	if (serial)
		spaste(&argv[optind], conchars, nconchars);
	else
		paste(&argv[optind], conchars, nconchars);
	exit(0);
/* NOTREACHED */
}



/*
 * paste()
 *
 * Do the actual paste.
 */
paste(files, con, ncons)
char *files[];		/* Null terminated list of input files		*/
char con[];		/* The concatination characters			*/
char ncons;		/* The number of above				*/
{
	char ibuf[MAXLINE+1];		/* The  input buffer		*/
	char obuf[MAXLINE];		/* The  output buffer		*/
	register char *iptr = ibuf;
	register char *optr = obuf;
	FILE *fps[MAXFILES];		/* One for each open file 	*/
	int f;				/* Number of files opened	*/
	int allfiles;			/* Ditto			*/
	int inc;			/* True if concat. char. == '\0'*/
	int ocount;			/* Output buffer char. count	*/
	char c;				/* The current concat. char	*/
	int i;

	/*
	 * Open all the input files, any filename of '-' means
	 * the standard input. No file name means standard input.
	 */
	for (f = 0; files[f] != (char *)NULL; f++)
	{
		if (*files[f] == '-')
			fps[f] = stdin;
		else if ((fps[f] = fopen(files[f], "r")) == (FILE *)NULL)
		{
			fprintf(stderr, "Failed to open file %s\n", files[f]);
			exit(1);
		}
		if (f >= MAXFILES)
		{
			fprintf(stderr, 
			   "Too many files. Maximum allowed is %d\n", MAXFILES);
			exit(1);
		}
	} 
	if (files[0] == (char *)NULL)
	{
		fps[0] = stdin;
		f++;
	}

	/*
	 * Read all lines until no more lines in any file.
	 */
	allfiles = f;
	while (f)
	{
		optr = obuf;
		ocount = 0;
		/*
		 * Join lines from all files.
		 *
		 * The concatination character may be '\0' which
		 * means no character. The variable inc is an indication
		 * of the concatination character being '\0', we need to
		 * if there is a concatination character to move up the
		 * output buffer.
		 *
		 * The concatination characters are used in a round robin
		 * list.
		 */

		for (inc = 0, i = 0; i < allfiles; i++)
		{
			iptr = ibuf;
			optr += inc;
			/* To save repeated evaluation */
			c = con[i % ncons];
			inc = c == '\0' ? 0 : 1;

			if (fps[i] == (FILE *)NULL)
			{
				/* No more lines in this file. */

				*optr = c;
				continue;
			}
			if (fgets(ibuf, sizeof(ibuf), fps[i]) == (char *)NULL)
			{
				/* Reached EOF - finished with the file */
				(void)fclose(fps[i]);
				fps[i] = (FILE *)NULL;
				*optr = c;
				f--;
				continue;
			}

			/*
			 * Replace the newline with the concatination character.
			 * There is no need to look for end-of-string since
			 * we know that 
			 * a) if ibuf is full to the max, then we will
			 *    overflow obuf before we hit the end of ibuf.
			 * b) if ibuf is not full, then it must contain a
			 *    a newline character, but may or may not  
			 *    fit into obuf.
			 */
			for (;  *iptr != '\n'; ocount++)
			{
				/* Need space for trailing null */
				if (ocount >= sizeof(obuf) - 1)
				{
					fprintf(stderr, "Output line too long, maximum length is %d.\n", MAXLINE);
					exit(1);
				}
				*optr++ = *iptr++;
			}
			*optr = c;

		}
		if (f)
		{
			*optr = '\0';
			puts(obuf);
		}
	}
}


/*
 * setconcat()
 *
 * Parse the concatination characters and place them in the array c.
 * Return the number of concatination characters.
 *
 * Specials are:
 *	\n	- Newline
 *	\t	- Tab (default)
 *	\	- Backslash
 *	\0	- No concatination character
 */
static int
setconcat(c, in)
char *c;
char *in;
{
	int i;		/* The number seen so far			*/

	for (i = 0; *in != '\0'; in++, c++, i++)
	{
		if (i > MAXFILES)
		{
			fprintf(stderr, "Too many concatination characters, maximum allowed is %d\n", MAXFILES);
			exit(1);
		}
		if (*in != '\\')
		{
			*c = *in;
			continue;
		}
		in++;
		switch (*in)
		{
		   case 'n':
			*c = '\n';
			break;
		   case 't':
			*c = '\t';
			break;
		   case '0':
			*c = '\0';
			break;
		   default:
			/* Includes '\\' */
			*c = *in;
			break;
		}
	}
	return(i);
}

static 
prusage()
{
	fprintf(stderr, "USAGE: paste [-s] [-d<list>] files\n");
	exit(1);
}