home *** CD-ROM | disk | FTP | other *** search
- From decwrl!wyse!uunet!allbery Sun Jan 29 16:45:24 PST 1989
- Article 784 of comp.sources.misc:
- Path: granite!decwrl!wyse!uunet!allbery
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Newsgroups: comp.sources.misc
- Subject: v06i009: xc: a mini-make
- Message-ID: <47273@uunet.UU.NET>
- Date: 24 Jan 89 02:59:25 GMT
- Sender: allbery@uunet.UU.NET
- Reply-To: edf@ROCKY2.ROCKEFELLER.EDU (David MacKenzie)
- Lines: 422
- Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 6, Issue 9
- Submitted-by: edf@ROCKY2.ROCKEFELLER.EDU (David MacKenzie)
- Archive-name: xc
-
- Xc is a program to execute commands within source code files.
- It's mainly useful for compiling small programs where there are
- many of them stored in one directory and keeping a lot of makefiles
- around would be a pain. It doesn't do any timestamp-checking
- like make does, but it's not really meant for projects that are
- composed of multiple source files anyway.
-
- A typical C program source file might start out like
-
- /*
- % cc -O foo.c -o foo -ltermcap
- %i cc -O foo.c -o foo -ltermcap
- %i cp foo /usr/new; chmod 755 /usr/new/foo
- */
-
- So you could ``xc foo.c'' to make it, or ``xc -i foo.c'' to make and
- install it.
-
- Xc is distantly descended from an anonymous program of the same name
- that I found on a computer at St. Olaf College a couple of years ago.
- Not much remains of the original code, though.
-
- -----
- David MacKenzie
- Environmental Defense Fund
- edf@rocky2.rockefeller.edu (...rutgers!cmcl2!rocky2!edf)
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: xc.1 xc.c
- # Wrapped by dave@zedfdc on Fri Dec 30 02:09:39 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'xc.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xc.1'\"
- else
- echo shar: Extracting \"'xc.1'\" \(1327 characters\)
- sed "s/^X//" >'xc.1' <<'END_OF_FILE'
- X.TH XC 1L
- X.SH NAME
- Xxc, xcb \- execute commands contained in a file
- X.SH SYNOPSIS
- X.B xc
- Xor
- X.B xcb
- X[
- X.B \-c key_character
- X] [
- X.B file
- X]
- X.SH DESCRIPTION
- X.I Xc
- Xsearches a
- X.I file
- Xfor a sequence of lines with the form
- X.sp
- X%c command_line
- X.sp
- Xor
- X.sp
- X$c command_line
- X.sp
- Xwhere 'c' is a single key character given with the
- X.I \-c
- Xcommand line option.
- XIt then executes each
- X.I command_line
- Xin turn.
- X.PP
- XIf the
- X.I \-c
- Xoption is omitted, lines with the form
- X.sp
- X% command_line
- X.sp
- Xor
- X.sp
- X$ command_line
- X.sp
- Xare executed. The `%' form echos the command line; the `$' form does not.
- X.PP
- XWhen invoked as
- X.I xcb,
- Xthe program automatically runs in the background, redirects the
- Xstandar output and standard error output to the file
- X.BR ./ERRS ,
- Xand makes a short announcement
- Xon its controlling terminal when it finishes.
- X.PP
- X.I Xc
- Xsaves the last filename and key character which were used
- Xinto the file
- X.BR $HOME/.xc ,
- Xand uses that file's contents as the defaults if the
- X.I file
- Xargument is omitted.
- X.PP
- XIf the
- X.I file
- Xcontains program source code, the
- X.I xc
- Xcommand lines should probably be enclosed within comments;
- Xhowever, the `%' and `$' must be the first characters on their lines,
- Xand be immediately followed by the key characters.
- X.SH FILES
- X$HOME/.xc
- X.PP
- XERRS
- X.SH "SEE ALSO"
- X.BR cc (1),
- X.BR sh (1)
- X.SH AUTHOR
- XDavid MacKenzie (mostly)
- END_OF_FILE
- if test 1327 -ne `wc -c <'xc.1'`; then
- echo shar: \"'xc.1'\" unpacked with wrong size!
- fi
- # end of 'xc.1'
- fi
- if test -f 'xc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xc.c'\"
- else
- echo shar: Extracting \"'xc.c'\" \(6428 characters\)
- sed "s/^X//" >'xc.c' <<'END_OF_FILE'
- X/*
- X xc - execute commands contained in a file
- X xcb - same, but in the background
- X
- X Usage: xc [-c key_character] [file]
- X xcb [-c key_character] [file]
- X
- X xc -c x file key: 'x' file: "file"
- X xc file key: ' ' file: "file"
- X xc -c x key: 'x' file: ~/.xc
- X xc key: ~/.xc file: ~/.xc
- X
- X Searches a file for a sequence of lines (probably in a comment)
- X with the form
- X %c command_line
- X or
- X $c command_line
- X where 'c' (any single character) in "%c" or "$c" is the same as
- X the key character given with the "-c" option on the command line,
- X and executes the command_lines.
- X If the "-c" option is omitted, lines with the form
- X % command_line
- X or
- X $ command_line
- X are executed.
- X The '%' form echos the command_line; the '$' form does not.
- X
- X When invoked as xcb, it automatically runs in the background, redirects
- X stdout and stderr to the file ./ERRS, and announces when it finishes.
- X
- X It saves the last filename and key character which were used
- X into $HOME/.xc, and uses that file's contents as the defaults if the
- X filename argument is omitted.
- X $HOME/.xc contains one line of the form:
- X c-filename
- X where 'c' is the key character, or a space if none was given.
- X
- X Latest modification: 12/30/88 */
- X
- X#include <stdio.h>
- X
- X#define XCFILE "/.xc" /* Where default file, key are read from. */
- X#define ERRFILE "ERRS" /* Where output goes if in background. */
- X
- Xvoid perror (), exit ();
- Xchar *getenv (), *strcpy (), *strcat (), *strchr (), *strrchr (), *fgets ();
- X
- Xvoid pfatal (), usage ();
- Xvoid read_xc_file (), write_xc_file ();
- Xvoid detatch (), notify (), execute ();
- Xchar *make_xc_name (), *basename ();
- X
- Xchar *program_name; /* Base of program name. */
- X
- Xmain (argc, argv)
- X int argc;
- X char **argv;
- X{
- X extern int optind; /* Option index. */
- X extern char *optarg; /* Option argument. */
- X char *xcfile; /* Expansion of "$HOME/.xc". */
- X char *file_name; /* File to get commands from. */
- X char key; /* Command line selector. */
- X int background; /* Run in the background? */
- X int c; /* Option character. */
- X
- X program_name = basename (argv[0]);
- X file_name = NULL;
- X key = 0;
- X background = !strcmp (program_name, "xcb");
- X xcfile = make_xc_name ();
- X
- X while ((c = getopt(argc, argv, "c:")) != EOF)
- X switch (c)
- X {
- X case 'c':
- X if (strlen (optarg) != 1)
- X {
- X fprintf (stderr, "%s: %s: Key must be one character long\n",
- X argv[0], optarg);
- X usage ();
- X }
- X key = *optarg;
- X break;
- X default:
- X usage ();
- X }
- X
- X if (optind < argc - 1)
- X usage ();
- X else if (optind == argc - 1)
- X file_name = argv[optind];
- X else
- X /* Read filename, and key if not set yet, from XCFILE. */
- X read_xc_file (xcfile, &file_name, &key);
- X
- X if (key == 0 || key == '\t')
- X key = ' ';
- X
- X if (background)
- X detatch ();
- X
- X execute (file_name, key);
- X
- X write_xc_file (xcfile, file_name, key);
- X
- X if (background)
- X notify ();
- X
- X exit (0);
- X}
- X
- X/* Return the path of the file "$HOME/.xc". */
- X
- Xchar *make_xc_name ()
- X{
- X static char xcbuf[BUFSIZ]; /* "$HOME/XCFILE". */
- X char *home;
- X
- X home = getenv ("HOME");
- X if (!home)
- X {
- X fprintf (stderr,
- X "%s: HOME environment variable is not defined\n", program_name);
- X exit (1);
- X }
- X (void) strcpy (xcbuf, home);
- X (void) strcat (xcbuf, XCFILE);
- X return xcbuf;
- X}
- X
- X/* Read from xcfile the filename, and the key if it's not already set. */
- X
- Xvoid read_xc_file (xcfile, file_namep, keyp)
- X char *xcfile;
- X char **file_namep;
- X char *keyp;
- X{
- X FILE *fp;
- X char *newline;
- X static char line[BUFSIZ];
- X
- X fp = fopen (xcfile, "r");
- X if (!fp)
- X pfatal (xcfile);
- X (void) fgets (line, BUFSIZ, fp);
- X newline = strchr (line, '\n');
- X if (newline)
- X *newline = 0;
- X (void) fclose (fp);
- X
- X *file_namep = &line[2];
- X if (*keyp == 0)
- X *keyp = *line;
- X}
- X
- X/* Update the xcfile. */
- X
- Xvoid write_xc_file (xcfile, file_name, key)
- X char *xcfile;
- X char *file_name;
- X char key;
- X{
- X FILE *fp;
- X
- X fp = fopen (xcfile, "w");
- X if (!fp)
- X return;
- X fprintf (fp, "%c-%s\n", key, file_name);
- X (void) fclose (fp);
- X}
- X
- Xstatic int save_stdout; /* Save file descriptor for notification. */
- X
- X/* Redirect the standard streams and fade into the background. */
- X
- Xvoid detatch ()
- X{
- X save_stdout = dup (1);
- X if (save_stdout == -1)
- X pfatal ("Can't dup standard output");
- X if (!freopen (ERRFILE, "w", stdout))
- X pfatal (ERRFILE);
- X (void) close (2);
- X if (dup (1) != 2) /* Could be 0 if stdin was closed. */
- X if (dup (1) == -1)
- X pfatal ("Can't dup standard output");
- X switch (fork ())
- X {
- X case -1:
- X pfatal ("Can't fork");
- X case 0:
- X break;
- X default:
- X exit (0);
- X }
- X}
- X
- Xvoid notify ()
- X{
- X (void) write (save_stdout, "\r\n\007[xcb: done]\r\n", 16);
- X printf ("Done\n");
- X (void) fflush (stdout);
- X}
- X
- X/* Read the file and execute command lines that match the key. */
- X
- Xvoid execute (file_name, key)
- X char *file_name;
- X char key;
- X{
- X FILE *fp; /* Pointer to file stream. */
- X char line[BUFSIZ]; /* One line of file. */
- X char *command; /* Command to execute. */
- X int key_matched = 0; /* Has command line matching key been found? */
- X int status; /* Return status from system. */
- X
- X fp = fopen (file_name, "r");
- X if (!fp)
- X pfatal (file_name);
- X
- X while (fgets (line, BUFSIZ, fp))
- X {
- X if (line[1] == '\t')
- X line[1] = ' ';
- X if ((*line != '%' && *line != '$') || line[1] != key)
- X {
- X if (key_matched)
- X break;
- X else
- X continue;
- X }
- X key_matched = 1;
- X /* Skip leading whitespace in the command for aesthetic reasons. */
- X for (command = &line[2];
- X *command && (*command == ' ' || *command == '\t'); ++command)
- X /* Do nothing. */ ;
- X if (*line == '%')
- X {
- X printf (" %s", command);
- X (void) fflush (stdout);
- X }
- X status = system (command);
- X if (status)
- X {
- X fprintf (stderr, "%s: ** Exit status 0%o **\n", program_name, status);
- X break;
- X }
- X }
- X (void) fclose (fp);
- X
- X if (!key_matched)
- X {
- X fprintf (stderr,
- X "%s: %s: No commands for key '%c'\n", program_name, file_name, key);
- X exit (1);
- X }
- X}
- X
- X/* Return name with any leading path stripped off. */
- X
- Xchar *basename (name)
- X char *name;
- X{
- X char *base;
- X
- X base = strrchr (name, '/');
- X return base ? base + 1 : name;
- X}
- X
- Xvoid pfatal (message)
- X char *message;
- X{
- X fprintf (stderr, "%s: ", program_name);
- X perror (message);
- X exit (1);
- X}
- X
- Xvoid usage ()
- X{
- X fprintf (stderr, "Usage: %s [-c key_character] [file]\n", program_name);
- X exit (1);
- X}
- END_OF_FILE
- if test 6428 -ne `wc -c <'xc.c'`; then
- echo shar: \"'xc.c'\" unpacked with wrong size!
- fi
- # end of 'xc.c'
- fi
- echo shar: End of shell archive.
-
-
-