pc@ukc.UUCP (R.P.A.Collinson) (10/22/85)
Here is a little program with a lot of power. It allows you to place shell commands as comments in files and then execute the commands by pointing the xtx command at the file. It solves many troff/nroff problems and can be used in various other situations. See the manual page for various `this was someone else's idea' caveats. # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #-----cut here-----cut here-----cut here-----cut here----- #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # xtx.c # xtx.1 # This archive created: Mon Oct 21 22:17:15 1985 cat << \SHAR_EOF > xtx.c #ifndef lint static char sccsid[] = "@(#)xtx.c 1.1 (UKC) 13/10/85"; #endif lint /*** * program name: xtx.c * function: Looks in a file for a string of the form <-xtx[letter]-> If the string is followed by a line ending with a \n Then takes the line and executes it using /bin/sh The letter is used to select one of a number of commands which may be embedded in the file. The character '*' is used to mean the default. * switches: -c [letter] select a particular line in the file -e echo the matched command from the file -a print all matched commands from the file and their key letter +[letter] same as -c [letter] files - Take data from standard input for scanning * libraries used: standard * compile time parameters: <-xtx-*> cc -o xtx -O xtx.c <-xtx-l> lint -h xtx.c * history: Written October 1985 Peter Collinson UKC ***/ #include <stdio.h> #include <ctype.h> char cmdbuf[BUFSIZ]; /* Where to store the command */ char selchar='*'; /* selection character */ int echosw; /* set if echo only */ int allsw; /* print all matched commands from the file */ #define WILD 1 /* Wild character in the string below */ char matchs[] = /* Used to find a match with a command */ { '<','-','x','t','x','-',WILD,'>' }; #define STORESTATE (sizeof matchs) char Usage[] = "Usage:txt [-e][-c letter|+letter] files..\n"; main(argc, argv) char **argv; { register char *p; FILE *fd; while (--argc) { p = *++argv; switch (*p) { case '-': p++; switch (*p) { case 'a': allsw++; echosw++; break; case 'c': if (--argc) { argv++; selchar = **argv; } else fatal("No argument to -c given\n"); break; case 'e': echosw++; break; case '\0': scanfile(stdin); if (cmdbuf[0]) execute(cmdbuf); break; default: fatal(Usage); } break; case '+': selchar = p[1]; break; default: if ((fd = fopen(argv[0], "r")) == NULL) { perror(argv[0]); break; } scanfile(fd); (void) fclose(fd); if (cmdbuf[0]) execute(cmdbuf); break; } } exit(1); /* Command has failed */ } /* * Scan a file looking for an appropriate line */ scanfile(fd) FILE *fd; { register c; register state = 0; register char *cmdp; while ((c = getc(fd)) != EOF) { if (state == STORESTATE) { if (isprint(c) || isspace(c)) { if (c == '\n') { *cmdp = '\0'; if (allsw) { execute(cmdbuf); state = 0; continue; } return; } else if (cmdp < &cmdbuf[BUFSIZ]) *cmdp++ = c; continue; } state = 0; } else if (matchs[state] == WILD) { if (allsw) selchar = c; if (c == selchar) state++; else state = 0; } else if (c == matchs[state]) { if (state++ == 0) { cmdp = cmdbuf; *cmdp = '\0'; } } else state = 0; } } /* * Call the shell */ execute(cmdp) register char *cmdp; { for (; isspace(*cmdp); cmdp++); if (allsw) fprintf(stderr, "%c\t%s\n", selchar, cmdp); else fprintf(stderr, "%s\n", cmdp); if (allsw) return; if (echosw) exit(0); execl("/bin/sh", "sh", "-c", cmdp, 0); perror("Exec"); exit(1); } fatal(str) char *str; { fprintf(stderr, str); exit(1); } SHAR_EOF cat << \SHAR_EOF > xtx.1 .TH XTX 1 "UKC local 19/10/85" .UC .SH NAME xtx \- execute embedded text commands .SH SYNOPSIS .B xtx [ .B \-a ] [ .B \-c letter | .B \+ "letter" ] [ .B -e ] files .... .SH DESCRIPTION .I Xtx looks for a magic string in a file and then takes the characters which follow up to the next newline character as a command to be executed by .I sh (1). The default magic string is .TP <\-xtx\-*>. .PP Any tabs and spaces which immediately follow the magic string are removed before the remainder of the line is sent to .I sh for execution. .PP Several commands can be embedded in the file and selected independently by the use of selector characters. If the character * in the xtx command string is replaced by another (printing) character; then the line is only executed if the character is specified to .I xtx using the .B -c letter or .B + letter switches. For instance, a string of the form <\-xtx\-l> will only be recognised and executed if .I xtx is called with the argument of `+l'; for Unix purists the form `-c l' may also be specified with the same effect. .PP The arguments to the program are:- .TP .B -a Print all the xtx lines which can be found in the file with their selector letter. .TP .B -e Echo the command which would be executed by this call to .I xtx. .TP .B -c is followed by a letter, use this letter as the selector character for the .I xtx run. .B + <letter> same as -c but allows the selector letter to be specified in the same argument. .PP All other arguments are files which are searched for matching command lines; a `-' on the input causes data to be taken from the standard input for searching. .SH "SEE ALSO" sh(1) .SH AUTHOR Peter Collinson UKC. .PP The basic idea is not new and exists in several editors (David Tilbrook's) .I qed and the infamous .I vi . However, the idea of making a tool for it seemed like the right thing to do. .PP By the way, xtx is pronounced `extex' and is a verb. It is possible therefore to `extex' a file in order to execute something on it in whatever way seems reasonable. SHAR_EOF # End of shell archive exit 0