head(1), and ctags(1) for AT&T type systems
sources-request at panda.UUCP
sources-request at panda.UUCP
Sat Jan 11 09:25:57 AEST 1986
Mod.sources: Volume 3, Issue 87
Submitted by: Steven List <bene!luke!itkin>
# I've recently had the pleasure (?) of working with an AT&T
# 3B2/300. Among the many differences I encountered are the
# absences of the Berkeley commands head(1) and ctags(1). I'd
# gotten used to those command due to the generosity of Plexus in
# providing them on their System III and V systems. Needless to
# say I immediately sat down and wrote them.
#
# My version of head(1) adds a command line option to the standard:
# +n. In this case, +n means "skip n lines before displaying".
# Yes, I'm aware that I could use sed(1) for this. But sed(1)
# doesn't stop when it has done what you asked. It still processes
# to the end of file. So, I figured that I'd just add this one
# little feature.
#
# My version of ctags(1) is pretty much the same as the Berkeley
# one, as far as I can tell. It uses some code to recognize
# function declarations that I borrowed from `cpr' (I don't have
# the original author's name). It is simple, straightforward, and
# readily modified.
#
# As always, comments, changes, and corrections are welcome.
#
# Steven
#
###
# Steven List @ Benetics Corporation, Mt. View, CA
# Just part of the stock at "Uncle Bene's Farm"
# {cdp,engfocus,greipa,idi,oliveb,plx,sun,tolerant}!bene!luke!itkin
###
#! /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:
# head.c
# ctags.c
# This archive created: Sat Dec 14 17:38:46 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'head.c'" '(4938 characters)'
if test -f 'head.c'
then
echo shar: will not over-write existing file "'head.c'"
else
sed 's/^ZZ//' << \SHAR_EOF > 'head.c'
ZZ/* head - replace head command */
ZZ/*
ZZ * call: head [ +n ] [ -n ] [ file ... ]
ZZ *
ZZ * +n = number of lines to skip before starting display
ZZ * default = 0
ZZ * -n = number of lines to display, starting with top of file
ZZ * default = 10
ZZ * file = any number of files may be present
ZZ * if name is `-', read from standard input
ZZ */
ZZ#include <stdio.h>
ZZ
ZZ#define FALSE 0
ZZ#define TRUE 1
ZZ
ZZvoid dofile ();
ZZ
ZZmain (ac, av)
ZZint ac;
ZZchar **av;
ZZ{
ZZ register FILE *in = stdin; /* default is standard input */
ZZ
ZZ register int header = FALSE; /* TRUE if multiple files */
ZZ
ZZ register char *cp; /* general purpose pointer */
ZZ
ZZ register long nlines = 10; /* number of lines to display */
ZZ register long skip = 0; /* number of lines to skip */
ZZ
ZZ register char *pgm; /* program name */
ZZ
ZZ if (pgm = strrchr (av[0], '/')) pgm++;
ZZ else pgm = av[0];
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* Adjust args to skip program name */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ av++; ac--;
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* process arguments/options */
ZZ /* it is assumed that the options will precede all file names */
ZZ /* on the command line */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ while (ac)
ZZ {
ZZ if (*av[0] == '+') /* lines to skip */
ZZ {
ZZ skip = atoi (&av[0][1]);
ZZ ac--; av++;
ZZ }
ZZ else if (*av[0] == '-') /* lines to display */
ZZ {
ZZ nlines = atoi (&av[0][1]);
ZZ ac--; av++;
ZZ }
ZZ else break;
ZZ }
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* If any files, then process each */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ if (ac)
ZZ {
ZZ /* ------------------------------------------------------------ */
ZZ /* If more than one file name specified, display headers */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ header = ac > 1;
ZZ while (ac--)
ZZ {
ZZ if (!strcmp (*av, "-"))
ZZ {
ZZ dofile (stdin, "standard input", skip, nlines, header);
ZZ }
ZZ else if (!(in = fopen (*av, "r")))
ZZ {
ZZ fprintf (stderr,
ZZ "head: cannot read file %s - skipping\n", *av);
ZZ }
ZZ else
ZZ {
ZZ dofile (in, *av, skip, nlines, header);
ZZ fclose (in);
ZZ }
ZZ av++;
ZZ }
ZZ }
ZZ else dofile (stdin, "standard input", skip, nlines, FALSE);
ZZ
ZZ exit (0);
ZZ}
ZZ/* ------------------------------------------------------------ */
ZZ/* Process a file, skipping and displaying as necessary */
ZZ/* ------------------------------------------------------------ */
ZZvoid
ZZdofile (in, inname, skip, nlines, dohead)
ZZregister FILE *in; /* input stream */
ZZregister char *inname; /* input file name */
ZZregister long skip; /* number of lines to skip */
ZZregister long nlines; /* number of lines to display */
ZZ int dohead; /* TRUE if header is to be displayed */
ZZ{
ZZ register char *c; /* convenient local pointer */
ZZ register long lineno = 0; /* line number in file */
ZZ
ZZ char inbuf[1024]; /* line buffer */
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* Print header if necessary */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ if (dohead)
ZZ {
ZZ printf ("\
ZZ+-----------------------------------------------------------------+\n\
ZZ+ %-40.40s +\n\
ZZ+-----------------------------------------------------------------+\n",
ZZ inname);
ZZ }
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* Skip lines */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ while (lineno++ < skip && fgets (inbuf, sizeof inbuf, in));
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* Display lines */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ lineno = 0;
ZZ
ZZ while (lineno++ < nlines && fgets (inbuf, sizeof inbuf, in))
ZZ fputs (inbuf, stdout);
ZZ
ZZ return;
ZZ}
SHAR_EOF
if test 4938 -ne "`wc -c < 'head.c'`"
then
echo shar: error transmitting "'head.c'" '(should have been 4938 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ctags.c'" '(6771 characters)'
if test -f 'ctags.c'
then
echo shar: will not over-write existing file "'ctags.c'"
else
sed 's/^ZZ//' << \SHAR_EOF > 'ctags.c'
ZZ/*T ctags - generate VI tags file from C sources */
ZZ/*S globals and stuff */
ZZ#include <stdio.h>
ZZ#include <ctype.h>
ZZ
ZZ#define EQ ==
ZZ#define NE !=
ZZ#define GT >
ZZ#define GE >=
ZZ#define LT <
ZZ#define LE <=
ZZ#define OR ||
ZZ#define AND &&
ZZ
ZZ#define TRUE 1
ZZ#define FALSE 0
ZZ
ZZ#define SPACE ' '
ZZ#define NUL '\0'
ZZ
ZZtypedef short BOOL;
ZZ
ZZchar FunctionName[40];
ZZ
ZZchar *ReservedWord[] = {
ZZ "BOOL", "auto", "bool", "break", "case", "char", "continue",
ZZ "default", "do", "double", "else", "entry", "enum",
ZZ "extern", "float", "for", "goto", "if",
ZZ "int", "long", "register", "return", "short",
ZZ "sizeof", "static", "struct", "switch",
ZZ "typedef", "union", "unsigned", "void", "while",
ZZ NULL };
ZZ
ZZchar *pgm;
ZZchar inbuf[512];
ZZ
ZZextern char *strchr (); /* index on BSD */
ZZextern char *strrchr (); /* rindex on BSD */
ZZextern char *strpbrk (); /* ??? */
ZZ
ZZint skiptoend (); /* skip to end of function */
ZZchar ckfunc (); /* check for function declaration */
ZZ/*Page Eject*/
ZZmain (ac, av)
ZZint ac;
ZZchar *av[];
ZZ{
ZZ register FILE *in; /* input file stream */
ZZ register FILE *tagfile; /* `tags' file being created */
ZZ
ZZ register char *cp; /* convenient character pointers */
ZZ register char *ep; /* */
ZZ
ZZ register int i; /* loop index and such */
ZZ register int index = FALSE; /* if true, produce a functions */
ZZ /* index instead of tags file */
ZZ register int line_number = 0; /* line number of declaration */
ZZ register int optind = 1; /* like getopt - command arg */
ZZ
ZZ char *funcname; /* function name */
ZZ
ZZ char filename[15]; /* like it says */
ZZ
ZZ if (pgm = strrchr (av[0], '/')) pgm++;
ZZ else pgm = av[0];
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* Create the tags file */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ tagfile = fopen ("tags", "w");
ZZ if (!tagfile)
ZZ {
ZZ perror ("tags");
ZZ fprintf (stderr,
ZZ "%s: cannot create file tags\n", pgm);
ZZ exit (1);
ZZ }
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* If selected, write a function index to stdout instead */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ if (!strncmp (av[1], "-x", 2))
ZZ {
ZZ index = TRUE;
ZZ optind++;
ZZ }
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* Process each file specified on the command line */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ for (i = optind; i LT ac; i++)
ZZ {
ZZ if (!(in = fopen (av[i], "r")))
ZZ {
ZZ perror (av[i]);
ZZ fprintf (stderr,
ZZ "%s: unable to read file %s\n", pgm, av[i]);
ZZ }
ZZ else
ZZ {
ZZ while (fgets (inbuf, sizeof inbuf, in))
ZZ {
ZZ line_number++;
ZZ if (ckfunc (inbuf))
ZZ {
ZZ /* ------------------------------------------------------------ */
ZZ /* Found a function declaration */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ inbuf[strlen(inbuf)-1] = NUL;
ZZ if (index)
ZZ {
ZZ printf ("%-20.20s %6d %s\t%s\n",
ZZ FunctionName, line_number, av[i], inbuf);
ZZ }
ZZ /* ------------------------------------------------------------ */
ZZ /* Special case function name `main' */
ZZ /* ------------------------------------------------------------ */
ZZ else if (!strcmp (FunctionName, "main"))
ZZ {
ZZ cp = strrchr (av[i], '/');
ZZ if (cp) cp++;
ZZ else cp = av[i];
ZZ strcpy (filename, cp);
ZZ ep = strrchr (filename, '.');
ZZ if (ep) *ep = NUL;
ZZ fprintf (tagfile, "M%s\t%s\t?^%s$?\n",
ZZ filename, av[i], inbuf);
ZZ }
ZZ else
ZZ {
ZZ fprintf (tagfile, "%s\t%s\t?^%s$?\n",
ZZ FunctionName, av[i], inbuf);
ZZ }
ZZ line_number += skiptoend (in);
ZZ }
ZZ }
ZZ fclose (in);
ZZ }
ZZ }
ZZ fclose (tagfile);
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* Tags file must be sorted alphabetically on tag */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ system ("sort -u -t'\t' +0 -1 -o tags tags");
ZZ
ZZ exit (0);
ZZ}
ZZ/*S ckfunc - check line for function declaration */
ZZ/*H ckfunc */
ZZ/*E*/
ZZ
ZZ#define isidchr(c) (isalnum(c) OR (c EQ '_'))
ZZ
ZZchar
ZZckfunc (s)
ZZregister char *s; /* string to check for declaration */
ZZ{
ZZ register char *p; /* convenient character pointer */
ZZ register int i; /* useful loop index */
ZZ register int result; /* used to terminate search loop */
ZZ register char found = FALSE; /* true if declaration found */
ZZ
ZZ static char *_fnm = "ckfunc";
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* There's GOT to be a left paren for there to be a declaration */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ if (strchr (s, '('))
ZZ {
ZZ found = TRUE;
ZZ
ZZ while (found)
ZZ {
ZZ found = FALSE;
ZZ p = FunctionName;
ZZ for (s; isascii (*s) AND isspace (*s) AND *s; s++);
ZZ if( *s EQ '*' )
ZZ {
ZZ for (++s; isascii (*s) AND isspace (*s) AND *s; s++);
ZZ }
ZZ
ZZ if ((*s EQ '_') OR isalpha(*s))
ZZ {
ZZ while (isidchr (*s)) *p++ = *s++;
ZZ
ZZ *p = NUL;
ZZ
ZZ for (found = FALSE, i = 0;
ZZ !found AND ReservedWord[i]; i++)
ZZ {
ZZ if (!(result = strcmp (FunctionName, ReservedWord[i])))
ZZ found = TRUE;
ZZ else if (result LT 0) break;
ZZ }
ZZ }
ZZ }
ZZ }
ZZ
ZZ for (s; isascii (*s) AND isspace (*s) AND *s; s++);
ZZ
ZZ if (*s EQ '(')
ZZ {
ZZ for (found = FALSE; *s AND !found; s++)
ZZ found = *s EQ ')';
ZZ
ZZ if (found)
ZZ {
ZZ for (; *s AND isspace (*s); s++);
ZZ
ZZ found = *s NE ';';
ZZ }
ZZ }
ZZ
ZZ return found;
ZZ}
ZZ/* ------------------------------------------------------------ */
ZZ/* Skiptoend is called after a function declaration is found */
ZZ/* to skip to the end of the function. */
ZZ/* ------------------------------------------------------------ */
ZZint
ZZskiptoend (in)
ZZregister FILE *in; /* file being processed */
ZZ{
ZZ register int nest = 0; /* nesting level - zero means end */
ZZ register int c; /* character being checked */
ZZ register int line_number = 0; /* like it says */
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* Simpleminded search for the starting brace */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ while (((c = getc (in)) NE EOF) AND c NE '{')
ZZ if (c EQ '\n') line_number++;
ZZ
ZZ nest++;
ZZ
ZZ /* ------------------------------------------------------------ */
ZZ /* Keep going until the paired brace is found */
ZZ /* ------------------------------------------------------------ */
ZZ
ZZ while (nest AND ((c = getc (in)) NE EOF))
ZZ {
ZZ switch (c)
ZZ {
ZZ case '{': nest++; break;
ZZ case '}': nest--; break;
ZZ case '\n': line_number++;
ZZ }
ZZ }
ZZ
ZZ return line_number;
ZZ}
SHAR_EOF
if test 6771 -ne "`wc -c < 'ctags.c'`"
then
echo shar: error transmitting "'ctags.c'" '(should have been 6771 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
More information about the Mod.sources
mailing list