[comp.sources.unix] v11i078: C cross-reference database system, Part01/03

rsalz@uunet.UU.NET (Rich Salz) (09/26/87)

Submitted-by: sun!suneast!kumquat!gmcgary (Greg Mcgary - Sun ECD Software)
Posting-number: Volume 11, Issue 78
Archive-name: id/Part01

This is a program identifier database package.  These tools provide a
logical extension to ctags. (which is limited in that it only stores the
location of function and type *definitions*).  The ID facility stores the
locations for all uses of identifiers, pre-processor names, and numbers
(in decimal, octal or hex).  The id-database is most useful for
maintaining large programs that consist of many source files.  The
database is simply a two dimensional boolean array indexed by
identifier-name and source-file-name.  For a given identifier and
source-file, if the identifier occurs in the file, the boolean value is
TRUE.  The database may be queried either by identifier-name or
file-name.


#! /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:
#	TUTORIAL
#	TODO
#	makefile
#	bitops.h
#	bool.h
#	extern.h
#	id.h
#	patchlevel.h
#	radix.h
#	string.h
#	lid.1
#	mkid.1
export PATH; PATH=/bin:$PATH
echo shar: extracting "'TUTORIAL'" '(16037 characters)'
sed 's/^X//' << \SHAR_EOF > 'TUTORIAL'
X
XThis is a program identifier database package.  These tools provide a
Xlogical extension to ctags. (which is limited in that it only stores the
Xlocation of function and type *definitions*a)  The ID facility
Xstores the locations for all uses of identifiers, pre-processor
Xnames, and numbers. (in decimal, octal or hex)
X
XWhen fixing or enhancing a large program (particularly one that is
Xunfamiliar) it is often necessary to audit the use of global
Xdata-structures in order to verify that the proposed modification will
Xnot trigger any hidden `gotchas'.  Often this entails grepping through
Xmany thousands of lines of source code spread over dozens and sometimes
Xhundreds of source files in multiple sub-directories.  This process
Xplaces a significant load on computing resources, and takes a long
Xtime.  There is even the danger that a programmer will avoid doing a
Xcomplete audit due to the perceived cost--he or she will rely on memory
Xand hope that there are no booby traps.
X
XThe id-database is most useful for maintaining large programs that
Xconsist of many source files.  The database is simply a two dimensional
Xboolean array indexed by identifier-name and source-file-name.  For a
Xgiven identifier and source-file, if the identifier occurs in the file,
Xthe boolean value is TRUE.  The database may be queried either by
Xidentifier-name or file-name.
X
XThe following types of queries supported:
X
X* name lookup
X	list all the files where an identifier occurs.  The name
X	may be a regular expression.
X
X* name apropos
X	list all the files for all identifiers that have the sub-string
X	name in them.  Matches are done in a case-insensitive mammer.
X
X* name `grep'
X	search for an identifier in all the files where it occurs.
X	This is an optimized `grep' over all the sources--we only
X	search on files that contain the identifier.
X
X* name edit
X	invoke an editor on the files where an identifier occurs,
X	and use the identifier as an initial search string.
X
X* file lookup
X	list all identifiers that occur in a file, or list
X	the identifiers that are common between two files.
X
X* non-unique names
X	list the names of all indentifiers whose names are non-unique
X	within some number of characters.  This is useful when porting
X	a program from a `flexnames' system to one more limited names.
X
X* solo
X	list all identifiers that occur exactly once in a software
X	system.  This may be useful for locating identifiers that are
X	declared but never used, or library functions that are used
X	but never declared.
X	
X
XThe first four queries are handled by one program.  The type of query
Xis determined by the name the program was invoked with.  The four links
Xare lid(1) for `lookup id', aid(1) for `apropos id', gid(1) for `grep
Xid' and eid(1) for `edit id'.  One or more identifiers may be passed on
Xthe command line.  The identifiers may be literal strings or regular
Xexpressions.  Here are some examples:
X
X$ lid FILE
XFILE           extern.h {fid,gets0,getsFF,idx,init,lid,mkid,opensrc,scan-asm,scan-c}.c
X
X$ lid FILE$
XAF_FILE        mkid.c
XAF_IDFILE      mkid.c
XFILE           extern.h {fid,gets0,getsFF,idx,init,lid,mkid,opensrc,scan-asm,scan-c}.c
XIDFILE         id.h {fid,lid,mkid}.c
XIdFILE         {fid,lid}.c
XargFILE        mkid.c
XgidFILE        lid.c
XidFILE         {init,mkid}.c
XinFILE         {gets0,getsFF,scan-asm,scan-c}.c
XopenSrcFILE    extern.h {idx,mkid,opensrc}.c
XsrcFILE        {idx,mkid,opensrc}.c
X
X$ lid ^get
Xget            opensrc.c
XgetAdaId       getscan.c
XgetAsmId       extern.h {getscan,scan-asm}.c
XgetCId         extern.h {getscan,scan-c}.c
XgetDirToName   extern.h {fid,lid,paths}.c
XgetId          {idx,mkid}.c
XgetLanguage    extern.h {getscan,idx,mkid}.c
XgetLispId      getscan.c
XgetPascalId    getscan.c
XgetRoffId      getscan.c
XgetSCCS        extern.h opensrc.c
XgetScanner     extern.h {getscan,idx,mkid}.c
XgetTeXId       getscan.c
XgetTextId      getscan.c
Xgetc           {gets0,getsFF,lid,scan-asm,scan-c}.c
Xgetchar        lid.c
Xgetenv         extern.h lid.c
Xgets           lid.c
XgetsFF         extern.h {bitsvec,fid,getsFF,lid,mkid}.c
X
XAs you can see, when a regular expression is used, it is possible to
Xget more than one line of output.  If you wish multiple lines to be
Xmerged into one, supply the `-m' option:
X
X$ lid -m ^get
X^get           extern.h {bitsvec,fid,gets0,getsFF,getscan,idx,lid,mkid,opensrc,paths,scan-asm,scan-c}.c
X
XThe query program searches for numbers numerically rather than
Xtextually.  Therefore you may search for multiple representations of a
Xnumber.  It is best to illustrate this with examples:
X
X$ lid -a 0x10
X020            numtst.c
X0x00010        numtst.c
X0x0010         scan-c.c
X0x10           {id,radix}.h {scan-asm,stoi}.c
X16             numtst.c
X
XThe `-a' argument tells lid(1) to look for 0x10 in all radixes.  (For
Xnumbers 0 through 7, lid(1) looks for all radixes by default.  For numbers
Xgreater than 7, lid(1) only looks for the radix that the argument is
Xsupplied in.) It is also possible to restrict the search to selected
Xradixes by supplying an argument consisting of one or more of the
Xkey-letters `o', `d', and `x' for octal decimal and hexadecimal
Xrespectively:
X
X$ lid -o 0x10
X020            numtst.c
X
X$ lid -x 16
X0x00010        numtst.c
X0x0010         scan-c.c
X0x10           {id,radix}.h  {scan-asm,stoi}.c
X
X$ lid -d 020
X16             numtst.c
X
X
XThe grep interface behaves somewhat like the following command:
X
X$ grep -w -n `lid TRUE`
X
XHeres some sample output for the equivalent gid command:
X
X$ gid TRUE
Xbool.h:5: #define	TRUE	(0==0)
Xlid.c:102: 		case 'm': forceMerge = TRUE; break;
Xlid.c:170: 			Merging = TRUE;
Xlid.c:204: 			crunching = TRUE;
Xlid.c:553: 			hitDigits = TRUE;
Xlid.c:787: 			return TRUE;
Xmkid.c:117: 			Verbose = TRUE;
Xmkid.c:191: 					keepLang = TRUE;
Xscan-asm.c:79: static bool eatUnder = TRUE;
Xscan-asm.c:80: static bool preProcess = TRUE;
Xscan-asm.c:96: 	static bool	newLine = TRUE;
Xscan-asm.c:130: 		newLine = TRUE;
Xscan-asm.c:141: 		newLine = TRUE;
Xscan-asm.c:145: 		newLine = TRUE;
Xscan-asm.c:150: 		newLine = TRUE;
Xscan-asm.c:165: 				newLine = TRUE;
Xscan-c.c:88: static bool eatUnder = TRUE;
Xscan-c.c:101: 	static bool	newLine = TRUE;
Xscan-c.c:138: 		newLine = TRUE;
Xscan-c.c:199: 				newLine = TRUE;
Xscan-c.c:205: 		newLine = TRUE;
Xscan-c.c:210: 			newLine = TRUE;
Xwmatch.c:37: 			return TRUE;
X
XNotice that each line is reported in the same format as a
XC-preprocessor error message.  This feature allows gid(1) lines to be
Xdigested by any program that parses error messages, such as error(1)
Xand gnu-emacs.
X
XIf you want to edit all files that have an identifier, you may
Xconveniently do so with eid(1):
X
X$ eid TRUE
XTRUE           bool.h {lid,mkid,scan-asm,scan-c,wmatch}.c
XEdit? [y1-9^S/nq] 
X
XBefore the editor is invoked, you are given the lid(1) output to review
Xand comfirm.  If you want to edit all files listed, respond with a
Xnewline or with `y'.  If you want to skip some number of files into the
Xargument list, respond with a single digit `1' through `9' to skip that
Xmany files, or do a string-search to the first file you want with
X`^S<string>' or `/<string>'.  If you don't want to edit anything, type
X`n' to go on to the next argument you gave to eid(1) or type `q' to
Xquit altogether.
X
XThe behavior of the editing interface is controlled by three
Xenvironment variables called EIDARG, EIDLDEL, and EIDRDEL.  The best
Xway to illustrate their use by an example.  Here is how to define them
Xfor vi(1) (using /bin/sh syntax)
X
XEIDARG='+/%s/'	# printf(3) string for initial search-string argument
XEIDLDEL='\<'	# left word-delimiter
XEIDRDEL='\>'	# right word-delimiter
X
X`EID[LR]DEL' are positioned around the identifier as left and right
Xword-delimiters if your editor supports that notion.  Then the whole
Xname-string is sprintf(3)'ed into `EIDARG' to construct the initial
Xsearch-string argument to the editor.  If your editor can't digest such
Xan argument, simply leave these variables undefined in the
Xenvironment.
X
XSome emacs users are appalled at the notion of starting up a fresh editor
Xsimply to follow an identifier.  For those who are fortunate enough to have
Xa programmable emacs such as gnu-emacs, it is fairly simple to devise
Xa command that invokes gid(1) and digests its output as though it were
X/lib/cpp error strings to be examined.  (Sorry, no such code is provided
Xat this posting...)
X
XAnother type of query is to find all identifiers that are non-unique
Xwithin some number of characters.  This is useful for finding potential
Xportability problems when moving to a system whose compiler or linker
Xlimits the number of significant characters in a name.  The `-u<n>'
Xargument does the trick.  Here's a list of identifiers that may yield
Xmultiply-defined errors in a symbol table that only knows about the
Xfirst 7 characters:
X
X$ lid -u7
XSCAN_TEX       getscan.c
XSCAN_TEXT      getscan.c
Xidh_argc       id.h {init,mkid}.c
Xidh_argo       id.h {init,mkid}.c
Xidh_namc       id.h {fid,mkid}.c
Xidh_namo       id.h {fid,init,lid,mkid}.c
XoldHashSize    mkid.c
XoldHashTable   mkid.c
X
XBetter yet, if you want to edit these, try
X
X$ eid -u7
X^SCAN_TE       getscan.c
XEdit? [y1-9^S/nq] n
X^idh_arg       getscan.c id.h {init,mkid}.c
XEdit? [y1-9^S/nq] n
X^idh_nam       {fid,getscan}.c id.h {init,lid,mkid}.c
XEdit? [y1-9^S/nq] n
X^oldHash       {fid,getscan}.c id.h {init,lid,mkid}.c
XEdit? [y1-9^S/nq] n
X
X
XAn additional feature of lid(1) is that pathnames are automatically
Xadjusted for the current working directory.  Large programs such as the
XUNIX kernel are often partitioned into subsystems whose sources live in
Xdifferent directories.  What follows are several examples of the same
Xsearch conducted from different points in the UNIX kernel source
Xhierarchy:
X
X$ cd /src/uts/m68k
X$ lid bdevsw
Xbdevsw         sys/conf.h  cf/conf.c  io/bio.c  os/{fio,main,prf,sys3}.c
X
X$ cd io
X$ lid bdevsw
Xbdevsw         ../sys/conf.h  ../cf/conf.c  bio.c  ../os/{fio,main,prf,sys3}.c
X
X$ cd ../os
Xbdevsw         ../sys/conf.h  ../cf/conf.c  ../io/bio.c  {fio,main,prf,sys3}.c
X
XThe database is built with mkid(1).  The user supplies pathnames
Xeither on the command line or on stdin.  Here's the output of the
X`verbose' option to mkid(1):
X
X$ mkid -v *.h *.c
Xc: bitops.h
Xc: bool.h
Xc: extern.h
Xc: id.h
Xc: patchlevel.h
Xc: radix.h
Xc: string.h
Xc: basename.c
Xc: bitcount.c
Xc: bitops.c
Xc: bitsvec.c
Xc: bsearch.c
Xc: bzero.c
Xc: document.c
Xc: fid.c
Xc: gets0.c
Xc: getsFF.c
Xc: getscan.c
Xc: hash.c
Xc: idx.c
Xc: init.c
Xc: lid.c
Xc: mkid.c
Xc: numtst.c
Xc: opensrc.c
Xc: paths.c
Xc: scan-asm.c
Xc: scan-c.c
Xc: stoi.c
Xc: tty.c
Xc: uerror.c
Xc: wmatch.c
XCompressing Hash Table...
XSorting Hash Table...
XWriting `ID'...
XNames: 593, Numbers: 64, Strings: 43, Solo: 119, Total: 697
XOccurrances: 11.67, Load: 0.17, Probes: 1.07
X
XMkid(1) echoes the name of each file as it is scanned, prefixed by the
Xname of the language it thinks the file is written in.  Mkid(1) reports
Xhow many unique names and numbers were found, how many names occurred
Xonly once, and the total for names and numbers.  It also reports the
Xaverage number of occurrances for all names and numbers.  Next, there
Xare some hash-table statistics on the load-factor and the average
Xnumber of open-addressed probes.
X
XMkid(1) can take arguments from the command line, from stdin, or from
Xa file.  A file full of filenames may also contain mkid options of the form
X-<option>.  Filenames and options appear in the file one-per-line.  Typical
Xusage for this feature is as follows:
X
X$ find . -name '*.[chys]' -print >IDFILES
X$ mkid -aIDFILES
X
X-- or --
X
X$ find . -name '*.[chys]' -print |mkid -
X
XMkid(1) stashes the filenames and relevant arguments in the database
Xitself.  It uses these to support the ``incremental-update' option.
XIf invoked with `-u', mkid(1) checks the modification times of all
Xconstituent files, and only re-scans those that are newer than the
Xdatabase itself.  It is invoked like so:
X
X$ mkid -u
X
XIn summation, mkid(1) can get arguments from one of four places:
X1) the command line, 2) a file, 3) stdin, 4) the database itself.
X
XMkid(1) accepts a number of scanner-specific arguments.  Generally,
Xthese are introduced with `-S<lang>' where <lang> is the name of
Xa language, such as `c' or `asm'.  You can get a scanner-specific
Xusage-report with `-S<lang>?'  (Of course, the `?' must be escaped
Xto get it past the shell)
X
XHere's scanner-usage for the assembly language scanner:
X
X$ mkid -Sasm\?
XThe Assembler scanner arguments take the form -Sasm<arg>, where
X<arg> is one of the following: (<cc> denotes one or more characters)
X  -c<cc> . . . . <cc> introduce(s) a comment until end-of-line.
X  (+|-)u . . . . (Do|Don't) strip a leading `_' from ids.
X  (+|-)a<cc> . . Allow <cc> in ids, and (keep|ignore) those ids.
X  (+|-)p . . . . (Do|Don't) handle C-preprocessor directives.
X  (+|-)C . . . . (Do|Don't) handle C-style comments. (/* */)
X
X`-Sasm-c<cc>' tells the scanner what characters are used to introduce comments
Xthat extend to end-of-line.
X
XUse `-Sasm+u' if your C compiler prepends leading underscores to external
Xnames.  This way, mkid(1) will strip leading underscores, and the name
X`foo' in a C source will be correctly associated with the name `_foo'
Xin an assembler source.  If your compiler doesn't prepend leading
Xunderscores, use `-Sasm-u'.
X
XMany assemblers allow special characters to be mixed with
Xalpha-numerics in label, constant and register names.  Common choices
Xare `.', `%', and `$'.  Thus, a label such as `L%123' should be scanned
Xas one token, not broken up into the name `L' and the number 123.
X`-Sasm-a%.' tells the scanner to allow `%' and `.' in tokens, but to throw
Xaway tokens containing `%' or `.' `-Sasm+a%.' tells the scanner to keep such
Xtokens and put them into the database.
X
X
X`-Sasm+p' tells the scanner to handle `#include' and `#define' lines as
Xin C source, and `-Sasm+C' tells it to ignore C-style comments.
X
XHere's the scanner-usage for C:
X
X$ mkid -Sc\?
XThe C scanner arguments take the form -Sc<arg>, where <arg>
Xis one of the following: (<cc> denotes one or more characters)
X  (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.
X  -s<cc> . . . . Allow <cc> in string ids.
X
XThe `+u' argument is akin to the argument for the assembly-language
Xscanner.  Mkid(1) keeps the contents of quoted-strings if the string
Xcontains a single valid C name and nothing else.  E.g.  mkid(1) would
Xkeep the contents of "_proc".  Such strings are interesting because
Xthey may contain symbol names that a program uses for nlist lookups.
XSo, if your compiler prepends underscores to external symbols, use
X`-Sc+u' so that mkid(1) will strip them back off.
X
XMkid(1) normally throws away the contents of quoted strings that have
Xanything other than a single name in them.  You can tell mkid(1) to
Xaccept additional characters in strings with `-Sc-s<cc>' where <cc> is
Xone or more special characters.  E.g. `-Sc-s/.-:,' will include most of
Xthe strings containing pathnames that you are likely to encounter.
X
XAnother class of scanner argument allows you to associate a suffix
Xwith a language.  E.g. `-S.y=c' tells mkid(1) to use the C language
Xscanner on all files ending with .y.  You can ask mkid(1) for the
Xavailable scanners and associated suffixes like so:
X
X$ mkid -S\?=\?
X.c=c, .h=c, .y=c, .s=asm, .p=pascal, .pas=pascal
X
XPlease note, mkid(1) is lying to you about its Pascal prowess!
XAt the time of this posting, there are scanners for C and assembly
Xlanguage sources.  There are also stubs for Pascal, Ada and LISP.  The
Xscanners are very fast.  The assembly language scanner knows how
Xto throw away C-style comments as well as the traditional `comment-
Xcharacter-until-end-of-line' style.  In order to test new scanners,
Xthere is a scanner driver called idx(1).  Idx(1) simply calls the
Xscanner to get identifiers one-at-a-time prints them on stdout one-per-line.
X
XFor more information, read the manual pages!
X
XHappy Hacking,
X--
X-- Greg McGary
X-- P.O. Box 286
X-- Lincoln, MA  01773
X--
X-- 9/15/87
X--
X--	Until the end of 1987,
X--	Consulting to Sun's East Coast Division:
X--		gmcgary@ecd.sun.com
X--		gmcgary@suneast.uu.net
X--
X--	After that, probably consulting in Europe...
SHAR_EOF
if test 16037 -ne "`wc -c < 'TUTORIAL'`"
then
	echo shar: error transmitting "'TUTORIAL'" '(should have been 16037 characters)'
fi
echo shar: extracting "'TODO'" '(546 characters)'
sed 's/^X//' << \SHAR_EOF > 'TODO'
XEnhancements:
X~~~~~~~~~~~~~
Xmkid:
X	handle attributes: IDN_NOISE
X	add makefile scanner
X
Xgetid-c:
X	add stuff to recognize float & double constants properly.
X
X[lgea]id:
X	recursively search sub-dirs for ID databases and optionally
X		merge everything into one BIG list
Xlid:
X	print attribute flags, add cmd-line args to query by flags
X	break out searching junk into lib-funcs that are useful to editors
X
XNew Applications:
X~~~~~~~~~~~~~~~~~
Xignid:
X	frob the IDN_NOISE attribute of an id in an existing ID database.
X		takes ids on command line or stdin.
SHAR_EOF
if test 546 -ne "`wc -c < 'TODO'`"
then
	echo shar: error transmitting "'TODO'" '(should have been 546 characters)'
fi
echo shar: extracting "'makefile'" '(3516 characters)'
sed 's/^X//' << \SHAR_EOF > 'makefile'
X#!/bin/make -f
X
X# Copyright (c) 1986, Greg McGary
X# @(#)makefile	1.3 86/11/06
X
X# --------------------------------------------------------------------
X# System Dependent Configuration:
X#   Choose a pre-packaged set of options below, or roll your own.
X#   The relevant options are as follows:
X#
X# * If you have the `PW' library which includes the regular-expression
X#   funcions regcmp(3) and regex(3), then use `-DREGEX' in DEFS, and
X#   `-lPW' in LIBS.  If you have the regular-expression functions
X#   re_comp(3) and re_exec(3), use `-DRE_EXEC' in DEFS.  If you don't
X#   have any regular-expression functions, don't add either to DEFS.
X#
X# * If you do not have the 4.2 directory access libraries, add `-lndir'
X#   to LIBS, and define `-DNDIR' in DEFS. 
X#
X# * If your string libraries have index(3) and rindex(3) instead of
X#   strchr(3) and strrchr(3), use `-DRINDEX' in DEFS.
X#
X# * If your compiler chokes on pointers to functions returning void,
X#   use `-Dvoid=int' in DEFS.
X#
X# * If you have setlinebuf(3) in your stdio to set line-buffering on
X#   a stream, use `-DERRLINEBUF' in DEFS.
X#
X# * If you have a System-III/V terminal driver, define `TERMIO' in DEFS.
X#
X# * If you have ranlib(1), define `RANLIB' as such.  If you don't have
X#   it, set `RANLIB' to something harmless like `@:', or `echo'
X# --------------------------------------------------------------------
X
X# DEFS	=	-DREGEX -DNDIR -DTERMIO	# typical System-V defs
X# DEFS	=	-Dvoid=int -DRINDEX -DRE_EXEC -DNDIR	# typical V7 defs
XDEFS	=	-Dvoid=int -DRINDEX -DRE_EXEC -DERRLINEBUF	# BSD defs
X
X# LIBS	=	-lndir -lPW	# typical System-V libs
X# LIBS	=	-lndir	# typical V7 libs
XLIBS	=	# typical BSD libs (none)
X
X#RANLIB	=	@:	# system doesn't have ranlib (Sys-V)
XRANLIB	=	ranlib	# system has ranlib (typically V7 & BSD)
X
X# --------------------------------------------------------------------
X# Compilation / Loading options:
X#   Choose options to generate a system as an installed product,
X#   for debugging, or for performance profiling.
X# --------------------------------------------------------------------
X
X# CCFLG	=	-g -DDEBUG 	# debugging
X# CCFLG	=	-p	# profiling
XCCFLG	=	-O	# production
X
X# LDFLG	=	-g	# debugging
X# LDFLG	=	-p	# profiling
XLDFLG	=	# production
X
X# --------------------------------------------------------------------
X
XSHELL =		/bin/sh
XTARGETS =	libid.a $(PROGS)
XPROGS =		mkid lid idx fid $(LIDLINKS)
XDESTINATION_DIR = /usr/local
X
XLIDLINKS = 	gid aid eid
XCFLAGS =	$(CCFLG) -I. $(DEFS)
XLDFLAGS =	$(LDFLG) libid.a $(LIBS)
X
XOFILES =	init.o getscan.o scan-c.o scan-asm.o bsearch.o hash.o \
X		bitops.o basename.o gets0.o getsFF.o paths.o opensrc.o \
X		stoi.o uerror.o document.o bitcount.o wmatch.o bitsvec.o \
X		tty.o bzero.o
X
X# --------------------------------------------------------------------
X
Xall:		$(TARGETS)
X
Xlibid.a:	$(OFILES)
X		ar rv $@ $?
X		$(RANLIB) $@
X
Xmkid:		mkid.o libid.a
X		$(CC) -o $@ $@.o $(LDFLAGS)
X
Xfid:		fid.o libid.a
X		$(CC) -o $@ $@.o $(LDFLAGS)
X
Xlid:		lid.o libid.a
X		$(CC) -o $@ $@.o $(LDFLAGS)
X
Xidx:		idx.o libid.a
X		$(CC) -o $@ $@.o $(LDFLAGS)
X
X$(LIDLINKS): lid
X		-/bin/rm -f $@
X		ln lid $@
X
Xinstall:	$(PROGS)
X		mv $(PROGS) $(DESTINATION_DIR)
X
Xclean:
X		rm -f $(TARGETS) *.o
X
Xid.tar:
X		cd ..; tar cvbf 20 id/id.tar id/*.[ch1-8] id/makefile id/TODO id/TUTORIAL
X
Xid.tar.Z:	id.tar
X		compress -b 14 <id.tar >id.tar.Z
X
Xid.shar:	id.shar-1 id.shar-2 id.shar-3
X
Xid.shar-1:
X		shar $(SHARFLAGS) TUTORIAL TODO makefile *.h *.[1-8] >$@
X
Xid.shar-2:
X		shar $(SHARFLAGS) [a-l]*.c >$@
X
Xid.shar-3:
X		shar $(SHARFLAGS) [m-z]*.c >$@
SHAR_EOF
if test 3516 -ne "`wc -c < 'makefile'`"
then
	echo shar: error transmitting "'makefile'" '(should have been 3516 characters)'
fi
echo shar: extracting "'bitops.h'" '(537 characters)'
sed 's/^X//' << \SHAR_EOF > 'bitops.h'
X/* Copyright (c) 1986, Greg McGary */
X/* @(#)bitops.h	1.1 86/10/09 */
X
X#define	BITTST(ba, bn)	((ba)[(bn) >> 3] &  (1 << ((bn) & 0x07)))
X#define	BITSET(ba, bn)	((ba)[(bn) >> 3] |= (1 << ((bn) & 0x07)))
X#define	BITCLR(ba, bn)	((ba)[(bn) >> 3] &=~(1 << ((bn) & 0x07)))
X#define	BITAND(ba, bn)	((ba)[(bn) >> 3] &= (1 << ((bn) & 0x07)))
X#define	BITXOR(ba, bn)	((ba)[(bn) >> 3] ^= (1 << ((bn) & 0x07)))
X
Xextern char *bitsand();
Xextern char *bitsclr();
Xextern char *bitsset();
Xextern char *bitsxor();
Xextern int bitsany();
Xextern int bitstst();
SHAR_EOF
if test 537 -ne "`wc -c < 'bitops.h'`"
then
	echo shar: error transmitting "'bitops.h'" '(should have been 537 characters)'
fi
echo shar: extracting "'bool.h'" '(128 characters)'
sed 's/^X//' << \SHAR_EOF > 'bool.h'
X/* Copyright (c) 1986, Greg McGary */
X/* @(#)bool.h	1.1 86/10/09 */
X
Xtypedef	int	bool;
X#define	TRUE	(0==0)
X#define	FALSE	(0!=0)
SHAR_EOF
if test 128 -ne "`wc -c < 'bool.h'`"
then
	echo shar: error transmitting "'bool.h'" '(should have been 128 characters)'
fi
echo shar: extracting "'extern.h'" '(1260 characters)'
sed 's/^X//' << \SHAR_EOF > 'extern.h'
X/* Copyright (c) 1986, Greg McGary */
X/* @(#)extern.h	1.1 86/10/09 */
X
X/* miscellaneous external declarations */
X
Xextern FILE *initID();
Xextern FILE *openSrcFILE();
Xextern char *(*getScanner())();
Xextern char *basename();
Xextern char *bsearch();
Xextern char *calloc();
Xextern char *coRCS();
Xextern char *dirname();
Xextern char *getAsmId();
Xextern char *getCId();
Xextern char *getDirToName();
Xextern char *getLanguage();
Xextern char *getSCCS();
Xextern char *getenv();
Xextern char *hashSearch();
Xextern char *intToStr();
Xextern char *malloc();
Xextern char *regcmp();
Xextern char *regex();
Xextern char *rootName();
Xextern char *skipJunk();
Xextern char *spanPath();
Xextern char *suffName();
Xextern char *uerror();
Xextern int bitCount();
Xextern int bitsCount();
Xextern int bitsToVec();
Xextern int canCrunch();
Xextern int dtoi();
Xextern int fgets0();
Xextern int getsFF();
Xextern int h1str();
Xextern int h2str();
Xextern int strToInt();
Xextern int otoi();
Xextern int radix();
Xextern int stoi();
Xextern int vecToBits();
Xextern int wordMatch();
Xextern int xtoi();
Xextern void bzero();
Xextern void document();
Xextern void filerr();
Xextern void setAsmArgs();
Xextern void setCArgs();
Xextern void setScanArgs();
Xextern void skipFF();
X
Xextern char *MyName;
Xextern int errno;
SHAR_EOF
if test 1260 -ne "`wc -c < 'extern.h'`"
then
	echo shar: error transmitting "'extern.h'" '(should have been 1260 characters)'
fi
echo shar: extracting "'id.h'" '(1716 characters)'
sed 's/^X//' << \SHAR_EOF > 'id.h'
X/* Copyright (c) 1986, Greg McGary */
X/* @(#)id.h	1.1 86/10/09 */
X
X#define	IDFILE	"ID"
X
Xstruct idhead {
X	char	idh_magic[2];	/* magic number */
X#define	IDH_MAGIC "\311\304"	/* magic-number ("ID" with hi bits) */
X	short	idh_vers;	/* id-file version number */
X#define	IDH_VERS	2	/* current version */
X	int	idh_argc;	/* # of args for mkid update */
X	int	idh_pthc;	/* # of paths for mkid update */
X	int	idh_namc;	/* # of identifiers */
X	int	idh_vecc;	/* # of bytes in a path vector entry */
X	int	idh_bsiz;	/* # of bytes in entry (bufsiz for lid) */
X	long	idh_argo;	/* file offset of args for mkid update */
X	long	idh_namo;	/* file offset of identifier names */
X	long	idh_endo;	/* file offset of EOF */
X};
X
Xstruct idarg {
X	struct idarg	*ida_next;
X	char	*ida_arg;
X	int	ida_index;
X	char	ida_flags;
X#define	IDA_ADJUST	0x01
X#define	IDA_SCAN	0x02
X#define	IDA_PATH	0x04
X#define	IDA_ARG		0x08
X#define	IDA_BLANK	0x10
X};
X
Xstruct idname {
X	char	*idn_name;
X	char	*idn_bitv;
X	char	idn_flags;
X#define	IDN_SOLO	0x01	/* occurs only once */
X#define	IDN_NUMBER	0x02	/* is a number */
X#define	IDN_NAME	0x04	/* is a name */
X#define	IDN_STRING	0x08	/* is a string */
X#define	IDN_LITERAL	0x10	/* occurs as a literal (not string) */
X#define	IDN_NOISE	0x20	/* occurs very frequently */
X};
X
X/*
X	Extract the various logical fields of a name:
X
X	NAME: null-terminated ascii string
X	TAG:  index of name within a sorted array of all names
X	SOLO: boolean indicating that this name occurs exactly once
X*/
X#define	ID_PATHS(b) ((b)+strlen(b)+1)
X#define	ID_FLAGS(b) (*(b))
X#define	ID_STRING(b) ((b)+1)
X
X#define	NEW(type)	((type *)calloc(1, sizeof(type)))
X
X#define	GETARG(argc, argv)	((argc)--, *(argv)++)
X#define	UNGETARG(argc, argv)	((argc)++, *--(argv))
SHAR_EOF
if test 1716 -ne "`wc -c < 'id.h'`"
then
	echo shar: error transmitting "'id.h'" '(should have been 1716 characters)'
fi
echo shar: extracting "'patchlevel.h'" '(21 characters)'
sed 's/^X//' << \SHAR_EOF > 'patchlevel.h'
X#define PATCHLEVEL 0
SHAR_EOF
if test 21 -ne "`wc -c < 'patchlevel.h'`"
then
	echo shar: error transmitting "'patchlevel.h'" '(should have been 21 characters)'
fi
echo shar: extracting "'radix.h'" '(225 characters)'
sed 's/^X//' << \SHAR_EOF > 'radix.h'
X/* Copyright (c) 1986, Greg McGary */
X/* @(#)radix.h	1.1 86/10/09 */
X
X#define	RADIX_DEC	(1 << (10 - 1))
X#define	RADIX_OCT	(1 << (010 - 1))
X#define	RADIX_HEX	(1 << (0x10 - 1))
X#define	RADIX_ALL	(RADIX_DEC|RADIX_OCT|RADIX_HEX)
SHAR_EOF
if test 225 -ne "`wc -c < 'radix.h'`"
then
	echo shar: error transmitting "'radix.h'" '(should have been 225 characters)'
fi
echo shar: extracting "'string.h'" '(525 characters)'
sed 's/^X//' << \SHAR_EOF > 'string.h'
X/* Copyright (c) 1986, Greg McGary */
X/* @(#)string.h	1.1 86/10/09 */
X
X#ifdef RINDEX
X#define	strchr	index
X#define	strrchr	rindex
X#endif
X
Xextern char
X	*strcpy(),
X	*strncpy(),
X	*strcat(),
X	*strncat(),
X	*strchr(),
X	*strrchr(),
X	*strpbrk(),
X	*strtok();
X
Xextern long
X	strtol();
X
Xextern char	*calloc();
X
X#define	strequ(s1, s2)		(strcmp((s1), (s2)) == 0)
X#define	strnequ(s1, s2, n)	(strncmp((s1), (s2), (n)) == 0)
X#define	strsav(s)		(strcpy(calloc(1, strlen(s)+1), (s)))
X#define	strnsav(s, n)		(strncpy(calloc(1, (n)+1), (s), (n)))
SHAR_EOF
if test 525 -ne "`wc -c < 'string.h'`"
then
	echo shar: error transmitting "'string.h'" '(should have been 525 characters)'
fi
echo shar: extracting "'lid.1'" '(4020 characters)'
sed 's/^X//' << \SHAR_EOF > 'lid.1'
X.TH LID 1
X.SH NAME
Xlid, gid, eid \- query id database
X.SH SYNOPSIS
X.B lid
X.RB [ \-f \^file]
X.RB [ \-u \^n]
X.RB [ \-edoxamse]
Xpatterns...
X.PP
X.B gid
X.RB [ \-f \^file]
X.RB [ \-edoxamse]
Xpatterns...
X.PP
X.B eid
X.RB [ \-f \^file]
X.RB [ \-doxamse]
Xpatterns...
X.PP
X.B aid
X.RB [ \-f \^file]
X.RB [ \-doxams]
Xpatterns...
X.SH DESCRIPTION
XThese commands provide a flexible query interface to the
X.I id
Xdatabase.
X.I Lid\^
Xdoes a lookup on
X.IR patters
Xand prints out lines in this way:
X.PP
X.nf
Xidname        ../hdir/hfile.h ../cdir/{cfile1,cfile2}.c
X.fi
X.PP
XNotice that multiple files with the same directory prefix
Xand suffix are concatenated in the globbing-set-notation of
X.IR csh (1).
XAlso notice that all of the
X.I id
Xdatabase query commands adjust the list of pathnames to be relative
Xto your current working directory, provided that
X.IR mkid (1)
Xwas used to build the database, and your working directory
Xis located within the sub-tree covered by the
X.I id
Xdatabase.
X.PP
XIf multiple names match on pattern, then there will be one line
Xof output per name.  The mnemonic significance of the name is
X\fI\|l(ookup) id\fP.
X.PP
X.I Gid
Xdoes a lookup and then searches for the names it matches in the
Xfiles where they occur.  The mnemonic for this name is
X\fI\|g(rep)id\fP. 
X.PP
X.I Eid
Xdoes a lookup, and then invokes an editor on all files with
Xthe matched name as an initial search string.  Of course, this
Xname stands for
X\fI\|e(dit) id\fP.
X.PP
X.I Eid
Xuses four environment variables to control its invocation of the
Xeditor.
XNaturally,
X.B EDITOR
Xis used to locate the editing program.
X.B EIDARG
Xis a
X.IR printf (3S)
Xstring used to specify the form of the initial-search-string
Xargument.  If the editor does not support such an argument,
Xthis variable may be left unset.
X.B EIDLDEL
Xand
X.B EIDRDEL
Xspecify the form of the left and right word-delimiters respectively.
XThe best way to explain the use of these last three variables is
Xwith an example.  Here are the proper settings for vi(1):
X.nf
XEIDARG='+/%s/'	# initial search argument template
XEIDLDEL='\\<'	# left word-delimiter
XEIDRDEL='\\>'	# right word-delimiter
X.fi
X.PP
X.I Patterns
Xmay be simple alpha-numeric strings, or regular expressions in the
Xstyle of
X.IR regcmp (3).
XIf the string contains no regular-expression meta-characters, it is
Xsearched for as a
X.IR word .
XIf the string contains meta-characters, or if the \-e argument is
Xsupplied, it is searched for as regular-expression.
X.PP
X.I Aid\^
Xproduces output in the style of
X.I lid\^
Xbut its pattern arguments are searched for as substrings within
Xthe identifiers in the database.  No regular-expression search
Xis performed, even if the pattern contains meta-characters.
XThe search is conducted in an alphabetic case insensitive manner.
XThe mnemonic for this name is
X\fI\|a(propos) id\fP. 
X.PP
XThe following options are recognized:
X.TP 10
X.BR \-f file\^
XUse
X.I file\^
Xas the database instead of the default
X.BR ID .
X.TP 10
X.BR \-u n
XLists all identifiers in the database that are non-unique within the first
X.I n
Xcharacters.  This facility is particularly helpful when porting a program
Xto a system whose compiler or linker has fewer significant characters
Xfor identifiers.
X.PP
XThe remaining options are for use in conjunction with numeric patterns:
X.TP 10
X.B \-doxa
XThese options may be specified in any combination.
XThey limit numeric matches to specific radixes.
XThe
X.BR \-d ,
X.BR \-o ,
Xand
X.B \-x
Xoptions limit matches to decimal, octal, and hexadecimal respectively.
XThe
X.BR \-a
Xoption is a shorthand for specifying all three radixes.
X.PP
XSearches for numbers 
Xare conducted numerically rather than lexically, so that all
Xrepresentations for a given number are potentially available
Xfrom a single search.
X.TP 10
X.B \-m
XMerge multiple lines of output into a single line.
X.TP 10
X.B \-s
XLimit the results of the search to identifiers that occur only
Xonce in the entire set of sources covered by the database.
XThis option is useful for finding identifiers that are defined
Xbut never used.
X.SH SEE ALSO
Xmkid(1),
Xfid(1).
SHAR_EOF
if test 4020 -ne "`wc -c < 'lid.1'`"
then
	echo shar: error transmitting "'lid.1'" '(should have been 4020 characters)'
fi
echo shar: extracting "'mkid.1'" '(4644 characters)'
sed 's/^X//' << \SHAR_EOF > 'mkid.1'
X.TH MKID 1
X.SH NAME
Xmkid \- make an id database
X.SH SYNOPSIS
X.B mkid
X.RB [ \-v ]
X.RB [ \-f \^out-file]
X.RB [ \-s \^directory]
X.RB [ \-r \^directory]
X.RB [ \-S \^scanarg]
X.RB [ \-a \^arg-file]
X.RB [ \- ]
X.RB [ \-u ]
X.RB [ files... ]
X.SH DESCRIPTION
X.I Mkid\^
Xbuilds a database that stores numbers and identifier names, as well
Xas the names of the files in which they occur.
X.I Mkid\^
Xis particularly useful with large programs spread out across multiple
Xsource files.  It serves as an aid for program maintenance and as a
X.I guide\^
Xfor perusing a program.
X.PP
XThe following options are recognized:
X.TP 10
X.B \-v
XVerbose.
XReport
X.IR mkid 's
Xprogress in building the database.  The output comes on standard error.
X.TP 10
X.BI \-f out-file\^
XWrite the finished database into
X.IR out-file .
X.B ID\^
Xis the default.
X.TP 10
X.BI \-s directory\^
X.TP 10
X.BI \-r directory\^
XIf
X.IR mkid 's
Xattempt to open a source-file fails, it will try to checkout the
Xcorresponding SCCS or RCS file if present.  The
X.B \-s
Xoption tells
X.I mkid\^
Xwhich directory holds the SCCS file.
XSimilarly, the
X.B \-r
Xoption tells
X.I mkid\^
Xwhich directory holds the RCS file.
XIf neither the RCS or SCCS directories are specified,
X.I mkid\^
Xwill first look for an SCCS file in the current directory, then in
X.BI sccs ,
Xand finally in
X.BI SCCS .
XIt will then look for an RCS file in the current directory, and finally in
X.BI RCS .
X.TP 10
X.BI \-a arg-file\^
XOpen and read
X.I arg-file\^
Xin order to obtain a list of source file arguments.  Source file names
Xmust appear one to a line.
X.BI \-S ,
X.BI \-r ,
Xand
X.BI \-s
Xarguments may also be placed one per line in
X.IR file .
XThey are distinguished from source file names by their leading `-'.  If a file name begins
Xwith `-', it can be distinguished from an argument by explicitly prepending the current
Xdirectory string: `./'.
X.TP 10
X.B \-
XThis operates in the same manner as the
X.B \-a
Xoption described above, but reads from the standard input instead of a file.
X.TP 10
X.B \-u
XUpdate an existing database.  Only those files that have been modified
Xsince the database was built will be rescanned.  This is a significant
Xtime-saver for updating large databases where few sources have changed.
X.TP 10
X.B files...
XIf neither the
X.BI \-a ,
X.BI \- ,
Xnor
X.BI \-u ,
Xarguments have been specified, take file names from the command line.
X.TP 10
X.BI \-S scanarg\^
X.I Mkid\^
Xscans source files in order to obtain numbers and identifier names.
XSince the lexical rules of languages differ,
X.I mkid\^
Xapplies a different scanning function to each language in order
Xto conform to that language's lexical rules.
X.I Mkid\^
Xdetermines the source file's language by examining its filename
Xsuffix which commonly occurs after a dot (`.').
XThe
X.B \-S
Xargument is a way of passing language specific arguments to the
Xscanner for that language.  This argument takes a number of forms:
X.br
X-S<suffix>=<language>
X.br
X-S<language>-<arg>
X.br
X+S-<arg>
X.br
XThe first form associates a suffix with a language.  You may find
Xout which suffixes are defined for which languages with the following
Xoptions: `-S<suffix>=?' tells which language is bound to
X.IR <suffix> ,
X`-S?=<language>' tells which suffixes are bound to 
X.IR <language> ,
Xand `-S?=?' reports all bindings between suffixes and languages.
X.PP
XThe second form passes an argument for processing by the scanner
Xfor a specific language.  The third form passes an argument to
Xall scanners.
X.PP
XYou may get a brief summary of the scanner-specific options for a
Xlanguage by supplying the following option: `-S<language>?'.
X.PP
XHere is a brief summary of the options for the
X.I `asm'\^
X(assembler) language.
X.PP
XThe
X.B \-u\^
Xoption controls whether or not the assembler scanner should strip
Xoff a leading
X.I underscore\^
X(`_') character.  If your assembler prepends an
X.I underscore\^
Xto external symbols, then you should tell the scanner to strip it
Xoff, so that references to the same symbol from assembly and from
Xa high-level language will look the same.
X.PP
XThe
X.B \-c<cc>\^
Xoption supplies the character(s) used to begin a comment that extends
Xto the end of the line.
X.PP
XThe
X.B \-a<cc>\^
Xoption indicates character(s) that are legal in names, in addition to
Xthe alpha-numeric characters.  If the option appears as `-a', names
Xthat contain these characters are ignored.  If it appears as `+a', these
Xnames are added to the database.
X.SH BUGS
XThis manual page needs to be more complete about the scanner-specific
Xarguments.
X.PP
XAt the moment, the only scanners implemented are for C and assembly
Xlanguage.  There ought to be scanners for Ada, Pascal, Fortran, Lisp,
Xnroff/troff, and TeX.
X.SH SEE ALSO
Xlid(1).
SHAR_EOF
if test 4644 -ne "`wc -c < 'mkid.1'`"
then
	echo shar: error transmitting "'mkid.1'" '(should have been 4644 characters)'
fi
#	End of shell archive
exit 0