capp - cut and paste processor

Ozan Yigit oz at yetti.UUCP
Sat Jan 18 08:28:15 AEST 1986


Following is a little cut and paste processor inspired by
m4 divert/undivert macros. It is useful only if your favorite
editor is not too good in cutting and pasting. If you are an
emacsoid, you may safely ignore this. 

[Please do not bother with any notes about how it takes 10 lines
of awk to accomplish the same thing. Not all systems have awk as
yet...nor sed for that matter..]

Oz
--------------- CLIP ----- CLIP -------------------------------
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	capp.l
#	capp.c
# This archive created: Fri Jan 17 17:22:33 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'capp.l'" '(2329 characters)'
if test -f 'capp.l'
then
	echo shar: over-writing existing file "'capp.l'"
fi
sed 's/^X//' << \SHAR_EOF > 'capp.l'
X.TH capp local
X.DA Jan 5 1986
X.SH NAME
Xcapp \- cut and paste processor
X.SH ORIGIN
XMetasystems
X.SH SYNOPSIS
X.ft B
Xcapp [-s \fIchar\fB] [-c \fIchar\fB] [-e \fIchar\fB] [-p \fIchar\fB]
X.ft
X.SH DESCRIPTION
XCapp is a cut and paste processor (hence the name) inspired by 
X.I m4
Xdivert/undivert macros. Capp is intended for major text re-organization
Xin files. Of course, capp is only useful if your favorite editor is not
Xwell equipped to handle such re-organization in a coherent manner. 
X.PP
XUnlike
X.I m4
Xor
X.I sed,
Xcapp makes two passes. During the first pass, standard input is read and the
Xtext between
X.B %Cn
X(where 
X.B n
Xis an cut index between 0-9) and
X.B %E
Xis saved and removed from input. Thus processed, input is saved in a temporary
Xfile.  
X.PP
XDuring the second pass, temporary file is read, and all occurences of
X.B %Pn
Xis replaced with the contents of the cut section
X.B n. 
Xthe second pass enables any text to be moved to somewhere 
X.I in front
Xof the location from where it was cut.
X.PP
XThe cut sections remain intact until capp is finished, thus
Xthe same cut may be pasted to several different places. At the end of
Xprocessing, all unprocessed cut sections are pasted at the end of the output
Xin sequence. All output is written on the standard output.
X.SH OPTIONS
X.PP
XThe options and their effects are as follows:
X.de OP
X.TP 6
X.B \\-\\$1 \\fI\\$2\\fR
X..
X.OP s char
Xchanges the 
X.B start
Xcharacter to something other than
X.B %.
XThis character must appear in the first column in the file.
X.OP c char
Xchanges the
X.B cut
Xcharacter to something other than
X.B C.
X.OP e char
Xchanges the
X.B end
Xcharacter to something other than
X.B E.
X.OP p char
Xchanges the 
X.B paste
Xcharacter to something other than
X.B P.
X.SH NOTES
X.B %C0
Xis the same as 
X.B %E. 
XAlso, if the cut section number less than 0, or greater
Xthan 9, it is essentially a bitbucket cut.
X.SH AUTHOR
XOzan S. Yigit (oz)
X.SH SEE ALSO
Xm4(1).
X.SH BUGS
XCapp works in a line-oriented mode, thus it is impossible to
Xcut and paste arbitrary chunks of text from within lines.
X.PP
XMaximum input line size is 512 bytes.
X.PP
XCapp is probably redundant in any system that can run a version
Xof EMACS, or any such editor with powerful multi-buffer cut/paste
Xor yank/pop operations.
X.PP
XCapp can only handle standard input. Perhaps multiple file handling
Xmay be a useful addition.
SHAR_EOF
if test 2329 -ne "`wc -c 'capp.l'`"
then
	echo shar: error transmitting "'capp.l'" '(should have been 2329 characters)'
fi
echo shar: extracting "'capp.c'" '(5097 characters)'
if test -f 'capp.c'
then
	echo shar: over-writing existing file "'capp.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'capp.c'
X/*
X * capp - cut and paste processor
X *
X * capp is a batch-mode cut and paste processor for
X * dramatic reorganization of files. unlike m4 and
X * similar filter programs, it makes two passes:
X *	pass1: process all cut requests
X *	pass2: process all paste requests 
X * which enables the cut fragments to be pasted
X * somewhere *in front* of the actual cut location.
X * capp is especially useful in situations where
X * the reorganization of the file is such that most
X * screen editors will keep you on your terminal for
X * hours. It is even possible to enter the text with
X * future organization in mind, and simply run 
X * capp from within the editor. 
X *
X * by default, all cut sections that are not pasted
X * elsewhere get pasted to the end of the file in
X * sequence.
X *
X * Author: Ozan S. Yigit
X *	   Metasystems
X *	   Jan 3 1986
X *
X * Jan 07 1986 Oz	Getopt interface and misc. options.
X * Jan 03 1986 Oz	Initial cut.
X */
X#include <stdio.h>
X#include <signal.h>
X
Xchar *divfile = "/tmp/cap*XXXXXX";	/* diversion file names */
X#define UNIQUE	8
X
X#define MAXOUT	10
X#define BUFMAX	512
X#define WR	1
X#define RD	0
X
X#define	CREAT	1
X#define	USED	2
X
Xstruct dfile {
X	FILE *fp;
X	char  fl;
X	char *fn;
X};
X
XFILE *active;				/* active output file   */
XFILE *temp;				/* temporary output     */
Xstruct dfile outfile[MAXOUT];		/* diversion array      */
Xchar *captemp;				/* filename for temp.   */
Xchar buf[BUFMAX];			/* input buffer..       */
X
Xchar stac = '%';			/* default starter char */
Xchar cutc = 'C';			/* default "cut"   char */
Xchar pasc = 'P';			/* default "paste" char */
Xchar endc = 'E';			/* default "end"   char */
X
Xint onintr();
Xchar *save();
Xchar *malloc();
Xchar *mktemp();
X
Xmain(argc, argv)
Xchar *argv[];
X{
X	extern char *optarg;
X	extern int optind;
X
X	int c;
X	register char *p;
X
X	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X		(void) signal(SIGINT, onintr);
X
X	while ((c = getopt(argc, argv, "c:p:e:s:")) != EOF)
X		switch(c) {
X
X		case 's':
X			stac = *optarg;
X			break;
X		case 'c':
X			cutc = *optarg;
X			break;
X		case 'p':
X			pasc = *optarg;
X			break;
X		case 'e':
X			endc = *optarg;
X			break;
X		case '?':
X			usage();
X		}
X
X
X	captemp = mktemp(divfile);
X	if ((temp = fopen(captemp, "w")) == NULL)
X		cant(captemp, WR);
X	active = temp;
X	/*
X	 * first pass: 	collect all CUT sections.
X	 *		resuting file goes into temp. CUT
X	 *		indicates that the section dissapears
X	 *		from the input file, and stored in
X	 *		one of the diversions, or in the
X	 *		bitbucket.
X	 */
X	while ((p = fgets(buf, BUFMAX, stdin)) != NULL)
X		if (*p++ == stac) {
X			if ((c = *p++) == cutc) {	
X				while (*p == ' ' || *p == '\t')
X					p++;
X				divert(atoi(p));
X			}
X			else if (c == endc)
X				divert(0);
X			else
X				out(buf);
X		}
X		else
X			out(buf);
X	(void) fclose(temp);
X	closeall();
X	captemp[UNIQUE] = '*';
X	if ((temp = fopen(captemp, "r")) == NULL)
X		cant(captemp, RD);
X	active = stdout;
X	/*
X	 * second pass: now read in all diversions. (PASTE)
X	 *		since we keep diversions around,
X	 *		it is possible to read them into
X	 *		different places more than once.
X	 */
X
X	while ((p = fgets(buf, BUFMAX, temp)) != NULL)
X		if (*p++ == stac) {
X			if (*p++ = pasc) {
X				while (*p == ' ' || *p == '\t')
X					p++;
X				undivert(atoi(p));
X			}
X			else
X				out(buf);
X		}
X		else
X			out(buf);
X	/*
X	 * at the end: read in all created
X	 *	       but unused diversions.
X	 */
X	unused();
X	rmall();
X	exit(0);
X}
X
Xdivert(n) {
X	if (n != 0) {
X		if (n < 0 || n >= MAXOUT)
X			n = 0;
X		if (outfile[n].fp == NULL) {
X			captemp[UNIQUE] = n + '0';
X			if ((outfile[n].fp = fopen(captemp, "w")) == NULL)
X				cant(captemp, WR);
X			outfile[n].fn = save(captemp);
X			outfile[n].fl |= CREAT;
X		}
X		active = outfile[n].fp;
X	}
X	else
X		active = temp;
X}
X
Xundivert(n) {
X	if (n > 0 && n < MAXOUT)
X		getdiv(n);
X}
X
Xcloseall() {
X	register int n;
X
X	for (n = 0; n < MAXOUT; n++)
X		if (outfile[n].fp != NULL) {
X			(void) fclose (outfile[n].fp);
X			outfile[n].fp = NULL;
X		}
X}
X
Xunused() {
X	register int n;
X
X	for (n = 1; n < MAXOUT; n++)
X		if (outfile[n].fl == CREAT)	/* created but not used */
X			getdiv(n);
X}
X
Xrmall() {
X	register int n;
X
X	for (n = 0; n < MAXOUT; n++)
X		if (outfile[n].fl & CREAT) {
X			if (outfile[n].fp != NULL)
X				(void)	fclose (outfile[n].fp);
X			(void) unlink(outfile[n].fn);
X		}
X	captemp[UNIQUE] = '*';
X	(void) unlink(captemp);
X}
X
Xgetdiv(n) {
X	register int c;
X
X	if (!(outfile[n].fl & CREAT))
X		fprintf(stderr,"diversion #%d is inactive.\n",n);
X	else {
X		if (outfile[n].fp == NULL) {
X			if ((outfile[n].fp = fopen(outfile[n].fn, "r")) == NULL)
X				cant(outfile[n].fn, RD);
X		
X		}
X		else
X			rewind(outfile[n].fp);
X		outfile[n].fl |= USED;
X		while ((c = getc(outfile[n].fp)) != EOF)
X			putc(c, active);
X	}
X}
X
Xout(s)
Xchar *s;
X{
X	while (*s)
X		putc(*s++, active);
X}
X
Xonintr() {
X	rmall();
X	fprintf(stderr, "\ninterrupted.\n");
X	exit(1);
X}
X
Xcant(s, n)
Xchar *s;
X{
X	fprintf(stderr, "%s: cannot open for %s.\n", s, n ? "write" : "read");
X	rmall();
X	exit(1);
X}
X
Xchar *save(s)
Xchar *s;
X{
X	char *p;
X	if ((p = malloc(strlen(s) + 1)) != NULL)
X		(void) strcpy(p, s);
X	return(p);
X}
X
Xusage() {
Xfprintf(stderr, "usage: capp [-s char] [-c char] [-e char] [-p char]\n");
X	exit(1);
X}
SHAR_EOF
if test 5097 -ne "`wc -c 'capp.c'`"
then
	echo shar: error transmitting "'capp.c'" '(should have been 5097 characters)'
fi
#	End of shell archive
exit 0
-- 
Usenet: [decvax|allegra|linus|ihnp4]!utzoo!yetti!oz
Bitnet: oz@[yusol|yuyetti]
		In the beginning, there was Word all right, except
		it wasn't fixed number of bits.



More information about the Comp.sources.unix mailing list