summaryrefslogtreecommitdiffstats
path: root/contrib/global
diff options
context:
space:
mode:
authorcwt <cwt@FreeBSD.org>1997-08-16 04:13:58 +0000
committercwt <cwt@FreeBSD.org>1997-08-16 04:13:58 +0000
commit9061d030a863ba8f4459b970cbd9de2e54ce2769 (patch)
treef1b6c84881f3a8f4bc5ae8ef2f59326c6076e13d /contrib/global
downloadFreeBSD-src-9061d030a863ba8f4459b970cbd9de2e54ce2769.zip
FreeBSD-src-9061d030a863ba8f4459b970cbd9de2e54ce2769.tar.gz
Import global v2.0 as contributed software. We will maintain it this
way, retiring the sources from usr.bin/global shortly. Reviewed by: jdp Discussed-with: obrien
Diffstat (limited to 'contrib/global')
-rw-r--r--contrib/global/HISTORY203
-rw-r--r--contrib/global/INSTALL148
-rw-r--r--contrib/global/MANIFEST18
-rw-r--r--contrib/global/Makefile3
-rw-r--r--contrib/global/Makefile.generic43
-rw-r--r--contrib/global/Makefile.inc1
-rw-r--r--contrib/global/README695
-rw-r--r--contrib/global/VERSION1
-rw-r--r--contrib/global/btreeop/Makefile5
-rw-r--r--contrib/global/btreeop/Makefile.generic22
-rw-r--r--contrib/global/btreeop/btreeop.1181
-rw-r--r--contrib/global/btreeop/btreeop.c405
-rw-r--r--contrib/global/btreeop/err.c217
-rw-r--r--contrib/global/gctags/C.c840
-rw-r--r--contrib/global/gctags/Makefile7
-rw-r--r--contrib/global/gctags/Makefile.generic23
-rw-r--r--contrib/global/gctags/assembler.c76
-rw-r--r--contrib/global/gctags/ctags.c410
-rw-r--r--contrib/global/gctags/ctags.h113
-rw-r--r--contrib/global/gctags/err.c217
-rw-r--r--contrib/global/gctags/fortran.c168
-rw-r--r--contrib/global/gctags/gctags.1237
-rw-r--r--contrib/global/gctags/lisp.c105
-rw-r--r--contrib/global/gctags/print.c122
-rw-r--r--contrib/global/gctags/test/ctags.test67
-rw-r--r--contrib/global/gctags/tree.c140
-rw-r--r--contrib/global/gctags/yacc.c151
-rw-r--r--contrib/global/global/Makefile9
-rw-r--r--contrib/global/global/Makefile.generic13
-rw-r--r--contrib/global/global/global.1149
-rw-r--r--contrib/global/global/global.pl302
-rw-r--r--contrib/global/gtags.el298
-rw-r--r--contrib/global/gtags/Makefile9
-rw-r--r--contrib/global/gtags/Makefile.generic13
-rw-r--r--contrib/global/gtags/gtags.186
-rw-r--r--contrib/global/gtags/gtags.pl84
-rw-r--r--contrib/global/htags/Makefile9
-rw-r--r--contrib/global/htags/Makefile.generic13
-rw-r--r--contrib/global/htags/htags.1124
-rw-r--r--contrib/global/htags/htags.pl1271
-rw-r--r--contrib/global/include/ansi.h93
-rw-r--r--contrib/global/include/cdefs.h158
-rw-r--r--contrib/global/include/err.h62
-rw-r--r--contrib/global/nvi-1.34.diff900
-rw-r--r--contrib/global/nvi-1.79.diff664
-rw-r--r--contrib/global/systags/Makefile7
-rw-r--r--contrib/global/systags/Makefile.generic10
-rwxr-xr-xcontrib/global/systags/systags.sh87
48 files changed, 8979 insertions, 0 deletions
diff --git a/contrib/global/HISTORY b/contrib/global/HISTORY
new file mode 100644
index 0000000..6698351
--- /dev/null
+++ b/contrib/global/HISTORY
@@ -0,0 +1,203 @@
+GLOBAL history
+--------------
+
+version 1.0 initial version [21-Apr-96]
+
+version 1.1 only bugfix [2-May-96]
+
+ [fixed bug]
+ global - makes corrupted path name by conversion error.
+ - description of exit code in online manual is mistaken.
+ btreeop - cannot treat a long line over BUFSIZ. With the result
+ that gtags fails.
+ extended ctags - when using -r option, considers a reserved word
+ to be a function name. With the result that GRTAGS becomes
+ too large.
+
+version 1.2 support of 1.34 nvi [7-Jun-96]
+
+ [changed]
+ extended ctags
+ - change to use bsearch(3) for searching reserved words.
+ - change to consider '__P' as a reserved word.
+ - unify the original patch (included in version1.0) and
+ the bugfix patch (included in version1.1).
+ [added]
+ extended vi
+ - VI tag support.
+
+version 1.3 support of GTAGSLIBPATH [28-Jul-96]
+
+ [changed]
+ global - search not only in a source tree but also in library paths
+ specified by environment variable GTAGSLIBPATH.
+ extended ctags
+ - change print format a little when -x option
+
+version 1.4 support of yacc source file [26-Oct-96]
+
+ [changed]
+ extended ctags
+ - support of yacc source file.
+ - this version of ctags is NOT COMPATIBLE with original one.
+ * search all part of a yacc file for C functions.
+ (original only 3rd part)
+ * no longer considers a yacc rule to be an object.
+
+version 1.5 hypertext generator [12-Dec-96]
+
+ [fixed bug]
+ gtags - treat 'y.tab.c' as a C source.(we should treat only *.y)
+ extended vi
+ - free stack memory. free(3) in FreeBSD 2.1.5R seems to
+ show a warning message when receive stack address.
+ So it spoils the screen.
+ [added]
+ htags - new command (hypertext generator of C source file)
+ gtags - error check code added.
+
+version 1.6 support of 1.76 nvi and reconstruction for other OS [21-Jan-97]
+
+ [changed]
+ htags - cease using <BLOCKQUOTE> because lynx doesn't understand it.
+ global,htags
+ - replace 'sort -u' with 'sort | uniq' for compatibility reason.
+ [fixed bug]
+ global - makes illegal path name when using GTAGSLIBPATH.
+ gtags - error message mistaken.
+ [added]
+ nvi-1.76.diff
+ - patch for nvi 1.76 to make extended vi.
+ gctags - this is the same with extended ctags in older version.
+ now GLOBAL includes BSD ctags in it. so no longer has
+ patch file (ctags.diff).
+ (I brought original ctags from FreeBSD 2.1.5R)
+ global - -a option added.
+
+version 1.7 make suitable for large project (mainly FreeBSD kernel) [17-Feb-97]
+
+ [changed]
+ htags - htags no longer makes frame.html. Index.html offers frame
+ function too.
+ - works MUCH faster than previous version.
+ [fixed bug]
+ htags - generate path name including '&param'. (It means special
+ charactor in hypertertext.)
+ So, changed internal separator from '&' to '|'.
+ [added]
+ gtags - -s option added. If specified, gtags extract ENTRY() and
+ ALTENTRY() from *.[sS] files.
+ htags - support one level nested index. It's always valid for file
+ index when directories found, and valid for function index
+ only when -a option specified.
+ - -v and -t option added.
+ systags.sh
+ - script to make all tags (GTAGS,GRTAGS,HTML) for kernel source.
+ (it is only for FreeBSD and Linux)
+
+version 1.8 fix some bugs, add options and make more portable [5-Apr-97]
+
+ [changed]
+ gctags, btreeop, Makefile
+ - modify for generic UNIX (Linux, Solaris)
+ - modify to quiet compiler.
+
+ Many thanks to
+ A.E. Brouwer
+ Oleg Checkulaev
+ Emile Heyns
+
+ gctags - modify to treat '\r' at the end of line.
+ htags - changed internal separator from '|' to ' '.
+ because some OS cannot treat '|' in a path.
+ [fixed bug]
+ htags - regard a part of path in #include as a reserved word.
+ - generate illegal links when same tags exist in a line.
+ - insufficient comment detection.
+
+ Thanks to Jeffrey Friedl. I took his code for complete
+ comment detection.
+
+ gctags - regard function name as a definition in extern statement.
+ - skip macro(no argment) body when -r specified.
+ gctags, htags
+ - regard 'entry' as a reserved word.
+ [added]
+ global - -c (complete) option added.
+ htags - -d tagdir option added.
+ - -w option added.
+
+version 1.81 make global to understand 'obj' directory [14-Apr-97]
+
+ [fixed bug]
+ extended vi
+ - doesn't hand '\' in a pattern to global.
+ [changed]
+ global
+ - can find tag file in obj directory.
+
+version 1.9 support of 1.79 nvi and some additional options [21-Apr-97]
+
+ [fixed bug]
+ htags - doesn't keep the code formatted correctly.
+ So, changed to convert tabs in source files into spaces.
+ (expand(1) needed)
+
+ Thanks to Andy Newman.
+
+ - cannot print error message correctly.
+ [changed]
+ gctags, btreeop
+ - modify for SunOS 4.1.3.
+
+ Thanks to Yoshiharu Ito.
+
+ [added]
+ btreeop - META record is available.
+ (It will be used in the furture.)
+ - -A and -D option added.
+ (It will be used in the future.)
+ global - 'format version record' is available.
+ (It will be used in the furture.)
+ htags - use temporary directory specified by TMPDIR environment
+ variable.
+ - -l option added.
+
+ Thanks to Jeff Trawick. This option is his idea.
+
+ nvi-1.79.diff
+ - patch for nvi 1.79 to make extended vi.
+
+version 2.0 Support of Emacs and CGI Form [7-Jul-97]
+
+ [fixed bug]
+ gtags, htags
+ - treat files under 'RCS/' or 'SCCS/' directory.
+ global - allow relative path of GTAGSDBPATH and GTAGSROOT.
+ htags - illegal tag generated when no definition found.
+ [changed]
+ htags - changed not to print line number by default.
+ If you need it, -n option should be specified.
+ - added the command name to error message.
+ - avoid sort(1)'s bug.
+ - changed for performance.
+ systags - use -n, -f option for htags by default.
+ doesn't use -w option for htags by default.
+ gtags - rewritten with perl.
+ gtags, gctags
+ - move some code for assembler source from gtags to gctags.
+ gtags, htags, global
+ - restrict PATH to '/bin:/usr/bin'.
+ btreeop - expand tabs into spaces of output.
+ [deleted]
+ nvi-1.76.diff
+ [added]
+ gtags.el- added emacs support (emulation of 1.34 nvi)
+ htags - added hyperlink for include files.
+ - added checking if GTAGS is the latest one.
+ - -f option added.
+ With this option, you can use input form and dynamic
+ index. (You need to setup httpd server for it.)
+ - -n option added.
+ global - -f option added.
+ btreeop - -L option added.
diff --git a/contrib/global/INSTALL b/contrib/global/INSTALL
new file mode 100644
index 0000000..11b916c
--- /dev/null
+++ b/contrib/global/INSTALL
@@ -0,0 +1,148 @@
+
+Installation of GLOBAL 2.0
+
+ 3-Jul-1997 Shigio Yamaguchi
+---------------------------------------------------------------------------
+Guide line (C style)
+---------------------------------------------------------------------------
+
+if (Your system == FreeBSD) {
+ You are lucky!
+ You need not to do procedure "1. Preparation for generic UNIX".
+
+ switch (version) {
+ case 2.0.5R:
+ case 2.1.0R:
+ case 2.1.5R:
+ There is no problem.
+ break;
+ case 2.1.6R:
+ case 2.1.7R:
+ I don't know. But it seems same with 2.1.5R.
+ break;
+ case 2.2.1R:
+ It is OK. But your native nvi is version 1.71.
+ Use 1.79 nvi available on the Internet.
+ break;
+ case 2.2.2R:
+ Your system inlucdes GLOBAL 1.9. You can overwrite it
+ with this 2.0 package.
+ But skip procedure "3. Extended vi (OPTIONAL)", because
+ your /usr/bin/nvi is already extended nvi for GLOBAL.
+ break;
+ default:
+ I don't know. But it semms to be little problem.
+ }
+} else {
+ You may some error message to make GLOBAL.
+ But it seems not so difficult to clear it. If you make a patch for it,
+ please let me know. I would like to include your patch into new
+ version of GLOBAL.
+
+ Thank you in advance.
+}
+
+----------------------------------------------------------------------------
+Install procedure
+----------------------------------------------------------------------------
+
+0. Extracting
+
+ % tar xzvf global-2.0.tar.gz
+ % cd global-2.0
+
+1. Preparation for generic UNIX
+
+ If you are a FreeBSD (all version) user, nothing to do here.
+ Please go to "2. GLOBAL basic".
+
+ Otherwise, you must install following items before you install GLOBAL.
+
+ a) Generic makefile
+
+ This package includes generic makefile. Please do the followings.
+
+ % make -f Makefile.generic gen
+ % vi Makefile <- check install directories (BINDIR, MANDIR)
+
+ b) BSD db library version 1.85
+
+ If you don't have it, you can fetch it from this site.
+
+ http://mongoose.bostic.com/db/packages/db.1.85.tar.gz
+
+ c) PERL version 4 or later
+
+ If you don't have it, you can fetch it from this site.
+
+ ftp://ftp.cis.ufl.edu/pub/perl/CPAN/src/5.0/latest.tar.gz
+
+ If you install perl into other than /usr/bin, please rewrite the header
+ of following commnads.
+
+ gtags/gtags.pl global/global.pl htags/htags.pl
+
+2. GLOBAL basic (NEEDED)
+
+ % make
+ # make install
+
+3. Extended vi (OPTIONAL)
+
+ GLOBAL supports two version of nvi. There is a little defference between
+ them when a number of functions located. (please see 'README' file.)
+ Version 1.34 nvi is included by FreeBSD 2.0.5R, 2.1.0R and 2.1.5R.
+ Version 1.79 nvi is available on
+
+ ftp://ftp.cs.berkeley.edu/ucb/4bsd/nvi-1.79.tar.gz.
+
+ If you don't have nvi-1.34, use nvi-1.79.
+
+ If you use version 1.34 nvi which is a native command in FreeBSD 2.0.5R,
+ 2.1.0R or 2.1.5R then
+
+ % cp -r /usr/src/usr.bin/vi vi <- version 1.34 of nex/nvi
+ % cd vi
+ % patch -p < ../nvi-1.34.diff
+ % make
+ # make install
+
+ else if you use version 1.79 nvi which is the latest version then
+ fetch from ftp://ftp.cs.berkeley.edu/ucb/4bsd/nvi-1.79.tar.gz and
+
+ % tar xzvf nvi-1.79.tar.gz
+ % cd nvi-1.79
+ % patch -p < ../nvi-1.79.diff
+ % cd build
+ % ./configure
+ % make
+ # make install
+
+ Caution: If you use FreeBSD 2.2.2R or later, your nvi is already
+ extended vi. Don't patch with nvi-1.79.diff.
+
+ else we have no patch for it.
+
+4. Extended emacs (OPTIONAL)
+
+ The version of Emacs supported by GLOBAL is GNU Emacs 19.28, 19.34 or
+ Mule 2.3 (= Emacs 19.28). Other emacs version seems to work well,
+ but I don't confirm it.
+
+ You can get it from
+
+ Emacs 19.34b:
+ prep.ai.mit.edu/pub/gnu/emacs-19.34b.tar.gz
+ Mule 2.3:
+ ftp://ftp.cs.buffalo.edu/pub/mule/mule-2.3.tar.gz
+
+ If you are a FreeBSD user, install it from package.
+
+ If you have installed it, to use extended emacs, copy gtags.el
+ in this package to the emacs lisp library directory or place the file
+ in a directory (for example "~/lisp") and write $HOME/.emacs like this.
+
+ +-----------------------------------------------
+ |(setq load-path (cons "~/lisp" load-path))
+
+Good luck!
diff --git a/contrib/global/MANIFEST b/contrib/global/MANIFEST
new file mode 100644
index 0000000..70304df
--- /dev/null
+++ b/contrib/global/MANIFEST
@@ -0,0 +1,18 @@
+HISTORY Histroy of GLOBAL.
+INSTALL Installation method
+MANIFEST This file.
+Makefile Makefile for BSD.
+Makefile.inc A part of Makefile for BSD.
+Makefile.generic Makefile for generic UNIX(including BSD).
+README Readme (introduction and usage).
+VERSION Version number.
+btreeop/ Btreeop command directory.
+gctags/ Gctags command directory (extended ctags).
+global/ Global command directory.
+gtags/ Gtags command directory.
+htags/ Htags command directory.
+include/ include files for non BSD system.
+systags/ Script for kernel.
+gtags.el Gtags mode for Emacs
+nvi-1.34.diff Patch for nvi 1.34.
+nvi-1.79.diff Patch for nvi 1.79.
diff --git a/contrib/global/Makefile b/contrib/global/Makefile
new file mode 100644
index 0000000..2eb181e
--- /dev/null
+++ b/contrib/global/Makefile
@@ -0,0 +1,3 @@
+SUBDIR= gctags global gtags btreeop htags systags
+
+.include <bsd.subdir.mk>
diff --git a/contrib/global/Makefile.generic b/contrib/global/Makefile.generic
new file mode 100644
index 0000000..a6a4a34
--- /dev/null
+++ b/contrib/global/Makefile.generic
@@ -0,0 +1,43 @@
+# @(#)Makefile 1-Mar-97
+
+SUBDIR= gctags global gtags btreeop htags systags
+BINDIR= /usr/bin # EDIT THIS
+MANDIR= /usr/share/man # EDIT THIS
+
+# For FreeBSD contrib
+CONTRIBDIR= /tmp/global
+RMFILES=INSTALL Makefile.generic nvi-1.34.diff nvi-1.79.diff \
+ */Makefile.generic */err.c include
+
+all:
+ @for d in $(SUBDIR); do \
+ set -e; (cd $$d; echo '===>' $$d; make $(MFLAGS)) \
+ done
+install:
+ @for d in $(SUBDIR); do \
+ set -e; (cd $$d; echo '===>' $$d; make $(MFLAGS) BINDIR=$(BINDIR) MANDIR=$(MANDIR) install) \
+ done
+gen:
+ @if [ ! -f Makefile.generic ]; then \
+ echo "Error: generic makefile not found."; exit 1; \
+ fi
+ mv Makefile Makefile.bsd; mv Makefile.generic Makefile
+ for d in $(SUBDIR); do \
+ (cd $$d; mv Makefile Makefile.bsd; mv Makefile.generic Makefile) \
+ done
+bsd:
+ @if [ ! -f Makefile.bsd ]; then \
+ echo "Error: BSD style makefile not found."; exit 1; \
+ fi
+ mv Makefile Makefile.generic; mv Makefile.bsd Makefile
+ for d in $(SUBDIR); do \
+ (cd $$d; mv Makefile Makefile.generic; mv Makefile.bsd Makefile) \
+ done
+bsdcontrib: clean
+ rm -rf $(CONTRIBDIR)
+ mkdir $(CONTRIBDIR) && cp -r . $(CONTRIBDIR)
+ cd $(CONTRIBDIR) && rm -rf $(RMFILES)
+clean:
+ @for d in $(SUBDIR); do \
+ (cd $$d; echo '===>' $$d; make $(MFLAGS) clean) \
+ done
diff --git a/contrib/global/Makefile.inc b/contrib/global/Makefile.inc
new file mode 100644
index 0000000..c24c4b1
--- /dev/null
+++ b/contrib/global/Makefile.inc
@@ -0,0 +1 @@
+BINDIR?= /usr/bin
diff --git a/contrib/global/README b/contrib/global/README
new file mode 100644
index 0000000..bb1f9e7
--- /dev/null
+++ b/contrib/global/README
@@ -0,0 +1,695 @@
+
+ @@@@@@@=
+ @= @=
+ @= @=
+ @= @= @@@@@= @@@@@@= @@= @=
+ @= F o r a l l h a c h e r s. version 2.0
+ @= @@@@@@=@= @= @= @@@@@= @= @= @=
+ @= @= @= @= @= @= @= @@@@@= @=
+ @= @= @= @= @= @= @=@= @= @=
+ @@@@@@@@= @@@@= @@@@@= @@@@@@=@@@= @@@@= @@@@@@=
+
+ Shigio Yamaguchi 7-Jul-97
+
+ Copyright 1996, 1997 Shigio Yamaguchi All right resereved.
+
+GLOBAL is a browsing system for C and Yacc source code.
+It brings benefits to all hackers. Enjoy!
+
+ Contents
+ --------------------------------
+ 0. Introduction
+
+ 1. Global
+
+ 1.1. Features
+ 1.2. Preparation
+ 1.3. Basic usage
+ 1.4. Applied usage
+
+ 2. Extended vi using global
+
+ 2.1. Features
+ 2.2. Preparation
+ 2.3. Basic usage
+ 2.4. Applied usage
+
+ 3. Hypertext generator
+
+ 3.1. Features
+ 3.2. Preparation
+ 3.3. Usage
+ 3.4. To make hypertext of kernel
+
+ 4. Extended emacs using global
+
+ 4.1. Features
+ 4.2. Preparation
+ 4.3. Basic usage
+ 4.4. Applied usage
+ --------------------------------
+
+0. Introduction
+
+GLOBAL is a browsing system for C and Yacc source files.
+You can locate the specified function in C source files and move there easily.
+It is useful to hack a large project containing many subdirectories,
+many '#ifdef' and many main() functions like MH, X or BSD kernel.
+
+It supports following environments.
+
+ o shell command line(see '1. Global')
+ o vi editor(see '2. Extended vi using global')
+ o web browser(see '3. Hypertext generator')
+ o emacs editor(see '4. Emacs using global')
+
+GLOBAL is consist of global(1), gtags(1), btreeop(1), gctags(1), htags(1),
+extended vi(1) and gtags.el.
+
+ * 'extended' means being entended for GLOBAL.
+
+ * Btreeop and gctags are used internally, so you need not
+ understand about them.
+
+The extended vi is completely upper compatible with original one.
+All the functions for GLOBAL are enabled only in 'gtagsmode'.
+
+------------------------------------------------------------------------------
+
+1. Global
+
+1.1. Features
+
+ o Global can find the locations of a specified function quickly.
+ o Global can locate not only function definitions but also function references.
+ o Global allows duplicate entries.
+ o Global can treat a source tree containing subdirectories and you can
+ get relative path of objects from anywhere within the tree.
+ o Global can understand perl's regular expression.
+ o Global can search in not only a source tree but also library paths.
+ o Global can treat yacc source file.
+
+ I think these features are useful for a large project containing many
+ subdirectories, many '#ifdef' and many main() functions like MH.
+
+1.2. Preparation
+
+ First of all, you must execute gtags(1) at the root of source tree.
+ For example, if you want to browse vi's source code, please do like this.
+
+ % cd /usr/src/usr.bin/vi
+ % gtags
+
+ Gtags traverse subdirectories and makes
+ two database at the root of source tree.
+
+ % ls G*TAGS
+ GRTAGS GTAGS
+
+ GTAGS - database for function definition
+ GRTAGS - database for function reference
+
+ If you cannot find functions that should exist, please try -e option.
+
+ % gtags -e
+
+1.3. Basic usage
+
+ Please think of following source tree.
+
+ ROOT/ <- the root of source tree (GTAGS,GRTAGS)
+ |
+ |- DIR1/
+ | |
+ | |- fileA.c ..... +---------------+
+ | | |main(){ |
+ | | | func1();|
+ | | | func2();|
+ | | |} |
+ | | +---------------+
+ | |
+ | |- fileB.c ..... +---------------+
+ | |func1(){ ... } |
+ | +---------------+
+ |- DIR2/
+ |
+ |- fileC.c ..... +---------------+
+ |#ifdef X |
+ |func2(){ i++; }|
+ |#else |
+ |func2(){ i--; }|
+ |#endif |
+ |func3(){ |
+ | func1();|
+ |} |
+ +---------------+
+
+ You can get the relative path of your object from anywhere within
+ the source tree.
+
+ % cd ROOT
+ % global func1
+ DIR1/fileB.c <- func1() is defined in fileB.c
+ % cd DIR1
+ % global func1
+ fileB.c <- relative path from DIR1
+ % cd ../DIR2
+ % global func1
+ ../DIR1/fileB.c <- relative path from DIR2
+
+ -r option locates function references.
+
+ % global -r func2
+ ../DIR1/fileA.c <- func2() is referred from fileA.c
+
+ You can use perl's regular expression.
+
+ % cd ROOT
+ % global 'func[1-3]'
+ DIR1/fileB.c <- func1, func2 and func3 are matched
+ DIR2/fileC.c
+
+ -x option shows the detail. It's similar to ctags's -x option.
+
+ % global func2
+ DIR2/fileC.c
+ % global -x func2
+ func2 2 DIR2/fileC.c func2(){ i++; }
+ func2 4 DIR2/fileC.c func2(){ i--; }
+
+ -a option produces the absolute path name.
+
+ % global -a func1
+ /home/user/ROOT/DIR1/fileB.c
+
+ You can edit files including specified function directly like this.
+
+ % vi `global func1` <- edit fileB.c
+
+
+1.4. Applied usage
+
+ You can make multiple tag files.
+ For example, you can execute gtags at ROOT/, version1.0/ and version2.0/.
+
+ ROOT/ <- the root of source tree (GTAGS,GRTAGS)
+ |
+ |- version1.0/ <- the root of version1.0 (GTAGS,GRTAGS)
+ | |
+ | |- file.c ..... +---------------+
+ | |func1(){ i++; }|
+ | +---------------+
+ |
+ |- version2.0/ <- the root of version2.0 (GTAGS,GRTAGS)
+ |
+ |- file.c ..... +---------------+
+ |func1(){ i--; }|
+ +---------------+
+
+ When you are walking in version1.0 directory, global locates functions
+ only in version1.0.
+
+ % cd ROOT/version1.0
+ % global -x func1
+ func1 1 file.c func1(){ i++; }
+
+ When you are walking in version2.0, global locates functions only in
+ version2.0.
+
+ % cd ROOT/version2.0
+ % global -x func1
+ func1 1 file.c func1(){ i--; }
+
+ If you are at ROOT/ or you set GTAGSROOT environment variable to ROOT,
+ global locates functions in both version1.0 and version2.0 directories.
+
+ % cd ROOT
+ % global -x func1
+ func1 1 version1.0/file.c func1(){ i++; }
+ func1 1 version2.0/file.c func1(){ i--; }
+
+ =-=-=-=
+
+ There is another usage of GTAGSROOT.
+ If your source files are on a read only device like CDROM, you cannot
+ make database on the root of source tree.
+ In such case, please do the following.
+
+ % mkdir /var/dbpath
+ % cd /cdrom/src <- the root of source tree
+ % gtags /var/dbpath <- make tag file in /var/dbpath
+ % setenv GTAGSROOT `pwd`
+ % setenv GTAGSDBPATH /var/dbpath
+ % global func
+
+ =-=-=-=
+
+ If you want to treat the references to a function that is not defined
+ in the source tree like a library function or system call, you can specify
+ library directories with the GTAGSLIBPATH environment variable.
+ You should execute gtags at each directory of the path.
+ If GTAGS is not found in a directory, global ignores it.
+
+ % pwd
+ /develop/src/mh <- this is the source tree
+ % gtags
+ % ls G*TAGS
+ GRTAGS GTAGS
+ % global mhl
+ uip/mhlsbr.c <- mhl() is found
+ % global strlen <- strlen() is not found
+ % (cd /usr/src/lib; gtags) <- library source
+ % (cd /usr/src/sys; gtags) <- kernel source
+ % setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys
+ % global strlen
+ ../../../usr/src/lib/libc/string/strlen.c <- strlen() is found in library
+ % global access
+ ../../../usr/src/sys/kern/vfs_syscalls.c <- access() is found in kernel
+
+ Of course, user program doesn't call kernel function directly, but
+ at least it is useful.
+
+ =-=-=-=
+
+ If you forget function name, you can use -c (complete) option.
+
+ % global -c kmem <- maybe k..k.. kmem..
+ kmem_alloc
+ kmem_alloc_pageable
+ kmem_alloc_wait
+ kmem_free
+ kmem_free_wakeup
+ kmem_init
+ kmem_malloc
+ kmem_suballoc <- This is what I need!
+ % global kmem_suballoc
+ ../vm/vm_kern.c
+
+ You can use -c option with tcsh's complete command.
+
+ % set funcs=(`global -c`)
+ % complete global 'n/*/$funcs/'
+ % global kmem_<TAB>
+ kmem_alloc kmem_alloc_wait kmem_free_wakeup kmem_malloc
+ kmem_alloc_pageable kmem_free kmem_init kmem_suballoc
+ % global kmem_s<TAB>
+ % global kmem_suballoc
+ ../vm/vm_kern.c
+
+ * <TAB> means tab key or Ctrl-I.
+
+ =-=-=-=
+
+ If you want to browse many files in order, do the followings.
+
+ % global -xr fork | awk '{printf "view +%s %s\n",$2,$3}' | tee /tmp/list
+ view +650 ../dev/aic7xxx/aic7xxx_asm.c
+ view +250 ibcs2/ibcs2_misc.c
+ view +401 linux/linux_misc.c
+ view +310 ../kern/init_main.c
+ view +318 ../kern/init_main.c
+ view +336 ../kern/init_main.c
+ view +351 ../kern/init_main.c
+ % sh !$ <- from now on, go to next tag with 'ZZ'.
+
+2. Extended vi using global
+
+2.1. Features
+
+ o Tag function of extended vi can locate not only function definitions
+ but also function references.
+ o Extended vi allows duplicate tag entries.
+ o Extended vi can understand perl's regular expression as a tag name
+ for search.
+ o Extended vi is completely upper compatible with original one.
+ Above functions are available only in 'gtags mode'.
+
+2.2. Preparation
+
+ First, do the preparation of global. (Please see "1.2. Preparation").
+
+ Second, to use global from vi, you need to get into 'gtagsmode'.
+ There are some ways to do it.
+
+ (a) Start vi with -G option
+
+ % vi -G file.c
+
+ (b) Start vi and execute "set gtagsmode"
+
+ % vi file.c
+ ~
+ ~
+ ~
+ :set gtagsmode
+
+ (c) Previously write the set command to .exrc or .nexrc file and start vi
+
+ $HOME/.exrc
+ +----------------------------
+ |set gtagsmode
+
+ You must start vi under the source tree described in "1.2. Preparation".
+
+2.3. Basic usage
+
+ o To go to func1, you can say
+
+ :tag func1
+
+ It seemes same with original vi, but extended vi use GTAGS
+ instead of tags.
+
+ o To go to referenced point of func1, add prefix 'r'
+
+ :rtag func1
+
+ Extended vi use GRTAGS.
+
+ o If a number of functions located, the action of extended vi differs
+ up to your nvi's version.
+
+ [Extended vi based 1.34 nvi]
+
+ Vi goes into 'GTAGS SELECT MODE' like this.
+
+ +-------------------------------------------------------------
+ |main 347 i386/isa/ultra14f.c main()
+ |main 128 kern/init_main.c main(framep)
+ |main 104 netiso/clnp_debug.c main()
+ |main 164 netiso/xebec/main.c main(argc, argv)
+ |~
+ |~
+ |~
+ |~
+ |~
+ |[GTAGS SELECT MODE] 4 lines
+ +-------------------------------------------------------------
+
+ You can select a tag line by any vi command and press [RETURN],
+ and you can go to the tag's point. In ex mode, type "select"
+ instead of [RETURN]. When you want to go to next or previous tag,
+ you can return to 'GTAGS SELECT MODE' with <control-T> and reselect.
+
+ Suggested .nexrc:
+ set gtagsmode
+ set leftright
+
+ [Extended vi based 1.79 nvi]
+
+ Vi goes to the first tag.
+ Then you can go to next tag by ':tagnext' or back by ':tagprev'.
+
+ Suggested .nexrc:
+ set gtagsmode
+ map ^N :tagnext^M
+ map ^P :tagprev^M
+
+ == WHY TWO STYLE EXIST ? ==
+ 1.34 nvi cannot treat duplicate tag entries, so I made 'GTAGS SELECT MODE'
+ in it. But 1.79 nvi (1.61 and later) can treat them, so I adapted GLOBAL
+ tags to nvi's tag structure.
+
+ o <control-]> command is available.
+
+ In gtagsmode, if you are on the first column of line, it is identical to
+ ":rtag <current token>[RETURN]", otherwise ":tag <current token>[RETURN]".
+
+ o Other tag commands are available too.
+
+ <control-T> - Return to the most recent tag context.
+ ":tagpop" - Pop to the specified tag in the tags stack.
+ ":tagtop" - Pop to the top tag in the tags stack.
+ ":display tags" - Display tags stack.
+
+ Please read online manual.
+
+2.4. Applied usage
+
+ o In large project which include many main() function like MH,
+ you can start vi like this.
+
+ % vi -G -t main
+
+ You can browse all commands sequentially.
+
+ o When you want to check functions the name of which start with
+ "set" or "get",
+
+ % vi -G -t '^[sg]et'
+
+ Of cause, following command is available too.
+
+ :tag ^[sg]et
+
+ o If your source files are on a read only device like CDROM, please do
+ the followings.
+
+ % mkdir /var/dbpath <- directory for tag file
+ % cd /cdrom/src <- the root of source tree
+ % gtags /var/dbpath <- make tag files in /var/dbpath
+ % setenv GTAGSROOT `pwd`
+ % setenv GTAGSDBPATH /var/dbpath
+ % vi -G -t main
+
+ o If you want to treat the references to the function that is not defined
+ in the source tree like library functions or system calls,
+ do the followings.
+
+ % cd /usr/src/lib
+ % gtags <- probably as a root
+ % cd /usr/src/sys
+ % gtags
+ % setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys
+
+ If you examine vi's source,
+
+ % cd /usr/src/usr.bin/vi
+ % gtags
+ % vi -G -t main
+
+ You can start from vi and trip the whole unix world as if using
+ hypertext.
+
+
+3. Hypertext generator
+
+3.1. Features
+
+ o Htags makes hypertext from C source files.
+ o Once the hypertext generated, you need nothing other than WWW browser.
+ o You can move hypertext to anywhere. It is independent of the source code.
+ o You can use all of your browser's functions, for example, search,
+ history, bookmark, save, frame, windows and so on.
+
+3.2. Preparation
+
+ At first, you must prepare much disk space. Hypertext needs so much
+ disk space. For example, the source code of FreeBSD kernel needs the
+ following disk space.
+
+ source code(/usr/src/sys) 14MB
+ tag database(GTAGS,GRTAGS) 9MB(!)
+ hypertext(HTML/*) 45MB(!!!)
+
+ Please do the followings.
+
+ (at your source directory)
+ % gtags <- make tag database
+ % htags <- make hypertext
+
+ Then you will find 'HTML' directory in the current directory.
+
+3.3. Usage
+
+ Please start a web browser like this.
+
+ % lynx HTML/index.html
+
+ You can use any browsers, for example, Lynx, Chimera, Mosaic,
+ Netscape Navigator, Internet Explorer and so on. But some browsers
+ cannot treat framed index. Then select '[no frame version is here]'.
+
+ You will understand the usage for the looking.
+ You can move HTML directory to anywhere. It is independent of
+ the source code.
+
+3.4. To make hypertext of kernel
+
+ If you would like to make hypertext of FreeBSD kernel source,
+ it is convenient to use systags script in this package.
+
+ % cd /usr/src/sys
+ % systags
+ then
+
+ % netscape HTML/index.html
+
+ You can use following functions with systags.
+
+ o input form for dynamic index.
+ (This reqires you to setup httpd server for CGI program.)
+ o one level nested index.
+ o browse assembler source file.
+
+ Of course, you can use above functions without systags.
+ Please see gtags(1), htags(1).
+
+
+4. Extended emacs using global
+
+4.1. Features
+
+ Addition to the extended vi,
+
+ o More intelligent to recongnize current token and its type.
+ o Tag completion is available for input tag name.
+ o Mouse event is supported.
+
+4.2. Preparation
+
+ First, do the preparation of global. (Please see "1.2. Preparation").
+
+ Second, to use global from emacs, you need to load gtags.el file and
+ execute gtags-mode function in it. There are some ways to do it.
+
+ (a) Start emacs, load gtags.el and execute gtags-mode function.
+
+ % emacs
+
+ |
+ |J_:-----Mule: *scratch* (Lisp Interaction)--L16--All----
+ |M-x load-library[RET]
+ +------------------------------------------------------
+
+ |
+ |J_:-----Mule: *scratch* (Lisp Interaction)--L16--All----
+ |Load library: gtags[RET]
+ +------------------------------------------------------
+
+ |
+ |J_:-----Mule: *scratch* (Lisp Interaction)--L16--All----
+ |M-x gtags-mode[RET]
+ +------------------------------------------------------
+
+ (b) Previously write autoload function to $HOME/.emacs file,
+ start emacs and execute gtags-mode function.
+
+ $HOME/.emacs
+ +------------------------------------------------------
+ |(autoload 'gtags-mode "gtags" "" t)
+
+ % emacs
+
+ |
+ |J_:-----Mule: *scratch* (Lisp Interaction)--L16--All----
+ |M-x gtags-mode[RET]
+ +------------------------------------------------------
+
+ (c) Previously write autoload function to $HOME/.emacs file and
+ start emacs with -f option
+
+ $HOME/.emacs
+ +------------------------------------------------------
+ |(autoload 'gtags-mode "gtags" "" t)
+
+ % emacs -f gtags-mode
+
+
+ You must start emacs under the source tree described in "1.2. Preparation".
+
+4.3. Basic usage
+
+ It is resemble to the extended vi based nvi-1.34.
+
+ o To go to func1, press 'ESC-t' and you can see a prompt in mini-buffer.
+ Then input tag name.
+
+ :tag func1 # ':tag ' is a prompt.
+ ~~~~~
+ o To go to referenced point of func1, press 'ESC-r'.
+
+ :rtag func1 # 'rtag ' is a prompt
+ ~~~~~
+
+ o Tag name completion is available.
+
+ :tag fu<TAB>
+
+ :tag func1 # 'nc1' is appended by emacs
+
+ o If a number of functions located, emacs goes into 'GTAGS SELECT MODE'
+ like this.
+
+ +-------------------------------------------------------------
+ |main 347 i386/isa/ultra14f.c main()
+ |main 128 kern/init_main.c main(framep)
+ |main 104 netiso/clnp_debug.c main()
+ |main 164 netiso/xebec/main.c main(argc, argv)
+ |
+ |
+ |
+ |
+ |
+ |J_:--%*-Mule: *scratch* (Gtags Select)--L1--All----
+ |[GTAGS SELECT MODE] 4 lines
+ +-------------------------------------------------------------
+
+ You can select a tag line by any emacs command and press [RETURN],
+ and you can go to the tag's point. When you want to go to next or
+ previous tag, you can return to 'GTAGS SELECT MODE' with <control-T>
+ and reselect.
+
+ o <control-]> command is available.
+
+ If current token is a definition, it is identical to
+ ":rtag <current token>[RETURN]", otherwise ":tag <current token>[RETURN]".
+ (GLOBAL decides this intelligentlly, but may sometimes misunderstand.)
+
+4.4. Applied usage
+
+ o You can use perl's regular expression.
+
+ :tag ^put_ # locate tags start with 'put_'.
+
+ o If your source files are on a read only device like CDROM, please do
+ the followings.
+
+ % mkdir /var/dbpath <- directory for tag file
+ % cd /cdrom/src <- the root of source tree
+ % gtags /var/dbpath <- make tag files in /var/dbpath
+ % setenv GTAGSROOT `pwd`
+ % setenv GTAGSDBPATH /var/dbpath
+ % mule -f gtags-mode
+
+ o If you want to treat the references to the function that is not defined
+ in the source tree like library functions or system calls,
+ do the followings.
+
+ % cd /usr/src/lib
+ % gtags <- probably as a root
+ % cd /usr/src/sys
+ % gtags
+ % setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys
+ % mule -f gtags-mode
+
+ o mouse command is avalable.
+
+ If you use X version emacs, try this.
+ (But xemacs doesn't work well. I don't know why.)
+
+ Move mouse cursor to a function name and click center button. And you
+ will go to function's definition or references depending on the context.
+ In 'GTAGS SELECT MODE', move mouse cursor to a line and click center
+ button.
+
+ To return to the previous position, click right button.
+
+Thank you for your reading of my poor english.
+And of course, I'm grateful to all excellent tools (vi, emacs, perl, C, db,
+mozilla ...) and its authors.
+----------------------------------------------------------------------------
+E-Mail: <shigio@wafu.netgate.net>
+WWW: <http://wafu.netgate.net/tama/unix/indexe.html>
+ (You can find the latest version here.)
+----------------------------------------------------------------------------
diff --git a/contrib/global/VERSION b/contrib/global/VERSION
new file mode 100644
index 0000000..cd5ac03
--- /dev/null
+++ b/contrib/global/VERSION
@@ -0,0 +1 @@
+2.0
diff --git a/contrib/global/btreeop/Makefile b/contrib/global/btreeop/Makefile
new file mode 100644
index 0000000..c9e0409
--- /dev/null
+++ b/contrib/global/btreeop/Makefile
@@ -0,0 +1,5 @@
+# @(#)Makefile 1.0 (Berkeley) 4/21/96
+
+PROG= btreeop
+
+.include <bsd.prog.mk>
diff --git a/contrib/global/btreeop/Makefile.generic b/contrib/global/btreeop/Makefile.generic
new file mode 100644
index 0000000..52dcc0e
--- /dev/null
+++ b/contrib/global/btreeop/Makefile.generic
@@ -0,0 +1,22 @@
+# @(#)Makefile 29-Dec-96
+
+PROG = btreeop
+CC = gcc
+#WARN = -Wall -Wparentheses -Wstrict-prototypes -Wmissing-prototypes
+LIBS = -ldb
+CFLAGS = -O -I../include
+OBJS = btreeop.o err.o
+BINDIR = /usr/bin
+MANDIR = /usr/share/man
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CC) -o $(PROG) $(OBJS) $(LIBS)
+install:
+ cp $(PROG) $(BINDIR)
+ chmod 755 $(BINDIR)/$(PROG)
+ cp $(PROG).1 $(MANDIR)/man1
+ chmod 644 $(MANDIR)/man1/$(PROG).1
+clean:
+ rm -f $(PROG) $(OBJS) GTAGS GRTAGS
diff --git a/contrib/global/btreeop/btreeop.1 b/contrib/global/btreeop/btreeop.1
new file mode 100644
index 0000000..8d42abc
--- /dev/null
+++ b/contrib/global/btreeop/btreeop.1
@@ -0,0 +1,181 @@
+.\"
+.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Shigio Yamaguchi.
+.\" 4. Neither the name of the author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd July 4, 1997
+.Dt BTREEOP 1
+.Os BSD 4
+.Sh NAME
+.Nm btreeop
+.Nd btree database maintenance tool
+.Sh SYNOPSIS
+.Nm btreeop
+.Op Fl A
+.Op Fl C
+.Op Fl D Ar key
+.Op Fl K Ar key
+.Op Fl L
+.Op Fl b
+.Op Fl c Ar cashesize
+.Op Fl l
+.Op Fl p Ar psize
+.Op Ar dbname
+.Sh DESCRIPTION
+.Nm Btreeop
+execute simple operations for
+.Xr btree 3
+database.
+.Nm Btreeop
+can create database, write record, read record (sequential or index) and
+delete record from it.
+Duplicate entries are allowed.
+.Sh OPTIONS
+A capital letter means a command. If no command specified
+then it assume sequential read operation.
+.Bl -tag -width Ds
+.It Fl A
+append records. If database doesn't exist, btreeop creates it.
+.It Fl C
+create database and write records to it.
+.It Fl D Ar key
+delete records by the key.
+.It Fl K Ar key
+search records by the key.
+.It Fl L
+list all keys. It is identical to following command line.
+
+ btreeop | awk '{print $1}' | sort | uniq
+.It Fl b
+assume BIG_ENDIAN byte order. default is LITTLE_ENDIAN.
+.It Fl c Ar cashesize
+specify cashesize. It's identical to
+.Nm info.cachesize
+of BTREEINFO. (see btree(3))
+.It Fl l
+assume LITTLE_ENDIAN byte order. (the default)
+.It Fl p Ar psize
+specify page size. It's identical to
+.Nm info.psize
+of BTREEINFO. (see btree(3))
+.It Ar dbname
+database name. default is 'btree'.
+.Sh DATA FORMAT
+To creat (or append) database,
+.Nm btreeop
+read data from stdin.
+The format of the data is the following.
+
+ Key Data\\n
+ Key Data\\n
+ .
+ .
+ .
+
+.El
+
+.Bl -enum -offset indent
+.It
+Key and Data are separated by blank('\\t' or ' ').
+.It
+Key cannot include blank.
+.It
+Data can include blank.
+.It
+Null Data not allowed.
+.It
+Additionally, META record is available. META record has a key that start with
+a blank. You can read this record only by indexed search (with -K option).
+Usage is unlimited by btreeop.
+.El
+.Sh EXAMPLES
+Create database.
+
+ % btreeop -C
+ key1 data1
+ key2 data2
+ key3 data3
+ ^D
+ %
+
+Append records.
+
+ % btreeop -A
+ __.VERSION 2
+ key2 data2-2
+ ^D
+ %
+
+Sequential read.
+
+ % btreeop
+ key1 data1
+ key2 data2-2
+ key2 data2
+ key3 data3
+ %
+
+Indexed read.
+
+ % btreeop -K key2
+ key2 data2-2
+ key2 data2
+ % btreeop -K ' __.VERSION'
+ __.VERSION 2
+ %
+
+List kyes.
+
+ % btreeop -L
+ key1
+ key2
+ key3
+ %
+
+Delete record.
+
+ % btreeop -D ' __.VERSION'
+ % btreeop -K ' __.VERSION'
+ %
+
+.Sh FILES
+.Bl -tag -width tags -compact
+.It Pa btree
+default database name.
+.El
+.Sh DIAGNOSTICS
+.Nm Btreeop
+exits with a value of 1 if an error occurred, 0 otherwise.
+.Sh SEE ALSO
+.Xr btree 3
+.Sh AUTHOR
+Shigio Yamaguchi (shigio@wafu.netgate.net)
+.Sh HISTORY
+The
+.Nm
+command appeared in FreeBSD 2.2.
diff --git a/contrib/global/btreeop/btreeop.c b/contrib/global/btreeop/btreeop.c
new file mode 100644
index 0000000..d7ae831
--- /dev/null
+++ b/contrib/global/btreeop/btreeop.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Shigio Yamaguchi.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * btreeop.c 6-Jul-97
+ *
+ */
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <db.h>
+#include <fcntl.h>
+
+char *dbdefault = "btree"; /* default database name */
+char *dbname;
+char buf[BUFSIZ+1];
+char out[BUFSIZ+1];
+
+#ifndef __P
+#if defined(__STDC__)
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+
+void die __P((char *));
+static void usage __P((void));
+void entab __P((char *));
+void detab __P((char *, char *));
+void main __P((int, char **));
+void dbwrite __P((DB *));
+void dbkey __P((DB *, char *));
+void dbscan __P((DB *, int));
+void dbdel __P((DB *, char *));
+DB *db;
+char *key;
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+
+void
+die(s)
+char *s;
+{
+ errx(1, "%s", s);
+}
+
+static void
+usage()
+{
+ fprintf(stderr, "%s\n%s\n",
+ "usage: btreeop [-A][-C][-D key][-K key][-L][-b][-c cachesize]",
+ " [-l][-p psize][dbname]");
+ exit(1);
+}
+
+#define TABPOS(i) ((i)%8 == 0)
+/*
+ * entab: convert spaces into tabs
+ *
+ * io) buf string buffer
+ */
+void
+entab(buf)
+char *buf;
+{
+ int blanks = 0;
+ int pos, src, dst;
+ char c;
+
+ pos = src = dst = 0;
+ while ((c = buf[src++]) != 0) {
+ if (c == ' ') {
+ if (!TABPOS(++pos)) {
+ blanks++; /* count blanks */
+ continue;
+ }
+ buf[dst++] = '\t';
+ } else if (c == '\t') {
+ while (!TABPOS(++pos))
+ ;
+ buf[dst++] = '\t';
+ } else {
+ ++pos;
+ while (blanks--)
+ buf[dst++] = ' ';
+ buf[dst++] = c;
+ }
+ blanks = 0;
+ }
+ buf[dst] = 0;
+}
+/*
+ * detab: convert tabs into spaces
+ *
+ * i) buf string including tabs
+ * o) out output
+ */
+void
+detab(buf, out)
+char *buf;
+char *out;
+{
+ int src, dst;
+ char c;
+
+ src = dst = 0;
+ while ((c = buf[src++]) != 0) {
+ if (c == '\t') {
+ do {
+ out[dst++] = ' ';
+ } while (!TABPOS(dst));
+ } else {
+ out[dst++] = c;
+ }
+ }
+ out[dst] = 0;
+}
+
+#include <errno.h>
+void
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ char command = 'R';
+ char *key = NULL;
+ DB *db;
+ BTREEINFO info;
+ int c;
+ int flags = 0;
+ extern char *optarg;
+ extern int optind;
+
+ info.flags = R_DUP; /* allow duplicate entries */
+ info.cachesize = 500000;
+ info.maxkeypage = 0;
+ info.minkeypage = 0;
+ info.psize = 0;
+ info.compare = NULL;
+ info.prefix = NULL;
+ info.lorder = LITTLE_ENDIAN;
+
+ while ((c = getopt(argc, argv, "ACD:K:Lbc:lp:")) != -1) {
+ switch (c) {
+ case 'K':
+ case 'D':
+ key = optarg;
+ case 'A':
+ case 'C':
+ case 'L':
+ if (command != 'R')
+ usage();
+ command = c;
+ break;
+ case 'b':
+ info.lorder = BIG_ENDIAN;
+ break;
+ case 'c':
+ info.cachesize = atoi(optarg);
+ break;
+ case 'l':
+ info.lorder = LITTLE_ENDIAN;
+ break;
+ case 'p':
+ info.psize = atoi(optarg);
+ break;
+ default:
+ usage();
+ }
+ }
+
+ dbname = (optind < argc) ? argv[optind] : dbdefault;
+ switch (command) {
+ case 'A':
+ case 'D':
+ flags = O_RDWR|O_CREAT;
+ break;
+ case 'C':
+ flags = O_RDWR|O_CREAT|O_TRUNC;
+ break;
+ case 'K':
+ case 'L':
+ case 'R':
+ flags = O_RDONLY;
+ break;
+ }
+ db = dbopen(dbname, flags, 0644, DB_BTREE, &info);
+ if (db == NULL) {
+ die("dbopen failed.");
+ }
+ switch (command) {
+ case 'A': /* Append records */
+ case 'C': /* Create database */
+ dbwrite(db);
+ break;
+ case 'D': /* Delete records */
+ dbdel(db, key);
+ break;
+ case 'K': /* Keyed (indexed) read */
+ dbkey(db, key);
+ break;
+ case 'R': /* sequencial Read */
+ case 'L': /* key's List */
+ dbscan(db, (command == 'L') ? 1 : 0);
+ break;
+ }
+ if (db->close(db)) {
+ die("db->close failed.");
+ }
+ exit(0);
+}
+/*
+ * dbwrite: write to database
+ *
+ * i) db
+ */
+void
+dbwrite(db)
+DB *db;
+{
+ DBT key, dat;
+ int status;
+#define IDENTLEN 80
+ char keybuf[IDENTLEN+1];
+ char *c;
+
+ /*
+ * Input file format:
+ * +------------------
+ * |Key Data\n
+ * |Key Data\n
+ * .
+ * .
+ * - Key and Data are separated by blank('\t' or ' ').
+ * - Key cannot include blank.
+ * - Data can include blank.
+ * - Null Data not allowed.
+ *
+ * META record:
+ * You can write meta record by making key start with a ' '.
+ * You can read this record only by indexed read ('-K' option).
+ * +------------------
+ * | __.VERSION 2
+ */
+ while (fgets(buf, BUFSIZ, stdin)) {
+ if (buf[strlen(buf)-1] == '\n') /* chop(buf) */
+ buf[strlen(buf)-1] = 0;
+ else
+ while (fgetc(stdin) != '\n')
+ ;
+ c = buf;
+ if (*c == ' ') { /* META record */
+ if (*++c == ' ')
+ die("illegal format.");
+ }
+ for (; *c && !isspace(*c); c++) /* skip key part */
+ ;
+ if (*c == 0)
+ die("data part not found.");
+ if (c - buf > IDENTLEN)
+ die("key too long.");
+ strncpy(keybuf, buf, c - buf); /* make key string */
+ keybuf[c - buf] = 0;
+ for (; *c && isspace(*c); c++) /* skip blanks */
+ ;
+ if (*c == 0)
+ die("data part is null.");
+ entab(buf);
+ key.data = keybuf;
+ key.size = strlen(keybuf)+1;
+ dat.data = buf;
+ dat.size = strlen(buf)+1;
+
+ status = (db->put)(db, &key, &dat, 0);
+ switch (status) {
+ case RET_SUCCESS:
+ break;
+ case RET_ERROR:
+ case RET_SPECIAL:
+ die("db->put: failed.");
+ }
+ }
+}
+
+/*
+ * dbkey: Keyed search
+ *
+ * i) db
+ * i) skey
+ */
+void
+dbkey(db, skey)
+DB *db;
+char *skey;
+{
+ DBT dat, key;
+ int status;
+
+ key.data = skey;
+ key.size = strlen(skey)+1;
+
+ for (status = (*db->seq)(db, &key, &dat, R_CURSOR);
+ status == RET_SUCCESS && !strcmp(key.data, skey);
+ status = (*db->seq)(db, &key, &dat, R_NEXT)) {
+ detab((char *)dat.data, out);
+ (void)fprintf(stdout, "%s\n", out);
+ }
+ if (status == RET_ERROR)
+ die("db->seq failed.");
+}
+
+/*
+ * dbscan: Scan all records
+ *
+ * i) db
+ * i) keylist
+ */
+void
+dbscan(db, keylist)
+DB *db;
+int keylist;
+{
+ DBT dat, key;
+ int status;
+ char prev[IDENTLEN+1];
+
+ prev[0] = 0;
+ for (status = (*db->seq)(db, &key, &dat, R_FIRST);
+ status == RET_SUCCESS;
+ status = (*db->seq)(db, &key, &dat, R_NEXT)) {
+ /* skip META record */
+ if (*(char *)key.data == ' ')
+ continue;
+ if (keylist) {
+ if (!strcmp(prev, (char *)key.data))
+ continue;
+ strcpy(prev, (char *)key.data);
+ (void)fprintf(stdout, "%s\n", (char *)key.data);
+ continue;
+ }
+ detab((char *)dat.data, out);
+ (void)fprintf(stdout, "%s\n", out);
+ }
+ if (status == RET_ERROR)
+ die("db->seq failed.");
+}
+
+/*
+ * dbdel: Delete records
+ *
+ * i) db
+ * i) skey key
+ */
+void
+dbdel(db, skey)
+DB *db;
+char *skey;
+{
+ DBT key;
+ int status;
+
+ key.data = skey;
+ key.size = strlen(skey)+1;
+
+ status = (*db->del)(db, &key, 0);
+ if (status == RET_ERROR)
+ die("db->del failed.");
+}
diff --git a/contrib/global/btreeop/err.c b/contrib/global/btreeop/err.c
new file mode 100644
index 0000000..bd84d46
--- /dev/null
+++ b/contrib/global/btreeop/err.c
@@ -0,0 +1,217 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/* extern char *__progname; Program name, from crt0. */
+char *progname = "btreeop";
+
+static FILE *err_file; /* file to use for error output */
+static void (*err_exit)(int);
+
+void
+err_set_file(void *fp)
+{
+ if (fp)
+ err_file = fp;
+ else
+ err_file = stderr;
+}
+
+void
+err_set_exit(void (*ef)(int))
+{
+ err_exit = ef;
+}
+
+void
+#ifdef __STDC__
+err(int eval, const char *fmt, ...)
+#else
+err(eval, fmt, va_alist)
+ int eval;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ verr(eval, fmt, ap);
+ va_end(ap);
+}
+
+void
+verr(eval, fmt, ap)
+ int eval;
+ const char *fmt;
+ va_list ap;
+{
+ int sverrno;
+
+ sverrno = errno;
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", progname);
+ if (fmt != NULL) {
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, ": ");
+ }
+ (void)fprintf(err_file, "%s\n", strerror(sverrno));
+ if(err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+void
+#if __STDC__
+errx(int eval, const char *fmt, ...)
+#else
+errx(eval, fmt, va_alist)
+ int eval;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ verrx(eval, fmt, ap);
+ va_end(ap);
+}
+
+void
+verrx(eval, fmt, ap)
+ int eval;
+ const char *fmt;
+ va_list ap;
+{
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", progname);
+ if (fmt != NULL)
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, "\n");
+ if (err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+void
+#if __STDC__
+warn(const char *fmt, ...)
+#else
+warn(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vwarn(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarn(fmt, ap)
+ const char *fmt;
+ va_list ap;
+{
+ int sverrno;
+
+ sverrno = errno;
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", progname);
+ if (fmt != NULL) {
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, ": ");
+ }
+ (void)fprintf(err_file, "%s\n", strerror(sverrno));
+}
+
+void
+#ifdef __STDC__
+warnx(const char *fmt, ...)
+#else
+warnx(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarnx(fmt, ap)
+ const char *fmt;
+ va_list ap;
+{
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", progname);
+ if (fmt != NULL)
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, "\n");
+}
diff --git a/contrib/global/gctags/C.c b/contrib/global/gctags/C.c
new file mode 100644
index 0000000..87652b5
--- /dev/null
+++ b/contrib/global/gctags/C.c
@@ -0,0 +1,840 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)C.c 8.4 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "ctags.h"
+
+static int func_entry __P((void));
+static void hash_entry __P((void));
+static void skip_string __P((int));
+static int str_entry __P((int));
+#ifdef GTAGS
+static int cmp __P((const void *, const void *));
+static int isstatement __P((char *));
+static void define_line __P((void));
+#endif
+
+#ifdef YACC
+extern int yaccfile; /* true when *.y file */
+#endif
+/*
+ * c_entries --
+ * read .c and .h files and call appropriate routines
+ */
+void
+c_entries()
+{
+ int c; /* current character */
+ int level; /* brace level */
+ int token; /* if reading a token */
+ int t_def; /* if reading a typedef */
+ int t_level; /* typedef's brace level */
+ char *sp; /* buffer pointer */
+ char tok[MAXTOKEN]; /* token buffer */
+#ifdef YACC
+ /*
+ * yacc file format is like the following.
+ *
+ * declarations
+ * %%
+ * rules
+ * %%
+ * programs
+ *
+ */
+#define DECLARATIONS 0
+#define RULES 1
+#define PROGRAMS 2
+ int yaccstatus = (yaccfile) ? DECLARATIONS : PROGRAMS;
+ int inyacc = (yaccfile) ? YES : NO; /* NO while C source */
+#endif
+
+ lineftell = ftell(inf);
+ sp = tok; token = t_def = NO; t_level = -1; level = 0; lineno = 1;
+ while (GETC(!=, EOF)) {
+ switch (c) {
+ /*
+ * Here's where it DOESN'T handle: {
+ * foo(a)
+ * {
+ * #ifdef notdef
+ * }
+ * #endif
+ * if (a)
+ * puts("hello, world");
+ * }
+ */
+ case '{':
+#ifdef YACC
+ if (yaccstatus == RULES && level == 0)
+ inyacc = NO;
+#endif
+ ++level;
+ goto endtok;
+ case '}':
+ /*
+ * if level goes below zero, try and fix
+ * it, even though we've already messed up
+ */
+ if (--level < 0)
+ level = 0;
+#ifdef GTAGS
+ /*
+ * -e flag force a function to end when a '}' appear
+ * at column 0. If -e flag not specified, all functions
+ * after funcA() would be lost.
+ *
+ * funcA() {
+ * #ifdef A
+ * if (a) {
+ * ...
+ * #else
+ * if (nota) {
+ * ...
+ * #endif
+ * }
+ * }
+ */
+ if (eflag && ftell(inf) == lineftell+1) {
+ level = 0;
+ }
+#endif
+#if YACC
+ if (yaccstatus == RULES && level == 0)
+ inyacc = YES;
+#endif
+ goto endtok;
+
+ case '\n':
+ SETLINE;
+ /*
+ * the above 3 cases are similar in that they
+ * are special characters that also end tokens.
+ */
+ endtok: if (sp > tok) {
+ *sp = EOS;
+ token = YES;
+ sp = tok;
+ }
+ else
+ token = NO;
+ continue;
+
+ /*
+ * We ignore quoted strings and character constants
+ * completely.
+ */
+ case '"':
+ case '\'':
+ (void)skip_string(c);
+ break;
+
+ /*
+ * comments can be fun; note the state is unchanged after
+ * return, in case we found:
+ * "foo() XX comment XX { int bar; }"
+ */
+ case '/':
+ if (GETC(==, '*')) {
+ skip_comment();
+ continue;
+ }
+ (void)ungetc(c, inf);
+ c = '/';
+ goto storec;
+
+ /* hash marks flag #define's. */
+ case '#':
+ if (sp == tok) {
+ hash_entry();
+ break;
+ }
+ goto storec;
+
+ /*
+ * if we have a current token, parenthesis on
+ * level zero indicates a function.
+#ifdef GTAGS
+ * in the case of rflag == 1, if we have a current token,
+ * parenthesis on level > zero indicates a function reference.
+#endif
+#ifdef YACC
+ * inyacc == NO while C source.
+#endif
+ */
+ case '(':
+#ifdef YACC
+ if (inyacc == NO)
+#endif
+#ifdef GTAGS
+ if (!rflag && !level && token)
+#else
+ if (!level && token)
+#endif
+ {
+ int curline;
+
+ if (sp != tok)
+ *sp = EOS;
+ /*
+ * grab the line immediately, we may
+ * already be wrong, for example,
+ * foo\n
+ * (arg1,
+ */
+ getline();
+ curline = lineno;
+#ifdef GTAGS
+ /* to make sure. */
+ if (!isstatement(tok))
+#endif
+ if (func_entry()) {
+ ++level;
+ pfnote(tok, curline);
+ }
+ break;
+ }
+#ifdef GTAGS
+ else if (rflag && level && token) {
+ if (sp != tok)
+ *sp = EOS;
+ getline();
+ if (!isstatement(tok) && isdefined(tok))
+ pfnote(tok, lineno);
+ break;
+ }
+#endif
+ goto storec;
+
+ /*
+ * semi-colons indicate the end of a typedef; if we find a
+ * typedef we search for the next semi-colon of the same
+ * level as the typedef. Ignoring "structs", they are
+ * tricky, since you can find:
+ *
+ * "typedef long time_t;"
+ * "typedef unsigned int u_int;"
+ * "typedef unsigned int u_int [10];"
+ *
+ * If looking at a typedef, we save a copy of the last token
+ * found. Then, when we find the ';' we take the current
+ * token if it starts with a valid token name, else we take
+ * the one we saved. There's probably some reasonable
+ * alternative to this...
+ */
+ case ';':
+ if (t_def && level == t_level) {
+ t_def = NO;
+ getline();
+ if (sp != tok)
+ *sp = EOS;
+ pfnote(tok, lineno);
+ break;
+ }
+ goto storec;
+
+#if YACC
+ case '%':
+ if (yaccstatus == DECLARATIONS || yaccstatus == RULES) {
+ if (GETC(==, '%')) {
+ level = 0;
+ if (yaccstatus == DECLARATIONS) {
+ if (!rflag) {
+ getline();
+ pfnote("yyparse", lineno);
+ }
+ yaccstatus = RULES;
+ } else if (yaccstatus == RULES) {
+ yaccstatus = PROGRAMS;
+ }
+ inyacc = (yaccstatus == PROGRAMS) ? NO : YES;
+ } else if (c == '{') {
+ level = 0;
+ inyacc = NO;
+ } else if (c == '}') {
+ level = 0;
+ inyacc = YES;
+ } else {
+ (void)ungetc(c, inf);
+ }
+ break;
+ }
+ /* else fall throuth */
+#endif
+ /*
+ * store characters until one that can't be part of a token
+ * comes along; check the current token against certain
+ * reserved words.
+ */
+ default:
+#ifdef BUGFIX
+ /*
+ * to treat following function.
+ * func (arg) {
+ * ....
+ * }
+ */
+ if (c == ' ' || c == '\t') {
+ int save = c;
+ while (GETC(!=, EOF) && (c == ' ' || c == '\t'))
+ ;
+ if (c == EOF)
+ return;
+ (void)ungetc(c, inf);
+ c = save;
+ }
+#endif
+ storec: if (!intoken(c)) {
+ if (sp == tok)
+ break;
+ *sp = EOS;
+#ifdef GTAGS
+ if (!memcmp(tok, "extern",7)) {
+ while (GETC(!=, EOF) && c != ';') {
+ if (c == '\n')
+ SETLINE;
+ }
+ if (c == EOF)
+ return;
+ break;
+ }
+#endif
+ if (tflag) {
+ /* no typedefs inside typedefs */
+ if (!t_def &&
+ !memcmp(tok, "typedef",8)) {
+ t_def = YES;
+ t_level = level;
+ break;
+ }
+ /* catch "typedef struct" */
+ if ((!t_def || t_level < level)
+ && (!memcmp(tok, "struct", 7)
+ || !memcmp(tok, "union", 6)
+ || !memcmp(tok, "enum", 5))) {
+ /*
+ * get line immediately;
+ * may change before '{'
+ */
+ getline();
+ if (str_entry(c))
+ ++level;
+ break;
+ /* } */
+ }
+ }
+ sp = tok;
+ }
+ else if (sp != tok || begtoken(c)) {
+ *sp++ = c;
+ token = YES;
+ }
+ continue;
+ /* end of default */
+ } /* end of switch */
+ /*
+ * 'break' statement in switch block come here.
+ */
+ sp = tok;
+ token = NO;
+ } /* end of while */
+}
+
+/*
+ * func_entry --
+ * handle a function reference
+ */
+static int
+func_entry()
+{
+ int c; /* current character */
+ int level = 0; /* for matching '()' */
+
+ /*
+ * Find the end of the assumed function declaration.
+ * Note that ANSI C functions can have type definitions so keep
+ * track of the parentheses nesting level.
+ */
+ while (GETC(!=, EOF)) {
+ switch (c) {
+ case '\'':
+ case '"':
+ /* skip strings and character constants */
+ skip_string(c);
+ break;
+ case '/':
+ /* skip comments */
+ if (GETC(==, '*'))
+ skip_comment();
+ break;
+ case '(':
+ level++;
+ break;
+ case ')':
+ if (level == 0)
+ goto fnd;
+ level--;
+ break;
+ case '\n':
+ SETLINE;
+ }
+ }
+ return (NO);
+fnd:
+ /*
+ * we assume that the character after a function's right paren
+ * is a token character if it's a function and a non-token
+ * character if it's a declaration. Comments don't count...
+ */
+ for (;;) {
+ while (GETC(!=, EOF) && iswhite(c))
+ if (c == '\n')
+ SETLINE;
+ if (intoken(c) || c == '{')
+ break;
+ if (c == '/' && GETC(==, '*'))
+ skip_comment();
+ else { /* don't ever "read" '/' */
+ (void)ungetc(c, inf);
+ return (NO);
+ }
+ }
+ if (c != '{')
+ (void)skip_key('{');
+ return (YES);
+}
+
+/*
+ * hash_entry --
+ * handle a line starting with a '#'
+ */
+static void
+hash_entry()
+{
+ int c; /* character read */
+ int curline; /* line started on */
+ char *sp; /* buffer pointer */
+ char tok[MAXTOKEN]; /* storage buffer */
+
+#ifdef BUGFIX
+ /*
+ * to treat following macro.
+ * # macro(arg) ....
+ */
+ while (GETC(!=, EOF) && (c == ' ' || c == '\t'))
+ ;
+ (void)ungetc(c, inf);
+#endif
+ curline = lineno;
+ for (sp = tok;;) { /* get next token */
+ if (GETC(==, EOF))
+ return;
+ if (iswhite(c))
+ break;
+ *sp++ = c;
+ }
+ *sp = EOS;
+ if (memcmp(tok, "define", 6)) /* only interested in #define's */
+ goto skip;
+ for (;;) { /* this doesn't handle "#define \n" */
+ if (GETC(==, EOF))
+ return;
+ if (!iswhite(c))
+ break;
+ }
+ for (sp = tok;;) { /* get next token */
+ *sp++ = c;
+ if (GETC(==, EOF))
+ return;
+ /*
+ * this is where it DOESN'T handle
+ * "#define \n"
+ */
+ if (!intoken(c))
+ break;
+ }
+ *sp = EOS;
+#ifdef GTAGS
+ if (rflag) {
+ /*
+ * #define XXX\n
+ */
+ if (c == '\n' || (c == '\r' && GETC(==, '\n'))) {
+ SETLINE;
+ return;
+ }
+ /*
+ * v
+ * #define XXX(X) XXXXXX
+ */
+ if (c == '(')
+ (void)skip_key(')');
+ /*
+ * v
+ * #define XXX(X) XXXXXX
+ */
+ while (GETC(!=, EOF)) {
+ if (c != ' ' && c != '\t') {
+ (void)ungetc(c, inf);
+ break;
+ }
+ }
+ /*
+ * v
+ * #define XXX(X) XXXXXX
+ */
+ define_line();
+ return;
+ }
+#endif
+ if (dflag || c == '(') { /* only want macros */
+ getline();
+ pfnote(tok, curline);
+ }
+skip: if (c == '\n') { /* get rid of rest of define */
+ SETLINE
+#ifdef MODIFY
+ if (*(sp - 1) == '\r') {
+ if (*(sp - 2) != '\\')
+ return;
+ } else
+#endif
+ if (*(sp - 1) != '\\')
+ return;
+ }
+ (void)skip_key('\n');
+}
+
+#ifdef GTAGS
+ /* sorted by alphabet */
+static struct words {
+ char *name;
+} words[] = {
+ {"__P"},
+ {"auto"},
+ {"break"},
+ {"case"},
+ {"char"},
+ {"continue"},
+ {"default"},
+ {"do"},
+ {"double"},
+ {"else"},
+ {"extern"},
+ {"float"},
+ {"for"},
+ {"goto"},
+ {"if"},
+ {"int"},
+ {"long"},
+ {"register"},
+ {"return"},
+ {"short"},
+ {"sizeof"},
+ {"static"},
+ {"struct"},
+ {"switch"},
+ {"typedef"},
+ {"union"},
+ {"unsigned"},
+ {"void"},
+ {"while"},
+};
+
+static int
+cmp(s1, s2)
+ const void *s1, *s2;
+{
+ return strcmp(((struct words *)s1)->name, ((struct words *)s2)->name);
+}
+
+static int
+isstatement(token)
+ char *token;
+{
+ struct words tmp;
+
+ tmp.name = token;
+ if (bsearch(&tmp, words, sizeof(words)/sizeof(struct words), sizeof(struct words), cmp))
+ return YES;
+ return NO;
+}
+
+static void
+define_line()
+{
+ int c; /* character read */
+ int level; /* brace level */
+ int token; /* if reading a token */
+ char *sp; /* buffer pointer */
+ char tok[MAXTOKEN]; /* storage buffer */
+
+ sp = tok; token = NO; level = 0;
+ while (GETC(!=, EOF)) {
+ switch (c) {
+ case '{':
+ ++level;
+ goto endtok;
+ case '}':
+ if (--level < 0)
+ level = 0;
+ goto endtok;
+
+ case '\\':
+ if (GETC(==, '\n') || (c == '\r' && GETC(==, '\n'))) {
+ SETLINE;
+ }
+ continue;
+
+ case '\n':
+ SETLINE;
+ return;
+ endtok: if (sp > tok) {
+ *sp = EOS;
+ token = YES;
+ sp = tok;
+ }
+ else
+ token = NO;
+ continue;
+
+ case '"':
+ case '\'':
+ (void)skip_string(c);
+ break;
+
+ case '/':
+ if (GETC(==, '*')) {
+ skip_comment();
+ continue;
+ }
+ (void)ungetc(c, inf);
+ c = '/';
+ goto storec;
+
+ case '(':
+ if (token) {
+ if (sp != tok)
+ *sp = EOS;
+ getline();
+ if (!isstatement(tok) && isdefined(tok))
+ pfnote(tok, lineno);
+ break;
+ }
+ goto storec;
+
+ case ';':
+ goto storec;
+
+ default:
+storec: if (!intoken(c)) {
+ if (sp == tok)
+ break;
+ *sp = EOS;
+ sp = tok;
+ }
+ else if (sp != tok || begtoken(c)) {
+ *sp++ = c;
+ token = YES;
+ }
+ continue;
+ }
+
+ sp = tok;
+ token = NO;
+ }
+}
+#endif
+/*
+ * str_entry --
+ * handle a struct, union or enum entry
+ */
+static int
+str_entry(c)
+ int c; /* current character */
+{
+ int curline; /* line started on */
+ char *sp; /* buffer pointer */
+ char tok[LINE_MAX]; /* storage buffer */
+
+ curline = lineno;
+ while (iswhite(c))
+ if (GETC(==, EOF))
+ return (NO);
+ if (c == '{') /* it was "struct {" */
+ return (YES);
+ for (sp = tok;;) { /* get next token */
+ *sp++ = c;
+ if (GETC(==, EOF))
+ return (NO);
+ if (!intoken(c))
+ break;
+ }
+ switch (c) {
+ case '{': /* it was "struct foo{" */
+ --sp;
+ break;
+ case '\n': /* it was "struct foo\n" */
+ SETLINE;
+ /*FALLTHROUGH*/
+ default: /* probably "struct foo " */
+ while (GETC(!=, EOF))
+ if (!iswhite(c))
+ break;
+ if (c != '{') {
+ (void)ungetc(c, inf);
+ return (NO);
+ }
+ }
+ *sp = EOS;
+ pfnote(tok, curline);
+ return (YES);
+}
+
+/*
+ * skip_comment --
+ * skip over comment
+ */
+void
+skip_comment()
+{
+ int c; /* character read */
+ int star; /* '*' flag */
+
+ for (star = 0; GETC(!=, EOF);)
+ switch(c) {
+ /* comments don't nest, nor can they be escaped. */
+ case '*':
+ star = YES;
+ break;
+ case '/':
+ if (star)
+ return;
+ break;
+ case '\n':
+ SETLINE;
+ /*FALLTHROUGH*/
+ default:
+ star = NO;
+ break;
+ }
+}
+
+/*
+ * skip_string --
+ * skip to the end of a string or character constant.
+ */
+static void
+skip_string(key)
+ int key;
+{
+ int c,
+ skip;
+
+ for (skip = NO; GETC(!=, EOF); )
+ switch (c) {
+ case '\\': /* a backslash escapes anything */
+ skip = !skip; /* we toggle in case it's "\\" */
+ break;
+#ifdef MODIFY
+ case '\r':
+ break;
+#endif
+ case '\n':
+ SETLINE;
+ /*FALLTHROUGH*/
+ default:
+ if (c == key && !skip)
+ return;
+ skip = NO;
+ }
+}
+
+/*
+ * skip_key --
+ * skip to next char "key"
+ */
+int
+skip_key(key)
+ int key;
+{
+ int c,
+ skip,
+ retval;
+
+ for (skip = retval = NO; GETC(!=, EOF);)
+ switch(c) {
+ case '\\': /* a backslash escapes anything */
+ skip = !skip; /* we toggle in case it's "\\" */
+ break;
+ case ';': /* special case for yacc; if one */
+ case '|': /* of these chars occurs, we may */
+ retval = YES; /* have moved out of the rule */
+ break; /* not used by C */
+ case '\'':
+ case '"':
+ /* skip strings and character constants */
+ skip_string(c);
+ break;
+ case '/':
+ /* skip comments */
+ if (GETC(==, '*')) {
+ skip_comment();
+ break;
+ }
+ (void)ungetc(c, inf);
+ c = '/';
+ goto norm;
+#ifdef MODIFY
+ case '\r':
+ break;
+#endif
+ case '\n':
+ SETLINE;
+ /*FALLTHROUGH*/
+ default:
+ norm:
+ if (c == key && !skip)
+ return (retval);
+ skip = NO;
+ }
+ return (retval);
+}
diff --git a/contrib/global/gctags/Makefile b/contrib/global/gctags/Makefile
new file mode 100644
index 0000000..2e3401f
--- /dev/null
+++ b/contrib/global/gctags/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= gctags
+CFLAGS+=-I${.CURDIR} -DGTAGS -DBUGFIX -DMODIFY -DYACC
+SRCS= C.c ctags.c fortran.c lisp.c print.c tree.c yacc.c assembler.c
+
+.include <bsd.prog.mk>
diff --git a/contrib/global/gctags/Makefile.generic b/contrib/global/gctags/Makefile.generic
new file mode 100644
index 0000000..59c2172
--- /dev/null
+++ b/contrib/global/gctags/Makefile.generic
@@ -0,0 +1,23 @@
+# @(#)Makefile 29-Dec-96
+
+PROG = gctags
+DEFS = -DGTAGS -DBUGFIX -DMODIFY -DYACC
+CC = gcc
+#WARN = -Wall -Wparentheses -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS = -O $(DEFS) -I../include
+LIBS = -ldb
+OBJS = C.o ctags.o fortran.o lisp.o print.o tree.o yacc.o assembler.o err.o
+BINDIR = /usr/bin
+MANDIR = /usr/share/man
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CC) -o $(PROG) $(OBJS) $(LIBS)
+install:
+ cp $(PROG) $(BINDIR)
+ chmod 755 $(BINDIR)/$(PROG)
+ cp $(PROG).1 $(MANDIR)/man1
+ chmod 644 $(MANDIR)/man1/$(PROG).1
+clean:
+ rm -f $(PROG) $(OBJS) GTAGS GRTAGS
diff --git a/contrib/global/gctags/assembler.c b/contrib/global/gctags/assembler.c
new file mode 100644
index 0000000..2ae468d
--- /dev/null
+++ b/contrib/global/gctags/assembler.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)assembler.c 8.3 (Berkeley) 6/6/97";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <string.h>
+#include "ctags.h"
+
+#ifdef GTAGS
+void
+asm_entries()
+{
+ char *lbp;
+ char tok[MAXTOKEN];
+ char *sp;
+
+ for (;;) {
+ lineftell = ftell(inf);
+ if (!fgets(lbuf, sizeof(lbuf), inf))
+ return;
+ ++lineno;
+ /* extract only ENTRY() and ALTENTRY(). */
+ if (lbuf[0] != 'E' && lbuf[0] != 'A')
+ continue;
+ lbp = lbuf;
+ if (!strncmp(lbp, "ENTRY(", 6)) {
+ lbp += 6;
+ } else if (!strncmp(lbp, "ALTENTRY(", 9)) {
+ lbp += 9;
+ } else
+ continue;
+ sp = tok;
+ while (*lbp && intoken(*lbp))
+ *sp++ = *lbp++;
+ if (*lbp != ')')
+ continue;
+ *sp = EOS;
+ getline();
+ pfnote(tok, lineno);
+ }
+ /*NOTREACHED*/
+}
+#endif
diff --git a/contrib/global/gctags/ctags.c b/contrib/global/gctags/ctags.c
new file mode 100644
index 0000000..5924cca
--- /dev/null
+++ b/contrib/global/gctags/ctags.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1987, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] =
+ "$Id: ctags.c,v 1.3 1997/07/10 06:43:40 charnier Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "ctags.h"
+
+/*
+ * ctags: create a tags file
+ */
+
+NODE *head; /* head of the sorted binary tree */
+
+ /* boolean "func" (see init()) */
+bool _wht[256], _etk[256], _itk[256], _btk[256], _gd[256];
+
+FILE *inf; /* ioptr for current input file */
+FILE *outf; /* ioptr for tags file */
+
+long lineftell; /* ftell after getc( inf ) == '\n' */
+
+int lineno; /* line number of current line */
+int dflag; /* -d: non-macro defines */
+#ifdef GTAGS
+int eflag; /* -e: '{' at 0 column force function end */
+#endif
+int tflag; /* -t: create tags for typedefs */
+int vflag; /* -v: vgrind style index output */
+int wflag; /* -w: suppress warnings */
+int xflag; /* -x: cxref style output */
+#ifdef GTAGS
+int Dflag; /* -D: allow duplicate entrys */
+int rflag; /* -r: function reference */
+#endif
+#ifdef YACC
+int yaccfile; /* yacc file */
+#endif
+
+char *curfile; /* current input file name */
+char searchar = '/'; /* use /.../ searches by default */
+char lbuf[LINE_MAX];
+
+void init __P((void));
+void find_entries __P((char *));
+void main __P((int, char **));
+static void usage __P((void));
+
+void
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ static char *outfile = "tags"; /* output file */
+ int aflag; /* -a: append to tags */
+ int uflag; /* -u: update tags */
+ int exit_val; /* exit value */
+ int step; /* step through args */
+ int ch; /* getopts char */
+ char cmd[100]; /* too ugly to explain */
+ extern char *optarg;
+ extern int optind;
+
+ aflag = uflag = NO;
+#ifdef GTAGS
+ while ((ch = getopt(argc, argv, "BDFadef:rtuwvxy")) != -1)
+#else
+ while ((ch = getopt(argc, argv, "BFadf:tuwvx")) != -1)
+#endif
+ switch(ch) {
+ case 'B':
+ searchar = '?';
+ break;
+#ifdef GTAGS
+ case 'D':
+ Dflag++;
+ break;
+#endif
+ case 'F':
+ searchar = '/';
+ break;
+ case 'a':
+ aflag++;
+ break;
+ case 'd':
+ dflag++;
+ break;
+#ifdef GTAGS
+ case 'e':
+ eflag++;
+ break;
+#endif
+ case 'f':
+ outfile = optarg;
+ break;
+#ifdef GTAGS
+ case 'r':
+ rflag++;
+ break;
+#endif
+ case 't':
+ tflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'w':
+ wflag++;
+ break;
+ case 'v':
+ vflag++;
+ case 'x':
+ xflag++;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+ if (!argc)
+ usage();
+#ifdef GTAGS
+ if (rflag)
+ gtagopen();
+#endif
+ init();
+
+ for (exit_val = step = 0; step < argc; ++step)
+ if (!(inf = fopen(argv[step], "r"))) {
+ warnx("%s cannot open", argv[step]);
+ exit_val = 1;
+ }
+ else {
+ curfile = argv[step];
+ find_entries(argv[step]);
+ (void)fclose(inf);
+ }
+
+ if (head)
+ if (xflag)
+ put_entries(head);
+ else {
+ if (uflag) {
+ for (step = 0; step < argc; step++) {
+ (void)sprintf(cmd,
+ "mv %s OTAGS; fgrep -v '\t%s\t' OTAGS >%s; rm OTAGS",
+ outfile, argv[step],
+ outfile);
+ system(cmd);
+ }
+ ++aflag;
+ }
+ if (!(outf = fopen(outfile, aflag ? "a" : "w"))) {
+ warnx("%s cannot open", outfile);
+ exit(exit_val);
+ }
+ put_entries(head);
+ (void)fclose(outf);
+ if (uflag) {
+ (void)sprintf(cmd, "sort -o %s %s",
+ outfile, outfile);
+ system(cmd);
+ }
+ }
+#ifdef GTAGS
+ if (rflag)
+ gtagclose();
+#endif
+ exit(exit_val);
+}
+
+static void
+usage()
+{
+ (void)fprintf(stderr,
+#ifdef GTAGS
+ "usage: gctags [-BDFadrtuwvx] [-f tagsfile] file ...\n");
+#else
+ "usage: gctags [-BFadtuwvx] [-f tagsfile] file ...\n");
+#endif
+ exit(1);
+}
+
+/*
+ * init --
+ * this routine sets up the boolean psuedo-functions which work by
+ * setting boolean flags dependent upon the corresponding character.
+ * Every char which is NOT in that string is false with respect to
+ * the pseudo-function. Therefore, all of the array "_wht" is NO
+ * by default and then the elements subscripted by the chars in
+ * CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in
+ * the string CWHITE, else NO.
+ */
+void
+init()
+{
+ int i;
+ unsigned char *sp;
+
+ for (i = 0; i < 256; i++) {
+ _wht[i] = _etk[i] = _itk[i] = _btk[i] = NO;
+ _gd[i] = YES;
+ }
+#define CWHITE " \f\t\n"
+ for (sp = (unsigned char *)CWHITE; *sp; sp++) /* white space chars */
+ _wht[*sp] = YES;
+#define CTOKEN " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?"
+ for (sp = (unsigned char *)CTOKEN; *sp; sp++) /* token ending chars */
+ _etk[*sp] = YES;
+#define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789"
+ for (sp = (unsigned char *)CINTOK; *sp; sp++) /* valid in-token chars */
+ _itk[*sp] = YES;
+#define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
+ for (sp = (unsigned char *)CBEGIN; *sp; sp++) /* token starting chars */
+ _btk[*sp] = YES;
+#define CNOTGD ",;"
+ for (sp = (unsigned char *)CNOTGD; *sp; sp++) /* invalid after-function chars */
+ _gd[*sp] = NO;
+}
+
+/*
+ * find_entries --
+ * this routine opens the specified file and calls the function
+ * which searches the file.
+ */
+void
+find_entries(file)
+ char *file;
+{
+ char *cp;
+
+ lineno = 0; /* should be 1 ?? KB */
+ if ((cp = strrchr(file, '.')) != NULL) {
+ if (cp[1] == 'l' && !cp[2]) {
+ int c;
+
+#ifdef GTAGS
+ if (rflag)
+ fprintf(stderr, "-r option is ignored in lisp file (Warning only)\n");
+#endif
+ for (;;) {
+ if (GETC(==, EOF))
+ return;
+ if (!iswhite(c)) {
+ rewind(inf);
+ break;
+ }
+ }
+#define LISPCHR ";(["
+/* lisp */ if (strchr(LISPCHR, c)) {
+ l_entries();
+ return;
+ }
+/* lex */ else {
+ /*
+ * we search all 3 parts of a lex file
+ * for C references. This may be wrong.
+ */
+ toss_yysec();
+ (void)strcpy(lbuf, "%%$");
+ pfnote("yylex", lineno);
+ rewind(inf);
+ }
+ }
+/* yacc */ else if (cp[1] == 'y' && !cp[2]) {
+#ifdef YACC
+ /*
+ * we search all part of a yacc file for C references.
+ * but ignore yacc rule tags.
+ */
+ yaccfile = YES;
+ c_entries();
+ return;
+#endif
+ /*
+ * we search only the 3rd part of a yacc file
+ * for C references. This may be wrong.
+ */
+ toss_yysec();
+ (void)strcpy(lbuf, "%%$");
+ pfnote("yyparse", lineno);
+ y_entries();
+ }
+#ifdef GTAGS
+/* assembler */ else if ((cp[1] == 's' || cp[1] == 'S') && !cp[2]) {
+ asm_entries();
+ return;
+ }
+#endif
+/* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) {
+#ifdef GTAGS
+ if (rflag)
+ fprintf(stderr, "-r option is ignored in fortran file (Warning only)\n");
+#endif
+ if (PF_funcs())
+ return;
+ rewind(inf);
+ }
+ }
+#ifdef YACC
+ yaccfile = NO;
+#endif
+/* C */ c_entries();
+}
+
+#ifdef GTAGS
+#include <db.h>
+DB *db;
+
+void
+gtagopen()
+{
+ BTREEINFO info;
+ char *env;
+ char dbname[200];
+
+ strcpy(dbname, ".");
+ if ((env = getenv("GTAGDBPATH"))) {
+ strcpy(dbname, env);
+ }
+ strcat(dbname, "/GTAGS");
+
+ info.flags = 0;
+ info.cachesize = 500000;
+ info.maxkeypage = 0;
+ info.minkeypage = 0;
+ info.psize = 0;
+ info.compare = 0;
+ info.prefix = 0;
+ info.lorder = 0;
+
+#define O_RDONLY 0x0000 /* open for reading only */
+ db = dbopen(dbname, O_RDONLY, 0, DB_BTREE, &info);
+ if (db == 0)
+ errx(1, "GTAGS file needed");
+}
+int
+isdefined(skey)
+char *skey;
+{
+ DBT dat, key;
+ int status;
+
+ key.data = skey;
+ key.size = strlen(skey)+1;
+
+ status = (*db->get)(db, &key, &dat, 0);
+ switch (status) {
+ case RET_SUCCESS:
+ return(1); /* exist */
+ case RET_ERROR:
+ errx(1, "db->get failed");
+ case RET_SPECIAL: /* not exist */
+ break;
+ }
+ return 0;
+}
+void
+gtagclose()
+{
+ if (db->close(db))
+ errx(1, "GTAGS cannot close.(dbclose)");
+}
+#endif
diff --git a/contrib/global/gctags/ctags.h b/contrib/global/gctags/ctags.h
new file mode 100644
index 0000000..b1bb287
--- /dev/null
+++ b/contrib/global/gctags/ctags.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ctags.h 8.3 (Berkeley) 4/2/94
+ */
+
+#define bool char
+
+#define YES 1
+#define NO 0
+#define EOS '\0'
+
+#define ENDLINE 50 /* max length of pattern */
+#define MAXTOKEN 250 /* max size of single token */
+
+#ifndef LINE_MAX
+#define LINE_MAX 2048
+#endif
+
+#define SETLINE {++lineno;lineftell = ftell(inf);}
+#define GETC(op,exp) ((c = getc(inf)) op (int)exp)
+
+#define iswhite(arg) (_wht[(unsigned)arg]) /* T if char is white */
+#define begtoken(arg) (_btk[(unsigned)arg]) /* T if char can start token */
+#define intoken(arg) (_itk[(unsigned)arg]) /* T if char can be in token */
+#define endtoken(arg) (_etk[(unsigned)arg]) /* T if char ends tokens */
+#define isgood(arg) (_gd[(unsigned)arg]) /* T if char can be after ')' */
+
+typedef struct nd_st { /* sorting structure */
+ struct nd_st *left,
+ *right; /* left and right sons */
+ char *entry, /* function or type name */
+ *file, /* file name */
+ *pat; /* search pattern */
+ int lno; /* for -x option */
+ bool been_warned; /* set if noticed dup */
+} NODE;
+
+extern char *curfile; /* current input file name */
+extern NODE *head; /* head of the sorted binary tree */
+extern FILE *inf; /* ioptr for current input file */
+extern FILE *outf; /* ioptr for current output file */
+extern long lineftell; /* ftell after getc( inf ) == '\n' */
+extern int lineno; /* line number of current line */
+#ifdef GTAGS
+extern int eflag; /* -e: '{' at 0 column force function end */
+extern int Dflag; /* -D: allow duplicate entrys */
+extern int rflag; /* -r: function reference */
+#endif /* GTAGS */
+extern int dflag; /* -d: non-macro defines */
+extern int tflag; /* -t: create tags for typedefs */
+extern int vflag; /* -v: vgrind style index output */
+extern int wflag; /* -w: suppress warnings */
+extern int xflag; /* -x: cxref style output */
+extern bool _wht[], _etk[], _itk[], _btk[], _gd[];
+extern char lbuf[LINE_MAX];
+extern char *lbp;
+extern char searchar; /* ex search character */
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+
+int cicmp __P((char *));
+void getline __P((void));
+void pfnote __P((char *, int));
+int skip_key __P((int));
+void put_entries __P((NODE *));
+void toss_yysec __P((void));
+void l_entries __P((void));
+void y_entries __P((void));
+int PF_funcs __P((void));
+void c_entries __P((void));
+void skip_comment __P((void));
+#ifdef GTAGS
+void asm_entries __P((void));
+void gtagopen __P((void));
+int isdefined __P((char *));
+void gtagclose __P((void));
+#endif
diff --git a/contrib/global/gctags/err.c b/contrib/global/gctags/err.c
new file mode 100644
index 0000000..9d20812
--- /dev/null
+++ b/contrib/global/gctags/err.c
@@ -0,0 +1,217 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/* extern char *__progname; Program name, from crt0. */
+char *progname = "gctags";
+
+static FILE *err_file; /* file to use for error output */
+static void (*err_exit)(int);
+
+void
+err_set_file(void *fp)
+{
+ if (fp)
+ err_file = fp;
+ else
+ err_file = stderr;
+}
+
+void
+err_set_exit(void (*ef)(int))
+{
+ err_exit = ef;
+}
+
+void
+#ifdef __STDC__
+err(int eval, const char *fmt, ...)
+#else
+err(eval, fmt, va_alist)
+ int eval;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ verr(eval, fmt, ap);
+ va_end(ap);
+}
+
+void
+verr(eval, fmt, ap)
+ int eval;
+ const char *fmt;
+ va_list ap;
+{
+ int sverrno;
+
+ sverrno = errno;
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", progname);
+ if (fmt != NULL) {
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, ": ");
+ }
+ (void)fprintf(err_file, "%s\n", strerror(sverrno));
+ if(err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+void
+#if __STDC__
+errx(int eval, const char *fmt, ...)
+#else
+errx(eval, fmt, va_alist)
+ int eval;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ verrx(eval, fmt, ap);
+ va_end(ap);
+}
+
+void
+verrx(eval, fmt, ap)
+ int eval;
+ const char *fmt;
+ va_list ap;
+{
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", progname);
+ if (fmt != NULL)
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, "\n");
+ if (err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+void
+#if __STDC__
+warn(const char *fmt, ...)
+#else
+warn(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vwarn(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarn(fmt, ap)
+ const char *fmt;
+ va_list ap;
+{
+ int sverrno;
+
+ sverrno = errno;
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", progname);
+ if (fmt != NULL) {
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, ": ");
+ }
+ (void)fprintf(err_file, "%s\n", strerror(sverrno));
+}
+
+void
+#ifdef __STDC__
+warnx(const char *fmt, ...)
+#else
+warnx(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarnx(fmt, ap)
+ const char *fmt;
+ va_list ap;
+{
+ if (! err_file)
+ err_set_file((FILE *)0);
+ (void)fprintf(err_file, "%s: ", progname);
+ if (fmt != NULL)
+ (void)vfprintf(err_file, fmt, ap);
+ (void)fprintf(err_file, "\n");
+}
diff --git a/contrib/global/gctags/fortran.c b/contrib/global/gctags/fortran.c
new file mode 100644
index 0000000..2a33aff
--- /dev/null
+++ b/contrib/global/gctags/fortran.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fortran.c 8.3 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+static void takeprec __P((void));
+
+char *lbp; /* line buffer pointer */
+
+int
+PF_funcs()
+{
+ bool pfcnt; /* pascal/fortran functions found */
+ char *cp;
+ char tok[MAXTOKEN];
+
+ for (pfcnt = NO;;) {
+ lineftell = ftell(inf);
+ if (!fgets(lbuf, sizeof(lbuf), inf))
+ return (pfcnt);
+ ++lineno;
+ lbp = lbuf;
+ if (*lbp == '%') /* Ratfor escape to fortran */
+ ++lbp;
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (!*lbp)
+ continue;
+ switch (*lbp | ' ') { /* convert to lower-case */
+ case 'c':
+ if (cicmp("complex") || cicmp("character"))
+ takeprec();
+ break;
+ case 'd':
+ if (cicmp("double")) {
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (!*lbp)
+ continue;
+ if (cicmp("precision"))
+ break;
+ continue;
+ }
+ break;
+ case 'i':
+ if (cicmp("integer"))
+ takeprec();
+ break;
+ case 'l':
+ if (cicmp("logical"))
+ takeprec();
+ break;
+ case 'r':
+ if (cicmp("real"))
+ takeprec();
+ break;
+ }
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (!*lbp)
+ continue;
+ switch (*lbp | ' ') {
+ case 'f':
+ if (cicmp("function"))
+ break;
+ continue;
+ case 'p':
+ if (cicmp("program") || cicmp("procedure"))
+ break;
+ continue;
+ case 's':
+ if (cicmp("subroutine"))
+ break;
+ default:
+ continue;
+ }
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (!*lbp)
+ continue;
+ for (cp = lbp + 1; *cp && intoken(*cp); ++cp)
+ continue;
+ if (cp == lbp + 1)
+ continue;
+ *cp = EOS;
+ (void)strcpy(tok, lbp);
+ getline(); /* process line for ex(1) */
+ pfnote(tok, lineno);
+ pfcnt = YES;
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * cicmp --
+ * do case-independent strcmp
+ */
+int
+cicmp(cp)
+ char *cp;
+{
+ int len;
+ char *bp;
+
+ for (len = 0, bp = lbp; *cp && (*cp &~ ' ') == (*bp++ &~ ' ');
+ ++cp, ++len)
+ continue;
+ if (!*cp) {
+ lbp += len;
+ return (YES);
+ }
+ return (NO);
+}
+
+static void
+takeprec()
+{
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (*lbp == '*') {
+ for (++lbp; isspace(*lbp); ++lbp)
+ continue;
+ if (!isdigit(*lbp))
+ --lbp; /* force failure */
+ else
+ while (isdigit(*++lbp))
+ continue;
+ }
+}
diff --git a/contrib/global/gctags/gctags.1 b/contrib/global/gctags/gctags.1
new file mode 100644
index 0000000..2d55d52
--- /dev/null
+++ b/contrib/global/gctags/gctags.1
@@ -0,0 +1,237 @@
+.\" Copyright (c) 1987, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)gctags.1 8.1 (Berkeley) 6/6/93
+.\"
+.Dd April 21, 1997
+.Dt GCTAGS 1
+.Os BSD 4
+.Sh NAME
+.Nm gctags
+.Nd create a tags file (special command for GLOBAL)
+.Sh SYNOPSIS
+.Nm gctags
+.Op Fl BDFadertuwvx
+.Op Fl f Ar tagsfile
+.Ar name ...
+.Sh DESCRIPTION
+.Nm Gctags
+makes a tags file for
+.Xr ex 1
+from the specified C,
+Pascal, Fortran,
+.Tn YACC ,
+lex, lisp and assembler sources.
+A tags file gives the locations of specified objects in a group of files.
+Each line of the tags file contains the object name, the file in which it
+is defined, and a search pattern for the object definition, separated by
+white-space.
+Using the
+.Ar tags
+file,
+.Xr ex 1
+can quickly locate these object definitions.
+Depending upon the options provided to
+.Nm gctags ,
+objects will consist of subroutines, typedefs, defines, structs,
+enums and unions.
+.Bl -tag -width Ds
+.It Fl B
+use backward searching patterns
+.Pq Li ?...? .
+.It Fl D
+allow duplicate object names.
+.It Fl F
+use forward searching patterns
+.Pq Li /.../
+(the default).
+.It Fl a
+append to
+.Ar tags
+file.
+.It Fl d
+create tags for
+.Li #defines
+that don't take arguments;
+.Li #defines
+that take arguments are tagged automatically.
+.It Fl e
+force a function to end when reach a '}' at the first column. (C source only)
+.It Fl f
+place the tag descriptions in a file called
+.Ar tagsfile .
+The default behavior is to place them in a file called
+.Ar tags .
+.It Fl r
+locate function references instead of function definitions. GTAGS file is
+needed at the current directory. (C source only)
+.It Fl t
+create tags for typedefs, structs, unions, and enums.
+.It Fl u
+update the specified files in the
+.Ar tags
+file, that is, all
+references to them are deleted, and the new values are appended to the
+file. (Beware: this option is implemented in a way which is rather
+slow; it is usually faster to simply rebuild the
+.Ar tags
+file.)
+.It Fl v
+An index of the form expected by
+.Xr vgrind 1
+is produced on the standard output. This listing
+contains the object name, file name, and page number (assuming 64
+line pages). Since the output will be sorted into lexicographic order,
+it may be desired to run the output through
+.Xr sort 1 .
+Sample use:
+.Bd -literal -offset indent
+gctags \-v files \&| sort \-f > index
+vgrind \-x index
+.Ed
+.It Fl w
+suppress warning diagnostics.
+.It Fl x
+.Nm gctags
+produces a list of object
+names, the line number and file name on which each is defined, as well
+as the text of that line and prints this on the standard output. This
+is a simple index which can be printed out as an off-line readable
+function index.
+.El
+.Pp
+Files whose names end in
+.Nm \&.c
+or
+.Nm \&.h
+are assumed to be C
+source files and are searched for C style routine and macro definitions.
+Files whose names end in
+.Nm \&.y
+are assumed to be
+.Tn YACC
+source files.
+Files whose names end in
+.Nm \&.l
+are assumed to be lisp files if their
+first non-blank character is `;', `(', or `[',
+otherwise, they are
+treated as lex files.
+Files whose names end in
+.Nm \&.s
+or
+.Nm \&.S
+are assumed to be Assembler
+source files. Other files are first examined to see if they
+contain any Pascal or Fortran routine definitions, and, if not, are
+searched for C style definitions.
+.Pp
+The tag
+.Li main
+is treated specially in C programs. The tag formed
+is created by prepending
+.Ar M
+to the name of the file, with the
+trailing
+.Nm \&.c
+and any leading pathname components removed. This
+makes use of
+.Nm gctags
+practical in directories with more than one
+program.
+.Pp
+Yacc and lex files each have a special tag.
+.Ar Yyparse
+is the start
+of the second section of the yacc file, and
+.Ar yylex
+is the start of
+the second section of the lex file.
+.Sh FILES
+.Bl -tag -width tags -compact
+.It Pa tags
+default output tags file
+.It Pa GTAGS
+tags file for GLOBAL
+.El
+.Sh DIAGNOSTICS
+.Nm Gctags
+exits with a value of 1 if an error occurred, 0 otherwise.
+Duplicate objects are not considered errors.
+.Sh SEE ALSO
+.Xr btreeop 1 ,
+.Xr ex 1 ,
+.Xr global 1 ,
+.Xr gtags 1 ,
+.Xr htags 1 ,
+.Xr vi 1 .
+.Sh BUGS
+.Pp
+Recognition of
+.Nm functions ,
+.Nm subroutines
+and
+.Nm procedures
+for
+.Tn FORTRAN
+and Pascal is done is a very simpleminded way. No attempt
+is made to deal with block structure; if you have two Pascal procedures
+in different blocks with the same name you lose.
+.Nm Gctags
+doesn't
+understand about Pascal types.
+.Pp
+The method of deciding whether to look for C, Pascal or
+.Tn FORTRAN
+functions is a hack.
+.Pp
+.Nm Gctags
+relies on the input being well formed, and any syntactical
+errors will completely confuse it. It also finds some legal syntax
+confusing; for example, since it doesn't understand
+.Li #ifdef Ns 's
+(incidentally, that's a feature, not a bug), any code with unbalanced
+braces inside
+.Li #ifdef Ns 's
+will cause it to become somewhat disoriented.
+In a similar fashion, multiple line changes within a definition will
+cause it to enter the last line of the object, rather than the first, as
+the searching pattern. The last line of multiple line
+.Li typedef Ns 's
+will similarly be noted.
+.Pp
+Assembler support is far from completeness. It extracts only ENTRY()
+and ALTENTRY() from source file. Probably valid only for FreeBSD and Linux
+kernel source.
+.Sh HISTORY
+The
+.Nm
+command appeared in FreeBSD 2.2.
diff --git a/contrib/global/gctags/lisp.c b/contrib/global/gctags/lisp.c
new file mode 100644
index 0000000..ebf5184
--- /dev/null
+++ b/contrib/global/gctags/lisp.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)lisp.c 8.3 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+/*
+ * lisp tag functions
+ * just look for (def or (DEF
+ */
+void
+l_entries()
+{
+ int special;
+ char *cp;
+ char savedc;
+ char tok[MAXTOKEN];
+
+ for (;;) {
+ lineftell = ftell(inf);
+ if (!fgets(lbuf, sizeof(lbuf), inf))
+ return;
+ ++lineno;
+ lbp = lbuf;
+ if (!cicmp("(def"))
+ continue;
+ special = NO;
+ switch(*lbp | ' ') {
+ case 'm':
+ if (cicmp("method"))
+ special = YES;
+ break;
+ case 'w':
+ if (cicmp("wrapper") || cicmp("whopper"))
+ special = YES;
+ }
+ for (; !isspace(*lbp); ++lbp)
+ continue;
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ for (cp = lbp; *cp && *cp != '\n'; ++cp)
+ continue;
+ *cp = EOS;
+ if (special) {
+ if (!(cp = strchr(lbp, ')')))
+ continue;
+ for (; cp >= lbp && *cp != ':'; --cp)
+ continue;
+ if (cp < lbp)
+ continue;
+ lbp = cp;
+ for (; *cp && *cp != ')' && *cp != ' '; ++cp)
+ continue;
+ }
+ else
+ for (cp = lbp + 1;
+ *cp && *cp != '(' && *cp != ' '; ++cp)
+ continue;
+ savedc = *cp;
+ *cp = EOS;
+ (void)strcpy(tok, lbp);
+ *cp = savedc;
+ getline();
+ pfnote(tok, lineno);
+ }
+ /*NOTREACHED*/
+}
diff --git a/contrib/global/gctags/print.c b/contrib/global/gctags/print.c
new file mode 100644
index 0000000..692d36b
--- /dev/null
+++ b/contrib/global/gctags/print.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)print.c 8.3 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ctags.h"
+
+/*
+ * getline --
+ * get the line the token of interest occurred on,
+ * prepare it for printing.
+ */
+void
+getline()
+{
+ long saveftell;
+ int c;
+ int cnt;
+ char *cp;
+
+ saveftell = ftell(inf);
+ (void)fseek(inf, lineftell, SEEK_SET);
+ if (xflag)
+ for (cp = lbuf; GETC(!=, '\n'); *cp++ = c)
+ continue;
+ /*
+ * do all processing here, so we don't step through the
+ * line more than once; means you don't call this routine
+ * unless you're sure you've got a keeper.
+ */
+ else for (cnt = 0, cp = lbuf; GETC(!=, EOF) && cnt < ENDLINE; ++cnt) {
+ if (c == '\\') { /* backslashes */
+ if (cnt > ENDLINE - 2)
+ break;
+ *cp++ = '\\'; *cp++ = '\\';
+ ++cnt;
+ }
+ else if (c == (int)searchar) { /* search character */
+ if (cnt > ENDLINE - 2)
+ break;
+ *cp++ = '\\'; *cp++ = c;
+ ++cnt;
+ }
+ else if (c == '\n') { /* end of keep */
+ *cp++ = '$'; /* can find whole line */
+ break;
+ }
+ else
+ *cp++ = c;
+ }
+ *cp = EOS;
+ (void)fseek(inf, saveftell, SEEK_SET);
+}
+
+/*
+ * put_entries --
+ * write out the tags
+ */
+void
+put_entries(node)
+ NODE *node;
+{
+
+ if (node->left)
+ put_entries(node->left);
+ if (vflag)
+ printf("%s %s %d\n",
+ node->entry, node->file, (node->lno + 63) / 64);
+ else if (xflag)
+#ifdef MODIFY
+ /* separate 'entry' and 'lno' */
+ if (strlen(node->entry) >= 16 && node->lno >= 1000)
+ printf("%-16s %4d %-16s %s\n",
+ node->entry, node->lno, node->file, node->pat);
+ else /* for compatibility */
+#endif
+ printf("%-16s%4d %-16s %s\n",
+ node->entry, node->lno, node->file, node->pat);
+ else
+ fprintf(outf, "%s\t%s\t%c^%s%c\n",
+ node->entry, node->file, searchar, node->pat, searchar);
+ if (node->right)
+ put_entries(node->right);
+}
diff --git a/contrib/global/gctags/test/ctags.test b/contrib/global/gctags/test/ctags.test
new file mode 100644
index 0000000..1f334ac
--- /dev/null
+++ b/contrib/global/gctags/test/ctags.test
@@ -0,0 +1,67 @@
+int bar = (1 + 5);
+
+FOO("here is a #define test: ) {");
+char sysent[20];
+int nsysent = sizeof (sysent) / sizeof (sysent[0]);
+/*
+ * now is the time for a comment.
+ * four lines in length...
+ */struct struct_xtra{int list;};r4(x,y){};typedef struct{int bar;}struct_xxe;
+#define FOO BAR
+struct struct_three {
+ int list;
+};
+#define SINGLE
+int BAD();
+enum color {red, green, gold, brown};
+char qq[] = " quote(one,two) {int bar;} ";
+typedef struct {
+ int bar;
+ struct struct_two {
+ int foo;
+ union union_3 {
+ struct struct_three entry;
+ char size[25];
+ };
+ struct last {
+ struct struct_three xentry;
+ char list[34];
+ };
+ };
+} struct_one;
+#define TWOLINE ((MAXLIST + FUTURE + 15) \
+ / (time_to_live ? 3 : 4))
+#if (defined(BAR))
+int bar;
+#endif
+#define MULTIPLE {\
+ multiple(one,two); \
+ lineno++; \
+ callroute(one,two); \
+}
+#if defined(BAR)
+int bar;
+#endif
+union union_one {
+ struct struct_three s3;
+ char foo[25];
+};
+#define XYZ(A,B) (A + B / 2) * (3 - 26 + l_lineno)
+routine1(one,two) /* comments here are fun... */
+ struct {
+ int entry;
+ char bar[34];
+ } *one;
+ char two[10];
+{
+typedef unsigned char u_char;
+ register struct buf *bp;
+ five(one,two);
+}
+ routine2 (one,two) { puts("hello\n"); }
+ routine3
+(one,
+two) { puts("world\n"); }
+routine4(int one, char (*two)(void)) /* test ANSI arguments */
+{
+}
diff --git a/contrib/global/gctags/tree.c b/contrib/global/gctags/tree.c
new file mode 100644
index 0000000..4d6f858
--- /dev/null
+++ b/contrib/global/gctags/tree.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tree.c 8.3 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <err.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ctags.h"
+
+static void add_node __P((NODE *, NODE *));
+static void free_tree __P((NODE *));
+
+/*
+ * pfnote --
+ * enter a new node in the tree
+ */
+void
+pfnote(name, ln)
+ char *name;
+ int ln;
+{
+ NODE *np;
+ char *fp;
+ char nbuf[MAXTOKEN];
+
+ /*NOSTRICT*/
+ if (!(np = (NODE *)malloc(sizeof(NODE)))) {
+ warnx("too many entries to sort");
+ put_entries(head);
+ free_tree(head);
+ /*NOSTRICT*/
+ if (!(head = np = (NODE *)malloc(sizeof(NODE))))
+ errx(1, "out of space");
+ }
+ if (!xflag && !strcmp(name, "main")) {
+ if (!(fp = strrchr(curfile, '/')))
+ fp = curfile;
+ else
+ ++fp;
+ (void)sprintf(nbuf, "M%s", fp);
+ fp = strrchr(nbuf, '.');
+ if (fp && !fp[2])
+ *fp = EOS;
+ name = nbuf;
+ }
+ if (!(np->entry = strdup(name)))
+ errx(1, "out of space");
+ np->file = curfile;
+ np->lno = ln;
+ np->left = np->right = 0;
+ if (!(np->pat = strdup(lbuf)))
+ errx(1, "out of space");
+ if (!head)
+ head = np;
+ else
+ add_node(np, head);
+}
+
+static void
+add_node(node, cur_node)
+ NODE *node,
+ *cur_node;
+{
+ int dif;
+
+ dif = strcmp(node->entry, cur_node->entry);
+#ifdef GTAGS
+ if (!Dflag && !dif) /* -D option allows duplicate entries. */
+#else
+ if (!dif)
+#endif
+ {
+ if (node->file == cur_node->file) {
+ if (!wflag)
+ fprintf(stderr, "Duplicate entry in file %s, line %d: %s\nSecond entry ignored\n", node->file, lineno, node->entry);
+ return;
+ }
+ if (!cur_node->been_warned)
+ if (!wflag)
+ fprintf(stderr, "Duplicate entry in files %s and %s: %s (Warning only)\n", node->file, cur_node->file, node->entry);
+ cur_node->been_warned = YES;
+ }
+ else if (dif < 0)
+ if (cur_node->left)
+ add_node(node, cur_node->left);
+ else
+ cur_node->left = node;
+ else if (cur_node->right)
+ add_node(node, cur_node->right);
+ else
+ cur_node->right = node;
+}
+
+static void
+free_tree(node)
+ NODE *node;
+{
+ while (node) {
+ if (node->right)
+ free_tree(node->right);
+ free(node);
+ node = node->left;
+ }
+}
diff --git a/contrib/global/gctags/yacc.c b/contrib/global/gctags/yacc.c
new file mode 100644
index 0000000..9dcdd5a
--- /dev/null
+++ b/contrib/global/gctags/yacc.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)yacc.c 8.3 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+/*
+ * y_entries:
+ * find the yacc tags and put them in.
+ */
+void
+y_entries()
+{
+ int c;
+ char *sp;
+ bool in_rule;
+ char tok[MAXTOKEN];
+
+ in_rule = NO;
+
+ while (GETC(!=, EOF))
+ switch (c) {
+ case '\n':
+ SETLINE;
+ /* FALLTHROUGH */
+ case ' ':
+ case '\f':
+ case '\r':
+ case '\t':
+ break;
+ case '{':
+ if (skip_key('}'))
+ in_rule = NO;
+ break;
+ case '\'':
+ case '"':
+ if (skip_key(c))
+ in_rule = NO;
+ break;
+ case '%':
+ if (GETC(==, '%'))
+ return;
+ (void)ungetc(c, inf);
+ break;
+ case '/':
+ if (GETC(==, '*'))
+ skip_comment();
+ else
+ (void)ungetc(c, inf);
+ break;
+ case '|':
+ case ';':
+ in_rule = NO;
+ break;
+ default:
+ if (in_rule || (!isalpha(c) && c != '.' && c != '_'))
+ break;
+ sp = tok;
+ *sp++ = c;
+ while (GETC(!=, EOF) && (intoken(c) || c == '.'))
+ *sp++ = c;
+ *sp = EOS;
+ getline(); /* may change before ':' */
+ while (iswhite(c)) {
+ if (c == '\n')
+ SETLINE;
+ if (GETC(==, EOF))
+ return;
+ }
+ if (c == ':') {
+ pfnote(tok, lineno);
+ in_rule = YES;
+ }
+ else
+ (void)ungetc(c, inf);
+ }
+}
+
+/*
+ * toss_yysec --
+ * throw away lines up to the next "\n%%\n"
+ */
+void
+toss_yysec()
+{
+ int c; /* read character */
+ int state;
+
+ /*
+ * state == 0 : waiting
+ * state == 1 : received a newline
+ * state == 2 : received first %
+ * state == 3 : recieved second %
+ */
+ lineftell = ftell(inf);
+ for (state = 0; GETC(!=, EOF);)
+ switch (c) {
+ case '\n':
+ ++lineno;
+ lineftell = ftell(inf);
+ if (state == 3) /* done! */
+ return;
+ state = 1; /* start over */
+ break;
+ case '%':
+ if (state) /* if 1 or 2 */
+ ++state; /* goto 3 */
+ break;
+ default:
+ state = 0; /* reset */
+ break;
+ }
+}
diff --git a/contrib/global/global/Makefile b/contrib/global/global/Makefile
new file mode 100644
index 0000000..256ea71
--- /dev/null
+++ b/contrib/global/global/Makefile
@@ -0,0 +1,9 @@
+# @(#)Makefile 1.0 (Berkeley) 4/21/96
+
+MAN1= global.1
+
+beforeinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/global.pl ${DESTDIR}/usr/bin/global
+
+.include <bsd.prog.mk>
diff --git a/contrib/global/global/Makefile.generic b/contrib/global/global/Makefile.generic
new file mode 100644
index 0000000..fe735da
--- /dev/null
+++ b/contrib/global/global/Makefile.generic
@@ -0,0 +1,13 @@
+# @(#)Makefile 29-Dec-96
+
+PROG = global
+BINDIR = /usr/bin
+MANDIR = /usr/share/man
+
+all:
+install:
+ cp $(PROG).pl $(BINDIR)/$(PROG)
+ chmod 755 $(BINDIR)/$(PROG)
+ cp $(PROG).1 $(MANDIR)/man1
+ chmod 644 $(MANDIR)/man1/$(PROG).1
+clean:
diff --git a/contrib/global/global/global.1 b/contrib/global/global/global.1
new file mode 100644
index 0000000..be81dd9
--- /dev/null
+++ b/contrib/global/global/global.1
@@ -0,0 +1,149 @@
+.\"
+.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Shigio Yamaguchi.
+.\" 4. Neither the name of the author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd April 21, 1997
+.Dt GLOBAL 1
+.Os BSD 4
+.Sh NAME
+.Nm global
+.Nd print the locations of specified function.
+.Sh SYNOPSIS
+.Nm global
+.Op Fl arx
+.Ar name
+.Nm global -c
+.Op Ar name
+.Nm global
+.Op Fl a
+.Fl f
+.Ar file
+.Sh DESCRIPTION
+.Nm Global
+find the locations of specified function in C and Yacc source files.
+.Nm Global
+can treat a source tree, that is, a directory that has subdirectories and
+source files.
+You can get the relative path of objects from anywhere within the tree.
+
+.Nm Global
+can locate not only function definitions but also function references and
+allow duplicate entries too.
+.Pp
+In advance of using this command, you must execute
+.Xr gtags 1
+at the root directory of the source tree.
+.Pp
+The following options are available:
+.Bl -tag -width Ds
+.It Fl a
+print absolute path name. By default, print relative path name.
+.It Fl c Op Ar name
+print candidate function names which start with specified
+.Ar name .
+If
+.Ar name
+is not specified, print all function names.
+.It Fl f Ar file
+print all function definitions in the
+.Ar file .
+This option implies -x option.
+.It Fl r
+print the locations of function references. By default, print function
+definitions.
+.It Fl x
+In addition to the default output, produce the line number and
+the line contents.
+.It Ar name
+function name. It can include perl's regular expression.
+.Sh FILES
+.Bl -tag -width tags -compact
+.It Pa GTAGS
+tags file for function definitions.
+.It Pa GRTAGS
+tags file for function references.
+.El
+.Sh ENVIRONMENT
+The following environment variables affect the execution of global.
+.Pp
+.Bl -tag -width indent
+.It Ev GTAGSROOT
+The directory which is the root of source tree.
+.It Ev GTAGSDBPATH
+The directory on which gtags database exist. This value is ignored
+when GTAGSROOT is not defined.
+.It Ev GTAGSLIBPATH
+If this variable is set, its value is used as the path to search for library
+functions. If specified function is not found in a source tree,
+global search in these path too.
+.Sh EXAMPLES
+
+ % ls -F
+ Makefile src/ lib/
+ % gtags
+ % global main
+ src/main.c
+ % global -x main
+ main 10 src/main.c main (argc, argv) {
+ % global -x '^[sg]et'
+ set_num 20 lib/util.c set_num(values)
+ get_num 30 lib/util.c get_num() {
+ % global -rx '^[sg]et'
+ set_num 113 src/op.c set_num(32);
+ set_num 225 src/opop.c if (set_num(0) > 0) {
+ get_num 90 src/op.c while (get_num() > 0) {
+ % cd lib
+ % global -rx '^[sg]et'
+ set_num 113 ../src/op.c set_num(32);
+ set_num 225 ../src/opop.c if (set_num(0) > 0) {
+ get_num 90 ../src/op.c while (get_num() > 0) {
+ % global strlen
+ % (cd /usr/src/sys; gtags)
+ % setenv GTAGSLIBPATH /usr/src/sys
+ % global strlen
+ ../../../usr/src/sys/libkern/strlen.c
+ % (cd /usr/src/lib; gtags)
+ % setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys
+ % global strlen
+ ../../../usr/src/lib/libc/string/strlen.c
+
+.Sh DIAGNOSTICS
+.Nm Global
+exits with a non 0 value if an error occurred, 0 otherwise.
+.Sh SEE ALSO
+.Xr btreeop 1 ,
+.Xr gctags 1 ,
+.Xr gtags 1 ,
+.Xr htags 1 .
+.Sh AUTHORS
+Shigio Yamaguchi (shigio@wafu.netgate.net)
+.Sh HISTORY
+The
+.Nm
+command appeared in FreeBSD 2.2.
diff --git a/contrib/global/global/global.pl b/contrib/global/global/global.pl
new file mode 100644
index 0000000..571bddb
--- /dev/null
+++ b/contrib/global/global/global.pl
@@ -0,0 +1,302 @@
+#!/usr/bin/perl
+#
+# Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Shigio Yamaguchi.
+# 4. Neither the name of the author nor the names of any co-contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# global.pl 7-Jul-97
+#
+sub getcwd {
+ local($dir);
+ chop($dir = `/bin/pwd`);
+ $dir;
+}
+sub regexp {
+ $_[0] =~ /[][.*\^\$+?|(){}\\]/; # include regular expression ?
+}
+$com = $0;
+$com =~ s/.*\///;
+$usage = "usage:\t$com [-a][-r][-x] pattern\n\t$com -c [name]\n\t$com [-a] -f file\n";
+$ENV{'PATH'} = '/bin:/usr/bin';
+#
+# options check
+#
+while ($ARGV[0] =~ /^-/) {
+ $opt = shift;
+ if ($opt =~ /a/) { $aflag = 1; }
+ if ($opt =~ /c/) { $cflag = 1; }
+ if ($opt =~ /f/) { $fflag = 1; }
+ if ($opt =~ /r/) { $rflag = 1; }
+ if ($opt =~ /x/) { $xflag = 1; }
+}
+# -f option is valid when it is only one except for -a and -x option
+if ($fflag && ($cflag || $rflag)) {
+ $fflag = 0;
+}
+# -c option is valid when it is only one
+if ($cflag && ($aflag || $fflag || $rflag || $xflag)) {
+ $cflag = 0;
+}
+if (@ARGV == 0) {
+ die($usage) if (! $cflag);
+}
+if ($cflag && &regexp($ARGV[0])) {
+ die "$com: regular expression not allowed with -c option.\n";
+}
+$ARGV[0] =~ s/^[ \t]+//; # remove leading blanks
+#
+# get $dbpath and $root
+#
+local($dbpath, $root) = &getdbpath();
+#
+# recognize format version of GTAGS. 'format version record' is saved as a
+# META record in GTAGS and GRTAGS. if 'format version record' is not found,
+# it's assumed version 1.
+ $support_version = 1; # accept this format version
+#
+open(GTAGS, "btreeop -K ' __.VERSION' $dbpath/GTAGS |") || die "$com: GTAGS not found.\n";
+$rec = <GTAGS>;
+close(GTAGS);
+if ($rec =~ /^ __\.VERSION[ \t]+([0-9]+)$/) {
+ $format_version = $1;
+} else {
+ $format_version = 1;
+}
+if ($format_version > $support_version) {
+ die "$com: GTAGS seems new format. Please install the latest GLOBAL.\n";
+}
+#
+# complete function name
+#
+if ($cflag) {
+ open(PIPEIN, "btreeop -L $dbpath/GTAGS |") || die "$com: btreeop cannot exec.\n";
+ while (<PIPEIN>) {
+ print if (@ARGV == 0 || $_ =~ /^$ARGV[0]/o);
+ }
+ close(PIPEIN);
+ exit(0);
+}
+#
+# make path filter.
+#
+if ($aflag) {
+ @com = ("-e 's!\\.!$root!'"); # absolute
+} else {
+ @com = &relative_filter($root); # relative
+}
+#
+# print function definitions.
+#
+if ($fflag) {
+ if (! -f $ARGV[0]) { die "$com: file '$ARGV[0]' not exist.\n"; }
+ $path = &realpath($ARGV[0]);
+ $path =~ s/^$root/./;
+ chdir($root) || die "$com: cannot move to directory '$root'.\n";
+ system("gctags -Dex '$path' | sort +1n -2 | sed @com");
+ exit(0);
+}
+#
+# search in current source tree.
+#
+$cnt = &search($ARGV[0], $dbpath, @com);
+#
+# search in library path.
+#
+if ($cnt == 0 && ! &regexp($ARGV[0]) && ! $rflag && defined($ENV{'GTAGSLIBPATH'})) {
+ local($cwd) = &getcwd;
+ foreach $lib (split(':', $ENV{'GTAGSLIBPATH'})) {
+ next unless (-f "$lib/GTAGS");
+ next if ($dbpath eq $lib);
+ chdir($lib) || die "$com: cannot chdir to $lib.\n";
+ $root = $dbpath = &getcwd;
+ if ($aflag) {
+ @com = ("-e 's!\\.!$root!'");
+ } else {
+ $common = &common($root, $cwd);
+ $up = $root;
+ $up =~ s/$common//;
+ $down = $cwd;
+ $down =~ s/$common//;
+ $down =~ s![^/]+!..!g;
+ next if ($down eq '' || $up eq '');
+ @com = ("-e 's!\\./!$down/$up/!'");
+ }
+ $cnt = &search($ARGV[0], $dbpath, @com);
+ last if ($cnt > 0);
+ }
+ chdir($cwd) || die "$com: cannot return current directory.\n";
+}
+exit(0);
+#
+# realpath: get absolute path name
+#
+# r) absolute path
+#
+sub realpath {
+ local($path) = @_;
+ local($dirname, $basename);
+ if ($path =~ m!^(.*)/([^/]*)$!) {
+ $dirname = $1;
+ $basename = $2;
+ } else {
+ $dirname = '.';
+ $basename = $path;
+ }
+ local($cwd) = &getcwd;
+ chdir($dirname) || die "$com: cannot move to '$dirname'.\n";
+ $path = &getcwd . '/' . $basename;
+ chdir($cwd) || die "$com: cannot return to '$cwd'.\n";
+ $path;
+}
+#
+# getdbpath: get dbpath and root directory
+#
+# r) ($dbpath, $root)
+#
+sub getdbpath {
+ local($dbpath, $root);
+ local($cwd) = &getcwd;
+
+ if (defined($ENV{'GTAGSROOT'})) {
+ $dbpath = $root = $ENV{'GTAGSROOT'};
+ if (defined($ENV{'GTAGSDBPATH'})) {
+ $dbpath = $ENV{'GTAGSDBPATH'};
+ }
+ $root =~ /^\// || die "$com: GTAGSROOT must be an absolute path.\n";
+ $dbpath =~ /^\// || die "$com: GTAGSDBPATH must be an absolute path.\n";
+ chdir($root) || die "$com: directory $root not found.\n";
+ $root = &getcwd;
+ chdir($cwd);
+ chdir($dbpath) || die "$com: directory $dbpath not found.\n";
+ $dbpath = &getcwd;
+ if ($cwd !~ /^$root/) {
+ die "$com: you must be under GTAGSROOT.\n";
+ }
+ }
+ if (!$root) {
+ local($gtags) = 'GTAGS';
+ while (! -r $gtags && ! -r "obj/$gtags") {
+ if (&getcwd =~ m!^/$!) { die "$com: $gtags not found.\n"; }
+ chdir('..');
+ }
+ $dbpath = $root = &getcwd;
+ $dbpath = "$dbpath/obj" if (! -r $gtags);
+ }
+ chdir($cwd) || die "$com: cannot return current directory.\n";
+ ($dbpath, $root);
+}
+#
+# relative_filter: make relative path filter
+#
+# i) $root the root directory of source tree
+# r) @com sed command list
+#
+sub relative_filter {
+ local($root) = @_;
+ local($cwd) = &getcwd;
+ local($cur) = $cwd;
+
+ $cur =~ s!$root!!;
+ $cur =~ s!^/!!;
+ local(@step) = split('/', $cur);
+ local($downpath) = '\\.\\./' x @step;
+ local(@com);
+ push(@com, "-e 's!\\./!$downpath!'");
+ foreach $step (@step) {
+ push(@com, "-e 's!\\.\\./$step/!!'");
+ }
+ chdir($cwd) || die "$com: cannot return current directory.\n";
+ @com;
+}
+#
+# common: extract a common part of two paths.
+#
+# i) $p1, $p2 paths
+# r) common part
+#
+sub common {
+ local($p1, $p2) = @_;
+ local(@p1, @p2, @common, $common);
+
+ @p1 = split('/', $p1);
+ @p2 = split('/', $p2);
+ while (@p1 && @p2 && $p1[0] eq $p2[0]) {
+ push(@common, shift @p1);
+ shift @p2;
+ }
+ $common = join('/', @common);
+ $common .= '/';
+ $common;
+}
+#
+# search: search specified function
+#
+# i) $pattern search pattern
+# i) $dbpath where GTAGS exist
+# i) @com sed's command
+# gi) $xflag -x option
+# gi) $rflag -r option
+# r) count of output lines
+#
+sub search {
+ local($pattern, $dbpath, @com) = @_;
+ local($regex, $gtags, $outfilter, $infilter);
+ #
+ # make input filter
+ #
+ $gtags = ($rflag) ? 'GRTAGS' : 'GTAGS';
+ if ($regex = &regexp($pattern)) { # regular expression
+ $infilter = "btreeop $dbpath/$gtags |";
+ } else {
+ $infilter = "btreeop -K '$pattern' $dbpath/$gtags |";
+ }
+ #
+ # make output filter
+ # gtags fields is same to ctags -x format.
+ # 0:tag, 1:lineno, 2:filename, 3: pattern.
+ #
+ if ($xflag) {
+ $outfilter = "| sort +0 -1 +2 -3 +1n -2";
+ } else {
+ $outfilter = "| awk '{print \$3}' | sort | uniq";
+ }
+ $outfilter .= "| sed @com";
+ open(PIPEIN, $infilter) || die "$com: database not found.\n";
+ open(PIPEOUT, $outfilter) || die "$com: pipe cannot open.\n";
+ local($cnt) = 0;
+ while (<PIPEIN>) {
+ local($tag) = split;
+ if (! $regex || $tag =~ /$pattern/o) {
+ $cnt++;
+ print PIPEOUT $_;
+ }
+ }
+ close(PIPEIN);
+ close(PIPEOUT);
+ $cnt;
+}
diff --git a/contrib/global/gtags.el b/contrib/global/gtags.el
new file mode 100644
index 0000000..0978638
--- /dev/null
+++ b/contrib/global/gtags.el
@@ -0,0 +1,298 @@
+;;; gtags.el --- gtags facility for Emacs
+
+;;
+;; Copyright (c) 1997 Shigio Yamaguchi. All rights reserved.
+;;
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions
+;; are met:
+;; 1. Redistributions of source code must retain the above copyright
+;; notice, this list of conditions and the following disclaimer.
+;; 2. Redistributions in binary form must reproduce the above copyright
+;; notice, this list of conditions and the following disclaimer in the
+;; documentation and/or other materials provided with the distribution.
+;; 3. All advertising materials mentioning features or use of this software
+;; must display the following acknowledgement:
+;; This product includes software developed by Shigio Yamaguchi.
+;; 4. Neither the name of the author nor the names of any co-contributors
+;; may be used to endorse or promote products derived from this software
+;; without specific prior written permission.
+;;
+;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+;; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+;; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+;; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+;; SUCH DAMAGE.
+;;
+;; gtags.el 6-Jul-97
+;;
+
+;; This file is part of GLOBAL.
+;; Author: Shigio Yamaguchi <shigio@wafu.netgate.net>
+;; Version: 1.0
+;; Keywords: tools
+
+;;; Code
+
+(defvar gtags-buffer-stack nil
+ "Stack for tag browsing.")
+(defvar gtags-point-stack nil
+ "Stack for tag browsing.")
+(defvar gtags-complete-list nil
+ "Gtags complete list.")
+(defconst symbol-regexp "[A-Za-z_][A-Za-z_0-9]*"
+ "Regexp matching tag name.")
+(defconst definition-regexp "#[ \t]*define[ \t]+\\|ENTRY(\\|ALTENTRY("
+ "Regexp matching tag definition name.")
+(defvar gtags-read-only nil
+ "Gtags read only mode")
+(defvar gtags-mode-map (make-sparse-keymap)
+ "Keymap used in gtags mode.")
+(define-key gtags-mode-map "\et" 'gtags-find-tag)
+(define-key gtags-mode-map "\er" 'gtags-find-rtag)
+(define-key gtags-mode-map "\C-]" 'gtags-find-tag-from-here)
+(define-key gtags-mode-map "\C-t" 'gtags-pop-stack)
+(define-key gtags-mode-map "\e." 'etags-style-find-tag)
+(define-key gtags-mode-map [mouse-2] 'gtags-find-tag-by-event)
+(define-key gtags-mode-map [mouse-3] 'gtags-pop-stack)
+
+(defvar gtags-select-mode-map (make-sparse-keymap)
+ "Keymap used in gtags select mode.")
+(define-key gtags-select-mode-map "q" 'gtags-pop-stack)
+(define-key gtags-select-mode-map "\C-t" 'gtags-pop-stack)
+(define-key gtags-select-mode-map "\C-m" 'gtags-select-tag)
+(define-key gtags-select-mode-map " " 'scroll-up)
+(define-key gtags-select-mode-map "\^?" 'scroll-down)
+(define-key gtags-select-mode-map "n" 'next-line)
+(define-key gtags-select-mode-map "p" 'previous-line)
+(define-key gtags-select-mode-map [mouse-2] 'gtags-select-tag-by-event)
+(define-key gtags-select-mode-map [mouse-3] 'gtags-pop-stack)
+
+;;
+;; utirity
+;;
+(defun match-string (n)
+ (buffer-substring (match-beginning n) (match-end n)))
+
+;; Return a default tag to search for, based on the text at point.
+(defun gtags-current-token ()
+ (cond
+ ((looking-at "[0-9A-Za-z_]")
+ (while (looking-at "[0-9A-Za-z_]")
+ (forward-char -1))
+ (forward-char 1))
+ (t
+ (while (looking-at "[ \t]")
+ (forward-char 1))))
+ (if (and (bolp) (looking-at definition-regexp))
+ (goto-char (match-end 0)))
+ (if (looking-at symbol-regexp)
+ (match-string 0) nil))
+
+;; push current context to stack
+(defun push-context ()
+ (setq gtags-buffer-stack (cons (current-buffer) gtags-buffer-stack))
+ (setq gtags-point-stack (cons (point) gtags-point-stack)))
+
+;; pop context from stack
+(defun pop-context ()
+ (if (not gtags-buffer-stack) nil
+ (let (buffer point)
+ (setq buffer (car gtags-buffer-stack))
+ (setq gtags-buffer-stack (cdr gtags-buffer-stack))
+ (setq point (car gtags-point-stack))
+ (setq gtags-point-stack (cdr gtags-point-stack))
+ (list buffer point))))
+
+;; if the buffer exist in the stack
+(defun exist-in-stack (buffer)
+ (memq buffer gtags-buffer-stack))
+
+;; is it a definition?
+(defun is-definition ()
+ (save-excursion
+ (if (bolp)
+ t
+ (forward-word -1)
+ (cond
+ ((looking-at "define")
+ (forward-char -1)
+ (while (and (not (bolp)) (looking-at "[ \t]"))
+ (forward-char -1))
+ (if (and (bolp) (looking-at "#"))
+ t nil))
+ ((looking-at "ENTRY\\|ALTENTRY")
+ (if (bolp) t nil))))))
+
+;;
+;; interactive command
+;;
+(defun gtags-find-tag ()
+ "Input tag name and move to the definition."
+ (interactive)
+ (let (tagname)
+ (setq tagname (completing-read ":tag " gtags-complete-list))
+ (push-context)
+ (gtags-goto-tag tagname t)))
+
+(defun etags-style-find-tag ()
+ "Input tag name and move to the definition.(etags style)"
+ (interactive)
+ (let (tagname prompt input)
+ (setq tagname (gtags-current-token))
+ (if tagname
+ (setq prompt (concat "Find tag: (default " tagname ") "))
+ (setq prompt "Find tag: "))
+ (setq input (completing-read prompt gtags-complete-list))
+ (if (not (equal "" input)) (setq tagname input))
+ (push-context)
+ (gtags-goto-tag tagname t)))
+
+(defun gtags-find-rtag ()
+ "Input tag name and move to the referenced point."
+ (interactive)
+ (let (tagname)
+ (setq tagname (completing-read ":rtag " gtags-complete-list))
+ (push-context)
+ (gtags-goto-tag tagname nil)))
+
+(defun gtags-find-tag-from-here ()
+ "Get the expression as a tagname around here and move there."
+ (interactive)
+ (let (tagname)
+ (setq tagname (gtags-current-token))
+ (if (not tagname)
+ nil
+ (push-context)
+ (gtags-goto-tag tagname (not (is-definition))))))
+
+(defun gtags-find-tag-by-event (event)
+ "Get the expression as a tagname around here and move there."
+ (interactive "e")
+ (select-window (posn-window (event-end event)))
+ (set-buffer (window-buffer (posn-window (event-end event))))
+ (goto-char (posn-point (event-end event)))
+ (let (tagname definition)
+ (setq definition nil)
+ (if (= 0 (count-lines (point-min) (point-max)))
+ (setq tagname "main")
+ (setq tagname (gtags-current-token))
+ (setq definition (is-definition)))
+ (if (not tagname)
+ nil
+ (push-context)
+ (gtags-goto-tag tagname (not definition)))))
+
+(defun gtags-select-tag ()
+ "Select a tagname in [GTAGS SELECT MODE] and move there."
+ (interactive)
+ (push-context)
+ (gtags-select-it nil))
+
+(defun gtags-select-tag-by-event (event)
+ "Select a tagname in [GTAGS SELECT MODE] and move there."
+ (interactive "e")
+ (select-window (posn-window (event-end event)))
+ (set-buffer (window-buffer (posn-window (event-end event))))
+ (goto-char (posn-point (event-end event)))
+ (push-context)
+ (gtags-select-it nil))
+
+(defun gtags-pop-stack ()
+ "Move to previous point on the stack."
+ (interactive)
+ (let (delete context buffer)
+ (if (not (exist-in-stack (current-buffer)))
+ (setq delete t))
+ (setq context (pop-context))
+ (if (not context)
+ (message "The tags stack is empty.")
+ (if delete
+ (kill-buffer (current-buffer)))
+ (switch-to-buffer (nth 0 context))
+ (goto-char (nth 1 context)))))
+
+;;
+;; common function
+;;
+
+;; goto tag's point
+(defun gtags-goto-tag (tagname definition)
+ (let (save flags buffer lines)
+ (setq save (current-buffer))
+ (if definition
+ (setq flags "") (setq flags "-r"))
+ ;; load tag
+ (setq buffer (generate-new-buffer (generate-new-buffer-name (concat (if (equal flags "") "(D)" "(R)") tagname))))
+ (set-buffer buffer)
+ (if (not (= 0 (call-process "global" nil t nil (concat "-ax" flags) tagname)))
+ (progn (message "cannot execute global.")
+ (pop-context))
+ (goto-char (point-min))
+ (setq lines (count-lines (point-min) (point-max)))
+ (cond
+ ((= 0 lines)
+ (message "%s: tag not found" tagname)
+ (pop-context)
+ (kill-buffer buffer)
+ (set-buffer save))
+ ((= 1 lines)
+ (gtags-select-it t))
+ (t
+ (switch-to-buffer buffer)
+ (gtags-select-mode))))))
+
+;; select a tag line from lines
+(defun gtags-select-it (delete)
+ (let (line file)
+ ;; get context from current tag line
+ (beginning-of-line)
+ (if (not (looking-at "[A-Za-z_][A-Za-z_0-9]*[ \t]+\\([0-9]+\\)[ \t]\\([^ \t]+\\)[ \t]"))
+ (pop-context)
+ (setq line (string-to-number (match-string 1)))
+ (setq file (match-string 2))
+ (if delete (kill-buffer (current-buffer)))
+ ;; move to the context
+ (if gtags-read-only (find-file-read-only file) (find-file file))
+ (goto-line line)
+ (use-local-map gtags-mode-map))))
+
+;; make complete list
+(defun make-gtags-complete-list ()
+ (save-excursion
+ (setq gtags-complete-list (make-vector 63 0))
+ (set-buffer (generate-new-buffer "*Completions*"))
+ (call-process "global" nil t nil "-c")
+ (goto-char (point-min))
+ (while (looking-at symbol-regexp)
+ (intern (match-string 0) gtags-complete-list)
+ (forward-line))
+ (kill-buffer (current-buffer))))
+
+;;;###autoload
+(defun gtags-mode ()
+ "Minor mode for browsing C source using GLOBAL."
+ (interactive)
+ (make-gtags-complete-list)
+ (use-local-map gtags-mode-map)
+ (run-hooks 'gtags-mode-hook))
+
+;; make gtags select mode
+(defun gtags-select-mode ()
+ "Major mode for choosing a tag from tags list."
+ (setq buffer-read-only t
+ major-mode 'gtags-select-mode
+ mode-name "Gtags Select")
+ (use-local-map gtags-select-mode-map)
+ (setq truncate-lines t)
+ (goto-char (point-min))
+ (message "[GTAGS SELECT MODE] %d lines" (count-lines (point-min) (point-max)))
+ (run-hooks 'gtags-select-mode-hook))
+
+;;; gtags.el ends here
diff --git a/contrib/global/gtags/Makefile b/contrib/global/gtags/Makefile
new file mode 100644
index 0000000..b45de63
--- /dev/null
+++ b/contrib/global/gtags/Makefile
@@ -0,0 +1,9 @@
+# @(#)Makefile 1.0 (Berkeley) 4/21/96
+
+MAN1= gtags.1
+
+beforeinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/gtags.pl ${DESTDIR}/usr/bin/gtags
+
+.include <bsd.prog.mk>
diff --git a/contrib/global/gtags/Makefile.generic b/contrib/global/gtags/Makefile.generic
new file mode 100644
index 0000000..61a5d89
--- /dev/null
+++ b/contrib/global/gtags/Makefile.generic
@@ -0,0 +1,13 @@
+# @(#)Makefile 29-Dec-96
+
+PROG = gtags
+BINDIR = /usr/bin
+MANDIR = /usr/share/man
+
+all:
+install:
+ cp $(PROG).pl $(BINDIR)/$(PROG)
+ chmod 755 $(BINDIR)/$(PROG)
+ cp $(PROG).1 $(MANDIR)/man1
+ chmod 644 $(MANDIR)/man1/$(PROG).1
+clean:
diff --git a/contrib/global/gtags/gtags.1 b/contrib/global/gtags/gtags.1
new file mode 100644
index 0000000..c7fddf0
--- /dev/null
+++ b/contrib/global/gtags/gtags.1
@@ -0,0 +1,86 @@
+.\"
+.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Shigio Yamaguchi.
+.\" 4. Neither the name of the author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd April 21, 1997
+.Dt GTAGS 1
+.Os BSD 4
+.Sh NAME
+.Nm gtags
+.Nd create GTAGS, GRTAGS file
+.Sh SYNOPSIS
+.Nm gtags
+.Op Fl e
+.Op Fl s
+.Op Ar dbpath
+.Sh DESCRIPTION
+.Nm Gtags
+makes GTAGS, GRTAGS files for global(1).
+.Nm Gtags
+trace subdirectories, read source files,
+locate the functions and save the information into tag files.
+C, yacc and assembler source files are supported.
+You should execute this command at the root of the source tree.
+.Pp
+If your source directory is on a read only device like CDROM, specify
+.Ar dbpath
+of the directory on which make tags files.
+.Pp
+.Bl -tag -width Ds
+.It Fl e
+force a function to end when reach a '}' at the first column in C source file.
+.It Fl s
+treat assembler source file (*.s, *.S).
+.Sh FILES
+.Bl -tag -width tags -compact
+.It Pa GTAGS
+tags file for function definitions.
+.It Pa GRTAGS
+tags file for function references.
+.El
+.Sh DIAGNOSTICS
+.Nm Gtags
+exits with a value of 1 if an error occurred, 0 otherwise.
+.Sh SEE ALSO
+.Xr btreeop 1 ,
+.Xr gctags 1 ,
+.Xr global 1 ,
+.Xr htags 1 .
+.Sh BUG
+GTAGS, GRTAGS are very large. In advance, check the space of your disk.
+
+Assembler support is far from completeness. It extracts only ENTRY()
+and ALTENTRY() from source file. Probably valid only for FreeBSD and Linux
+kernel source.
+.Sh AUTHORS
+Shigio Yamaguchi (shigio@wafu.netgate.net)
+.Sh HISTORY
+The
+.Nm
+command appeared in FreeBSD 2.2.
diff --git a/contrib/global/gtags/gtags.pl b/contrib/global/gtags/gtags.pl
new file mode 100644
index 0000000..20c5877
--- /dev/null
+++ b/contrib/global/gtags/gtags.pl
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+#
+# Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Shigio Yamaguchi.
+# 4. Neither the name of the author nor the names of any co-contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# gtags.pl 5-Jul-97
+#
+$com = $0;
+$com =~ s/.*\///;
+$usage = "usage: $com [-e][-s][dbpath]";
+$ENV{'PATH'} = '/bin:/usr/bin';
+#
+# ctags flag
+#
+$eflag = $sflag = '';
+while ($ARGV[0] =~ /^-/) {
+ $opt = shift;
+ if ($opt =~ /[^-es]/) { die "$usage\n"; }
+ if ($opt =~ /e/) { $eflag = 'e'; }
+ if ($opt =~ /s/) { $sflag = 's'; }
+}
+$dbpath = '.';
+$dbpath = $ARGV[0] if ($ARGV[0]);
+if (-f "$dbpath/GTAGS" && -f "$dbpath/GRTAGS") {
+ if (! -w "$dbpath/GTAGS") {
+ die "$com: cannot write to GTAGS.\n";
+ } elsif (! -w "$dbpath/GRTAGS") {
+ die "$com: cannot write to GRTAGS.\n";
+ }
+} elsif (! -w "$dbpath") {
+ die "$com: cannot write to the directory '$dbpath'.\n"
+}
+#
+# make global database
+#
+foreach $db ('GTAGS', 'GRTAGS') {
+ # currently only *.c *.h *.y are supported.
+ # *.s *.S is valid only when -s option specified.
+ open(FIND, "find . -type f -name '*.[chysS]' -print |") || die "$com: cannot exec find.\n";
+ open(DB, "|btreeop -C $dbpath/$db") || die "$com: cannot create db file '$dbpath/$db'.\n";
+ while (<FIND>) {
+ chop;
+ next if /(y\.tab\.c|y\.tab\.h)$/;
+ next if /(\/SCCS\/|\/RCS\/)/;
+ next if (/\.[sS]$/ && (!$sflag || $db eq 'GRTAGS'));
+
+ $flag = ($db eq 'GRTAGS') ? "${eflag}Dxr" : "${eflag}Dx";
+ $ENV{'GTAGDBPATH'} = $dbpath;
+ open(TAGS, "gctags -$flag $_ |") || die "$com: cannot read '$_'.\n";
+ while (<TAGS>) {
+ print DB;
+ }
+ close(TAGS);
+ }
+ close(DB);
+ close(FIND);
+}
+exit 0;
diff --git a/contrib/global/htags/Makefile b/contrib/global/htags/Makefile
new file mode 100644
index 0000000..f53639a
--- /dev/null
+++ b/contrib/global/htags/Makefile
@@ -0,0 +1,9 @@
+# @(#)Makefile 1.0 (Berkeley) 4/21/96
+
+MAN1= htags.1
+
+beforeinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/htags.pl ${DESTDIR}/usr/bin/htags
+
+.include <bsd.prog.mk>
diff --git a/contrib/global/htags/Makefile.generic b/contrib/global/htags/Makefile.generic
new file mode 100644
index 0000000..18a584a
--- /dev/null
+++ b/contrib/global/htags/Makefile.generic
@@ -0,0 +1,13 @@
+# @(#)Makefile 29-Dec-96
+
+PROG = htags
+BINDIR = /usr/bin
+MANDIR = /usr/share/man
+
+all:
+install:
+ cp $(PROG).pl $(BINDIR)/$(PROG)
+ chmod 755 $(BINDIR)/$(PROG)
+ cp $(PROG).1 $(MANDIR)/man1
+ chmod 644 $(MANDIR)/man1/$(PROG).1
+clean:
diff --git a/contrib/global/htags/htags.1 b/contrib/global/htags/htags.1
new file mode 100644
index 0000000..cbe356b
--- /dev/null
+++ b/contrib/global/htags/htags.1
@@ -0,0 +1,124 @@
+.\"
+.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Shigio Yamaguchi.
+.\" 4. Neither the name of the author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd June 28, 1997
+.Dt HTAGS 1
+.Os BSD 4
+.Sh NAME
+.Nm htags
+.Nd generate hypertext from C and Yacc source code
+.Sh SYNOPSIS
+.Nm htags
+.Op Fl a
+.Op Fl f
+.Op Fl l
+.Op Fl n
+.Op Fl v
+.Op Fl w
+.Op Fl d Ar tagdir
+.Op Fl t Ar title
+.Op Ar dir
+.Sh DESCRIPTION
+.Nm Htags
+makes hypertext from C and Yacc source code using GLOBAL database (GTAGS, GRTAGS).
+.Pp
+In advance of using this command, you must execute
+.Xr gtags 1
+at the root directory of the source tree.
+Then you can execute
+.Nm htags
+at the same place.
+.Nm Htags
+makes HTML directory and generate hypertext in it.
+.Pp
+You can start browsing from 'HTML/index.html'.
+Once hypertext generated, you can move it anywhere and browse it
+by any browsers.
+.Pp
+.br
+.Bl -tag -width Ds
+.It Fl a
+make an alphabetical function index. It's suitable for large project.
+.It Fl f
+support input form and dynamic index by CGI program.
+You need to setup HTTP server for it.
+.It Fl l
+make name tag(<A NAME=line number>) for each line so that outer hypertext
+can point any line of this hypertext.
+By default, make it only for lines which have referred object.
+.It Fl n
+print line number. By default, doesn't print it.
+.It Fl v
+verbose mode.
+.It Fl w
+print warning message.
+.It Fl d Ar tagdir
+the directory in which GTAGS and GRTAGS exist. Default is current directory.
+.It Fl t Ar title
+Tile of this hypertext. Default is the last conponent of current path.
+.It Ar dir
+the directory in which hypertext generated. Default is current directory.
+.Sh EXAMPLES
+ % cd /usr/src/sys
+ # gtags -se
+ # htags -fnvat 'Welcom to FreeBSD kernel source tour!'
+ % lynx HTML/index.html
+.Sh FILES
+.Bl -tag -width tags -compact
+.It Pa HTML/index.html
+Index file.
+.It Pa GTAGS
+tags file for function definitions.
+.It Pa GRTAGS
+tags file for function references.
+.El
+.Sh ENVIRONMENT
+The following environment variables affect the execution of htags.
+.Pp
+.Bl -tag -width indent
+.It Ev TMPDIR
+If this variable is set, its value is used as the directory to make temporary file.
+Default is /tmp.
+.Sh DIAGNOSTICS
+.Nm Htags
+exits with a value of 1 if an error occurred, 0 otherwise.
+.Sh SEE ALSO
+.Xr btreeop 1 ,
+.Xr gctags 1 ,
+.Xr global 1 ,
+.Xr gtags 1 .
+.Sh BUG
+Generated hypertext is VERY LARGE. In advance, check the space of your disk.
+.Sh AUTHORS
+Shigio Yamaguchi (shigio@wafu.netgate.net)
+.Sh HISTORY
+The
+.Nm
+command appeared in FreeBSD 2.2.
diff --git a/contrib/global/htags/htags.pl b/contrib/global/htags/htags.pl
new file mode 100644
index 0000000..7738f51
--- /dev/null
+++ b/contrib/global/htags/htags.pl
@@ -0,0 +1,1271 @@
+#!/usr/bin/perl
+#
+# Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Shigio Yamaguchi.
+# 4. Neither the name of the author nor the names of any co-contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# htags.pl 7-Jul-97
+#
+$com = $0;
+$com =~ s/.*\///;
+$usage = "usage: $com [-a][-f][-l][-n][-v][-w][-t title][-d tagdir][dir]";
+$ENV{'PATH'} = '/bin:/usr/bin';
+#-------------------------------------------------------------------------
+# CONFIGURATION
+#-------------------------------------------------------------------------
+# columns of line number
+$ncol = 4;
+# font
+$comment_begin = '<I><FONT COLOR=green>'; # /* ... */
+$comment_end = '</FONT></I>';
+$sharp_begin = '<FONT COLOR=darkred>'; # #define, #include or so on
+$sharp_end = '</FONT>';
+$brace_begin = '<FONT COLOR=blue>'; # { ... }
+$brace_end = '</FONT>';
+$reserved_begin = '<B>'; # if, while, for or so on
+$reserved_end = '</B>';
+# reserved words
+$reserved_words = "auto|break|case|char|continue|default|do|double|else|extern|float|for|goto|if|int|long|register|return|short|sizeof|static|struct|switch|typedef|union|unsigned|void|while";
+# temporary directory
+$tmp = '/tmp';
+if (defined($ENV{'TMPDIR'}) && -d $ENV{'TMPDIR'}) {
+ $tmp = $ENV{'TMPDIR'};
+}
+#-------------------------------------------------------------------------
+# DEFINITION
+#-------------------------------------------------------------------------
+# unit for a path
+$SEP = ' '; # source file path must not include $SEP charactor
+$ESCSEP = &escape($SEP);
+$SRCS = 'S';
+$DEFS = 'D';
+$REFS = 'R';
+$INCS = 'I';
+#-------------------------------------------------------------------------
+# JAVASCRIPT PARTS
+#-------------------------------------------------------------------------
+# escaped angle
+$langle = sprintf("unescape('%s')", &escape('<'));
+$rangle = sprintf("unescape('%s')", &escape('>'));
+# frame name
+$f_mains = 'mains'; # for main view
+$f_funcs = 'funcs'; # for function index
+$f_files = 'files'; # for file index
+$begin_script="<SCRIPT LANGUAGE=javascript>\n<!--\n";
+$end_script="<!-- end of script -->\n</SCRIPT>\n";
+$defaultview=
+ "// if your browser doesn't support javascript, write a BASE tag statically.\n" .
+ "if (parent.frames.length)\n" .
+ " document.write($langle+'BASE TARGET=$f_mains'+$rangle)\n";
+$rewrite_href_funcs =
+ "if (parent.frames.length && parent.$f_funcs == self) {\n" .
+ " document.links[0].href = '../funcs.html';\n" .
+ " document.links[document.links.length - 1].href = '../funcs.html';\n" .
+ "}\n";
+$rewrite_href_files =
+ "if (parent.frames.length && parent.$f_files == self) {\n" .
+ " document.links[0].href = '../files.html';\n" .
+ " document.links[document.links.length - 1].href = '../files.html';\n" .
+ "}\n";
+#-------------------------------------------------------------------------
+# UTIRITIES
+#-------------------------------------------------------------------------
+sub getcwd {
+ local($dir) = `/bin/pwd`;
+ chop($dir);
+ $dir;
+}
+sub date {
+ local($date) = `date`;
+ chop($date);
+ $date;
+}
+sub error {
+ local($msg) = @_;
+ &clean();
+ die "$com: " . $msg;
+}
+sub clean {
+ &anchor'finish();
+ &cache'close();
+}
+sub escape {
+ local($c) = @_;
+ '%' . sprintf("%x", ord($c));
+}
+sub usable {
+ local($com) = @_;
+
+ foreach $path (split(/:/, $ENV{'PATH'})) {
+ if (-x "$path/$com") {
+ return 1;
+ }
+ }
+ return 0;
+}
+sub copy {
+ local($from, $to) = @_;
+ local($ret);
+
+ $ret = system("cp $from $to");
+ $ret = $ret / 256;
+ $ret = ($ret == 0) ? 1 : 0;
+ $ret;
+}
+#-------------------------------------------------------------------------
+# PROCESS START
+#-------------------------------------------------------------------------
+#
+# options check ($sflag is set internally)
+#
+$aflag = $cflag = $fflag = $lflag = $nflag = $vflag = $wflag = $sflag = '';
+while ($ARGV[0] =~ /^-/) {
+ $opt = shift;
+ if ($opt =~ /[^-aflnvwtd]/) {
+ print STDERR "$usage\n";
+ exit 1;
+ }
+ if ($opt =~ /a/) { $aflag = 1; }
+ if ($opt =~ /f/) { $fflag = 1; }
+ if ($opt =~ /l/) { $lflag = 1; }
+ if ($opt =~ /n/) { $nflag = 1; }
+ if ($opt =~ /v/) { $vflag = 1; }
+ if ($opt =~ /w/) { $wflag = 1; }
+ if ($opt =~ /t/) {
+ $opt = shift;
+ last if ($opt eq '');
+ $title = $opt;
+ } elsif ($opt =~ /d/) {
+ $opt = shift;
+ last if ($opt eq '');
+ $dbpath = $opt;
+ }
+}
+if (!$title) {
+ @cwd = split('/', &getcwd);
+ $title = $cwd[$#cwd];
+}
+if (!$dbpath) {
+ $dbpath = &getcwd();
+}
+unless (-r "$dbpath/GTAGS" && -r "$dbpath/GRTAGS") {
+ &error("GTAGS and GRTAGS not found. please type 'gtags[RET]'\n");
+}
+#
+# recognize format version
+# if version record is not found, it's assumed version 1.
+#
+ $support_version = 1; # I can understand this format version
+#
+open(GTAGS, "btreeop -K ' __.VERSION' $dbpath/GTAGS |") || die "$com: GTAGS not found.\n";
+$rec = <GTAGS>;
+close(GTAGS);
+if ($rec =~ /^ __\.VERSION[ \t]+([0-9]+)$/) {
+ $format_version = $1;
+} else {
+ $format_version = 1;
+}
+if ($format_version != $support_version) {
+ die "$com: GTAGS format version unmatched. Please remake it.\n";
+}
+#
+# check directories
+#
+$html = &getcwd() . '/HTML';
+if ($ARGV[0]) {
+ $cwd = &getcwd();
+ unless (-w $ARGV[0]) {
+ &error("$ARGV[0] is not writable directory.\n");
+ }
+ chdir($ARGV[0]) || &error("directory $ARGV[0] not found.\n");
+ $html = &getcwd() . '/HTML';
+ chdir($cwd) || &error("cannot return directory.\n");
+}
+#
+# set sflag if *.[sS] are included.
+#
+open(CHECK, "btreeop $dbpath/GTAGS |") || &error("btreeop $dbpath/GTAGS failed.\n");
+while (<CHECK>) {
+ local($tag, $lno, $filename) = split;
+ if ($filename =~ /\.[sS]$/) {
+ $'sflag = 1;
+ last;
+ }
+}
+close(CHECK);
+#
+# check if GTAGS, GRTAGS is the latest.
+#
+$gtags_ctime = (stat("$dbpath/GTAGS"))[10];
+open(FIND, "find . -type f -name '*.[chysS]' -print |") || &error("cannot exec find.\n");
+while (<FIND>) {
+ chop;
+ next if /(y\.tab\.c|y\.tab\.h)$/;
+ next if (!$'sflag && /\.[sS]$/);
+ next if /(\/SCCS\/|\/RCS\/)/;
+ if ($gtags_ctime < (stat($_))[10]) {
+ print STDERR "Caution: GTAGS is not the latest one. You had better make new one.\n";
+ }
+}
+close(FIND);
+#-------------------------------------------------------------------------
+# MAKE FILES
+#-------------------------------------------------------------------------
+# HTML/cgi-bin/global.cgi ... CGI program (1)
+# HTML/help.html ... help file (2)
+# HTML/$REFS/* ... referencies (3)
+# HTML/$DEFS/* ... definitions (3)
+# HTML/funcs.html ... function index (4)
+# HTML/funcs/* ... function index (4)
+# HTML/files.html ... file index (5)
+# HTML/files/* ... file index (5)
+# HTML/index.html ... index file (6)
+# HTML/mains.html ... main index (7)
+# HTML/$SRCS/ ... source files (8)
+# HTML/$INCS/ ... include file index (9)
+#-------------------------------------------------------------------------
+print STDERR "[", &date, "] ", "Htags started\n" if ($vflag);
+#
+# (0) make directories
+#
+print STDERR "[", &date, "] ", "(1) making directories ...\n" if ($vflag);
+mkdir($html, 0777) || &error("cannot make directory <$html>.\n") if (! -d $html);
+foreach $d ($SRCS, $INCS, $DEFS, $REFS, files, funcs) {
+ mkdir("$html/$d", 0775) || &error("cannot make HTML directory\n") if (! -d "$html/$d");
+}
+if ($fflag) {
+ mkdir("$html/cgi-bin", 0775) || &error("cannot make cgi-bin directory\n") if (! -d "$html/cgi-bin");
+}
+#
+# (1) make CGI program
+#
+if ($fflag) {
+ print STDERR "[", &date, "] ", "(1) making CGI program ...\n" if ($vflag);
+ &makeprogram("$html/cgi-bin/global.cgi") || &error("cannot make CGI program.\n");
+ chmod(0755, "$html/cgi-bin/global.cgi") || &error("cannot chmod CGI program.\n");
+ unlink("$html/cgi-bin/GTAGS", "$html/cgi-bin/GRTAGS");
+ link("$dbpath/GTAGS", "$html/cgi-bin/GTAGS") || &copy("$dbpath/GTAGS", "$html/cgi-bin/GTAGS") || &error("cannot copy GTAGS.\n");;
+ link("$dbpath/GRTAGS", "$html/cgi-bin/GRTAGS") || &copy("$dbpath/GRTAGS", "$html/cgi-bin/GRTAGS") || &error("cannot copy GRTAGS.\n");;
+}
+#
+# (2) make help file
+#
+print STDERR "[", &date, "] ", "(2) making help.html ...\n" if ($vflag);
+&makehelp("$html/help.html");
+#
+# (3) make function entries ($DEFS/* and $REFS/*)
+# MAKING TAG CACHE
+#
+print STDERR "[", &date, "] ", "(3) making duplicate entries ...\n" if ($vflag);
+sub suddenly { &clean(); exit 1}
+$SIG{'INT'} = 'suddenly';
+$SIG{'QUIT'} = 'suddenly';
+$SIG{'TERM'} = 'suddenly';
+&cache'open(100000);
+$func_total = &makedupindex();
+print STDERR "Total $func_total functions.\n" if ($vflag);
+#
+# (4) make function index (funcs.html and funcs/*)
+# PRODUCE @funcs
+#
+print STDERR "[", &date, "] ", "(4) making function index ...\n" if ($vflag);
+$func_total = &makefuncindex("$html/funcs.html", $func_total);
+print STDERR "Total $func_total functions.\n" if ($vflag);
+#
+# (5) make file index (files.html and files/*)
+# PRODUCE @files %includes
+#
+print STDERR "[", &date, "] ", "(5) making file index ...\n" if ($vflag);
+$file_total = &makefileindex("$html/files.html", "$html/$INCS");
+print STDERR "Total $file_total files.\n" if ($vflag);
+#
+# [#] make a common part for mains.html and index.html
+# USING @funcs @files
+#
+print STDERR "[", &date, "] ", "(#) making a common part ...\n" if ($vflag);
+$index = &makecommonpart($title);
+#
+# (6)make index file (index.html)
+#
+print STDERR "[", &date, "] ", "(6) making index file ...\n" if ($vflag);
+&makeindex("$html/index.html", $title, $index);
+#
+# (7) make main index (mains.html)
+#
+print STDERR "[", &date, "] ", "(7) making main index ...\n" if ($vflag);
+&makemainindex("$html/mains.html", $index);
+#
+# (#) make anchor database
+#
+print STDERR "[", &date, "] ", "(#) making temporary database ...\n" if ($vflag);
+&anchor'create();
+#
+# (8) make HTML files ($SRCS/*)
+# USING TAG CACHE, %includes and anchor database.
+#
+print STDERR "[", &date, "] ", "(8) making hypertext from source code ...\n" if ($vflag);
+&makehtml($file_total);
+&clean();
+print STDERR "[", &date, "] ", "Done.\n" if ($vflag);
+exit 0;
+#-------------------------------------------------------------------------
+# SUBROUTINES
+#-------------------------------------------------------------------------
+#
+# makeprogram: make CGI program
+#
+sub makeprogram {
+ local($file) = @_;
+
+ open(PROGRAM, ">$file") || &error("cannot make CGI program.\n");
+ $program = <<'END_OF_SCRIPT';
+#!/usr/bin/perl
+#------------------------------------------------------------------
+# SORRY TO HAVE SURPRISED YOU!
+# IF YOU SEE THIS UNREASONABLE FILE WHILE BROUSING, FORGET PLEASE.
+# IF YOU ARE A ADMINISTRATOR OF THIS SITE, PLEASE SETUP HTTP SERVER
+# SO THAT THIS SCRIPT CAN BE EXECUTED AS A CGI COMMAND. THANK YOU.
+#------------------------------------------------------------------
+$SRCS = 'S';
+$SEP = ' '; # source file path must not include $SEP charactor
+$ESCSEP = &escape($SEP);
+sub escape {
+ local($c) = @_;
+ '%' . sprintf("%x", ord($c));
+}
+print "Content-type: text/html\n\n";
+print "<HTML>\n";
+@pairs = split (/&/, $ENV{'QUERY_STRING'});
+foreach $p (@pairs) {
+ ($name, $value) = split(/=/, $p);
+ $value =~ tr/+/ /;
+ $value =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("C", hex($1))/eg;
+ $form{$name} = $value;
+}
+if ($form{'pattern'} eq '') {
+ print "<H3>Pattern not specified. <A HREF=../mains.html>[return]</A></H3>\n";
+ print "</HTML>\n";
+ exit 0;
+}
+$pattern = $form{'pattern'};
+$flag = ($form{'type'} eq 'definition') ? '' : 'r';
+$words = ($form{'type'} eq 'definition') ? 'definitions' : 'referencies';
+print "<H1><FONT COLOR=#cc0000>\"$pattern\"</FONT></H1>\n";
+print "Following $words are matched to above pattern.<HR>\n";
+unless (open(PIPE, "/usr/bin/global -x$flag '$pattern' |")) {
+ print "<H3>Cannot execute global. <A HREF=../mains.html>[return]</A></H3>\n";
+ print "</HTML>\n";
+ exit 0;
+}
+$cnt = 0;
+print "<PRE>\n";
+while (<PIPE>) {
+ $cnt++;
+ local($tag, $lno, $filename) = split;
+ $filename =~ s/^\.\///;
+ $filename =~ s/\//$ESCSEP/g;
+ s/($tag)/<A HREF=..\/$SRCS\/$filename.html#$lno>$1<\/A>/;
+ print;
+}
+print "</PRE>\n";
+if ($cnt == 0) {
+ print "<H3>Pattern not found. <A HREF=../mains.html>[return]</A></H3>\n";
+}
+print "</HTML>\n";
+exit 0;
+#------------------------------------------------------------------
+# SORRY TO HAVE SURPRISED YOU!
+# IF YOU SEE THIS UNREASONABLE FILE WHILE BROUSING, FORGET PLEASE.
+# IF YOU ARE A ADMINISTRATOR OF THIS SITE, PLEASE SETUP HTTP SERVER
+# SO THAT THIS SCRIPT CAN BE EXECUTED AS A CGI COMMAND. THANK YOU.
+#------------------------------------------------------------------
+END_OF_SCRIPT
+
+ print PROGRAM $program;
+ close(PROGRAM);
+}
+#
+# makehelp: make help file
+#
+sub makehelp {
+ local($file) = @_;
+
+ open(HELP, ">$file") || &error("cannot make help file.\n");
+ print HELP "<HTML>\n<HEAD><TITLE>HELP</TITLE></HEAD>\n<BODY>\n";
+ print HELP "<H2>Usage of Links</H2>\n";
+ print HELP "<PRE>/* [&lt;][&gt;][^][v] [top][bottom][index][help] */</PRE>\n";
+ print HELP "<DL>\n";
+ print HELP "<DT>[&lt;]<DD>Previous function.\n";
+ print HELP "<DT>[&gt;]<DD>Next function.\n";
+ print HELP "<DT>[^]<DD>First function in this file.\n";
+ print HELP "<DT>[v]<DD>Last function in this file.\n";
+ print HELP "<DT>[top]<DD>Top of this file.\n";
+ print HELP "<DT>[bottom]<DD>Bottom of this file.\n";
+ print HELP "<DT>[index]<DD>Return to index page (mains.html).\n";
+ print HELP "<DT>[help]<DD>You are seeing now.\n";
+ print HELP "</DL>\n";
+ print HELP "</BODY>\n</HTML>\n";
+ close(HELP);
+}
+#
+# makedupindex: make duplicate entries index ($DEFS/* and $REFS/*)
+#
+# go) tag cache
+# r) $count
+#
+sub makeline {
+ $_[0] =~ s/\.\///;
+ $_[0] =~ s/&/&amp;/g;
+ $_[0] =~ s/</&lt;/g;
+ $_[0] =~ s/>/&gt;/g;
+ local($tag, $lno, $filename) = split(/[ \t\n]+/, $_[0]);;
+ $filename =~ s/\//$ESCSEP/g;
+ $_[0] =~ s/^$tag/<A HREF=..\/$SRCS\/$filename.html#$lno>$tag<\/A>/;
+}
+sub makedupindex {
+ local($expand) = &'usable('expand') ? 'expand' : 'cat';
+ local($count) = 0;
+
+ foreach $db ('GRTAGS', 'GTAGS') {
+ local($kind) = $db eq 'GTAGS' ? "definitions" : "references";
+ local($prev) = '';
+ local($first_line);
+ local($writing) = 0;
+
+ $count = 0;
+ open(LIST, "btreeop $dbpath/$db | sort +0 -1 +2 -3 +1n -2|") || &error("btreeop $dbpath/$db | sort +0 -1 +2 -3 +1n -2 failed.\n");
+ while (<LIST>) {
+ chop;
+ local($tag, $lno, $filename) = split;
+ if ($prev ne $tag) {
+ $count++;
+ print STDERR " [$count] adding $tag $kind.\n" if ($vflag);
+ if ($writing) {
+ print FILE "</PRE>\n</BODY>\n</HTML>\n";
+ close(FILE);
+ $writing = 0;
+ }
+ # single entry
+ if ($first_line) {
+ &cache'put($db, $prev, $first_line);
+ }
+ $first_line = $_;
+ $prev = $tag;
+ } else {
+ # duplicate entry
+ if ($first_line) {
+ &cache'put($db, $tag, '');
+ local($type) = ($db eq 'GTAGS') ? $DEFS : $REFS;
+ open(FILE, ">$html/$type/$tag.html") || &error("cannot make file <$html/$type/$tag.html>.\n");
+ $writing = 1;
+ print FILE "<HTML>\n<HEAD><TITLE>$tag</TITLE></HEAD>\n<BODY>\n";
+ print FILE "<PRE>\n";
+ &makeline($first_line);
+ print FILE $first_line, "\n";
+ $first_line = '';
+ }
+ &makeline($_);
+ print FILE $_, "\n";
+ }
+ }
+ close(LIST);
+ if ($writing) {
+ print FILE "</PRE>\n</BODY>\n</HTML>\n";
+ close(FILE);
+ }
+ if ($first_line) {
+ &cache'put($db, $prev, $first_line);
+ }
+ }
+ $count;
+}
+#
+# makefuncindex: make function index (including alphabetic index)
+#
+# i) file function index file
+# i) total functions total
+# gi) tag cache
+# go) @funcs
+#
+sub makefuncindex {
+ local($file, $total) = @_;
+ local($count) = 0;
+
+ open(FUNCTIONS, ">$file") || &error("cannot make function index <$file>.\n");
+ print FUNCTIONS "<HTML>\n<HEAD><TITLE>FUNCTION INDEX</TITLE>\n";
+ print FUNCTIONS "$begin_script$defaultview$end_script</HEAD>\n<BODY>\n";
+ print FUNCTIONS "<H2>FUNCTION INDEX</H2>\n";
+ print FUNCTIONS "<OL>\n" if (!$aflag);
+ local($old) = select(FUNCTIONS);
+ open(TAGS, "btreeop -L $dbpath/GTAGS |") || &error("btreeop -L $dbpath/GTAGS failed.\n");
+ local($alpha) = '';
+ @funcs = (); # [A][B][C]...
+ while (<TAGS>) {
+ $count++;
+ chop;
+ local($tag) = $_;
+ print STDERR " [$count/$total] adding $tag\n" if ($vflag);
+ if ($aflag && $alpha ne substr($tag, 0, 1)) {
+ if ($alpha) {
+ print ALPHA "</OL>\n";
+ print ALPHA "<A HREF=../mains.html TARGET=_self>[index]</A>\n";
+ print ALPHA "$begin_script$rewrite_href_funcs$end_script";
+ print ALPHA "</BODY>\n</HTML>\n";
+ close(ALPHA);
+ }
+ $alpha = substr($tag, 0, 1);
+ push(@funcs, "<A HREF=funcs/$alpha.html TARGET=_self>[$alpha]</A>\n");
+ open(ALPHA, ">$html/funcs/$alpha.html") || &error("cannot make alphabetical function index.\n");
+ print ALPHA "<HTML>\n<HEAD><TITLE>$alpha</TITLE>\n";
+ print ALPHA "$begin_script$defaultview$end_script";
+ print ALPHA "</HEAD>\n<BODY>\n<H2>[$alpha]</H2>\n";
+ print ALPHA "<A HREF=../mains.html TARGET=_self>[index]</A>\n";
+ print ALPHA "<OL>\n";
+ select(ALPHA);
+ }
+ local($line) = &cache'get('GTAGS', $tag);
+ if (!$line) {
+ print "<LI><A HREF=", ($aflag) ? "../" : "", "$DEFS/$tag.html>$tag</A>\n";
+ } else {
+ local($tag, $lno, $filename) = split(/[ \t]+/, $line);
+ $filename =~ s/^\.\///;
+ $filename =~ s/\//$ESCSEP/g;
+ print "<LI><A HREF=", ($aflag) ? "../" : "", "$SRCS/$filename.html#$lno>$tag</A>\n";
+ }
+ }
+ close(TAGS);
+ select($old);
+ if ($aflag) {
+ print ALPHA "</OL>\n";
+ print ALPHA "<A HREF=../mains.html TARGET=_self>[index]</A>\n";
+ print ALPHA "$begin_script$rewrite_href_funcs$end_script";
+ print ALPHA "</BODY>\n</HTML>\n";
+ close(ALPHA);
+
+ print FUNCTIONS @funcs;
+ }
+ print FUNCTIONS "</OL>\n" if (!$aflag);
+ print FUNCTIONS "</BODY>\n</HTML>\n";
+ close(FUNCTIONS);
+ $count;
+}
+#
+# makefileindex: make file index
+#
+# i) file name
+# i) $INC directory
+# go) @files
+# go) %includes
+#
+sub makefileindex {
+ local($file, $incdir) = @_;
+ local($count) = 0;
+
+ open(FILES, ">$file") || &error("cannot make file <$file>.\n");
+ print FILES "<HTML>\n<HEAD><TITLE>FILES</TITLE>\n";
+ print FILES "$begin_script$defaultview$end_script";
+ print FILES "</HEAD>\n<BODY>\n<H2>FILE INDEX</H2>\n";
+ print FILES "<OL>\n";
+ local($old) = select(FILES);
+ open(FIND, "find . -type f -name '*.[chysS]' -print | sort |") || &error("cannot exec find.\n");
+ local($lastdir) = '';
+ @files = ();
+ while (<FIND>) {
+ next if /(y\.tab\.c|y\.tab\.h)$/;
+ next if (!$'sflag && /\.[sS]$/);
+ next if /(\/SCCS\/|\/RCS\/)/;
+
+ $count++;
+ chop;
+ s/^\.\///;
+ local($filename) = $_;
+ print STDERR " [$count] adding $filename\n" if ($vflag);
+ local($dir);
+ if (index($filename, '/') >= 0) {
+ @split = split('/');
+ $dir = $split[0];
+ } else {
+ $dir = '';
+ }
+ #if ($dir && $dir ne $lastdir) {
+ if ($dir ne $lastdir) {
+ if ($lastdir) {
+ print DIR "</OL>\n";
+ print DIR "<A HREF=../mains.html TARGET=_self>[index]</A>\n";
+ print DIR "$begin_script$rewrite_href_files$end_script";
+ print DIR "</BODY>\n</HTML>\n";
+ close(DIR);
+ }
+ if ($dir) {
+ push(@files, "<LI><A HREF=files/$dir.html TARGET=_self>$dir/</A>\n");
+ open(DIR, ">$html/files/$dir.html") || &error("cannot make directory index.\n");
+ print DIR "<HTML>\n<HEAD><TITLE>$dir/</TITLE>\n";
+ print DIR "$begin_script$defaultview$end_script";
+ print DIR "</HEAD>\n<BODY>\n<H2>$dir/</H2>\n";
+ print DIR "<A HREF=../mains.html TARGET=_self>[index]</A>\n";
+ print DIR "<OL>\n";
+ }
+ $lastdir = $dir;
+ }
+ # collect include files.
+ if ($filename =~ /.*\.h$/) {
+ local($last) = $filename;
+ $last =~ s!.*/!!;
+ if (! defined $includes{$last}) {
+ $includes{$last} = $filename;
+ } else {
+ # duplicate entries
+ $includes{$last} = "$includes{$last}\n$filename";
+ }
+ }
+ local($path) = $filename;
+ $path =~ s/\//$ESCSEP/g;
+ if ($dir eq '') {
+ push(@files, "<LI><A HREF=$SRCS/$path.html>$filename</A>\n");
+ } else {
+ print DIR "<LI><A HREF=../$SRCS/$path.html>$filename</A>\n";
+ }
+ }
+ close(FIND);
+ select($old);
+ if ($lastdir) {
+ print DIR "</OL>\n";
+ print DIR "<A HREF=../mains.html TARGET=_self>[index]</A>\n";
+ print DIR "$begin_script$rewrite_href_files$end_script";
+ print DIR "</BODY>\n</HTML>\n";
+ close(DIR);
+ }
+ print FILES @files;
+ print FILES "</OL>\n";
+ print FILES "</BODY>\n</HTML>\n";
+ close(FILES);
+
+ foreach $last (keys %includes) {
+ local(@incs) = split(/\n/, $includes{$last});
+ if (@incs > 1) {
+ open(INCLUDE, ">$incdir/$last.html") || &error("cannot open file '$incdir/$last.html'.\n");
+ print INCLUDE "<HTML>\n<HEAD><TITLE>$last</TITLE></HEAD>\n<BODY>\n<PRE>\n";
+ foreach $filename (@incs) {
+ local($path) = $filename;
+ $path =~ s/\//$ESCSEP/g;
+ print INCLUDE "<A HREF=../$SRCS/$path.html>$filename</A>\n";
+ }
+ print INCLUDE "</PRE>\n</BODY>\n</HTML>\n";
+ close(INCLUDE);
+ # '' means that information already written to file.
+ $includes{$last} = '';
+ }
+ }
+ $count;
+}
+#
+# makecommonpart: make a common part for mains.html and index.html
+#
+# gi) @files
+# gi) @funcs
+#
+sub makecommonpart {
+ local($title) = @_;
+ local($index) = '';
+
+ $index .= "<H1><FONT COLOR=#cc0000>$title</FONT></H1>\n";
+ $index .= "<P ALIGN=right>";
+ $index .= "Last updated " . &date . "<BR>\n";
+ $index .= "This hypertext was generated by <A HREF=http://wafu.netgate.net/tama/unix/indexe.html#global TARGET=_top>GLOBAL</A>.<BR>\n";
+ $index .= "$begin_script";
+ $index .= "if (parent.frames.length && parent.$f_mains == self)\n";
+ $index .= " document.write($langle+'A HREF=mains.html TARGET=_top'+$rangle+'[No frame version is here.]'+$langle+'/A'+$rangle)\n";
+ $index .= "$end_script";
+ $index .= "</P>\n<HR>\n";
+ if ($fflag) {
+ $index .= "<H2>FUNCTION SEARCH</H2>\n";
+ $index .= "Please input function name and select [Search]. Perl's regular expression is allowed.<P>\n";
+ $index .= "<FORM METHOD=GET ACTION=cgi-bin/global.cgi>\n";
+ $index .= "<INPUT NAME=pattern>\n";
+ $index .= "<INPUT TYPE=submit VALUE=Search>\n";
+ $index .= "<INPUT TYPE=reset VALUE=Reset><BR>\n";
+ $index .= "<INPUT TYPE=radio NAME=type VALUE=definition CHECKED>Definition\n";
+ $index .= "<INPUT TYPE=radio NAME=type VALUE=reference>Reference\n";
+ $index .= "</FORM>\n<HR>\n";
+ }
+ $index .= "<H2>MAINS</H2>\n";
+ $index .= "<PRE>\n";
+ open(PIPE, "btreeop -K main $dbpath/GTAGS | sort +0 -1 +2 -3 +1n -2|") || &error("btreeop -K main $dbpath/GTAGS failed.\n");
+ while (<PIPE>) {
+ local($nouse, $lno, $filename) = split;
+ $nouse = ''; # to make perl quiet
+ $filename =~ s/^\.\///;
+ $filename =~ s/\//$ESCSEP/g;
+ s/(main)/<A HREF=$SRCS\/$filename.html#$lno>$1<\/A>/;
+ $index .= $_;
+ }
+ close(PIPE);
+ $index .= "</PRE>\n<HR>\n<H2>FUNCTIONS</H2>\n";
+ if ($aflag) {
+ foreach $f (@funcs) {
+ $index .= $f;
+ }
+ } else {
+ $index .= "<PRE><A HREF=funcs.html>function index</A></PRE>\n";
+ }
+ $index .= "<HR>\n<H2>FILES</H2>\n";
+ $index .= "<OL>\n";
+ foreach $f (@files) {
+ $index .= $f;
+ }
+ $index .= "</OL>\n<HR>\n";
+ $index;
+}
+#
+# makeindex: make index file
+#
+# i) $file file name
+# i) $title title of index file
+# i) $index common part
+#
+sub makeindex {
+ local($file, $title, $index) = @_;
+
+ open(FRAME, ">$file") || &error("cannot open file <$file>.\n");
+ print FRAME "<HTML>\n<HEAD><TITLE>$title</TITLE></HEAD>\n";
+ print FRAME "<FRAMESET COLS='200,*'>\n";
+ print FRAME "<NOFRAME>\n$index</NOFRAME>\n";
+ print FRAME "<FRAMESET ROWS='50%,50%'>\n";
+ print FRAME "<FRAME NAME=$f_funcs SRC=funcs.html>\n";
+ print FRAME "<FRAME NAME=$f_files SRC=files.html>\n";
+ print FRAME "</FRAMESET>\n";
+ print FRAME "<FRAME NAME=$f_mains SRC=mains.html>\n";
+ print FRAME "</FRAMESET>\n";
+ print FRAME "</HTML>\n";
+ close(FRAME);
+}
+#
+# makemainindex: make main index
+#
+# i) $file file name
+# i) $index common part
+#
+sub makemainindex {
+ local($file, $index) = @_;
+
+ open(INDEX, ">$file") || &error("cannot create file <$file>.\n");
+ print INDEX "<HTML>\n<HEAD><TITLE>MAINS</TITLE></HEAD>\n";
+ print INDEX "<BODY>\n$index</BODY>\n</HTML>\n";
+ close(INDEX);
+}
+#
+# makehtml: make html files
+#
+# i) total number of files.
+#
+sub makehtml {
+ local($total) = @_;
+ local($count) = 0;
+
+ open(FIND, "find . -type f -name '*.[chysS]' -print|") || &error("cannot exec find.\n");
+ while (<FIND>) {
+ next if /y\.tab\.c|y\.tab\.h/;
+ next if (!$'sflag && /\.[sS]$/);
+ next if /(\/SCCS\/|\/RCS\/)/;
+
+ $count++;
+ chop;
+ s/^\.\///;
+ local($path) = $_;
+ $path =~ s/\//$SEP/g;
+ print STDERR " [$count/$total] converting $_\n" if ($vflag);
+ &convert'src2html($_, "$html/$SRCS/$path.html");
+ }
+ close(FIND);
+}
+#=========================================================================
+# CONVERT PACKAGE
+#=========================================================================
+package convert;
+#
+# src2html: convert source code into HTML
+#
+# i) $file source file - Read from
+# i) $html HTML file - Write to
+# gi) %includes
+# pairs of include file and the path
+#
+sub src2html {
+ local($file, $html) = @_;
+ local($ncol) = $'ncol;
+ local($expand) = &'usable('expand') ? 'expand' : 'cat';
+ local(%ctab) = ('&', '&amp;', '<', '&lt;', '>', '&gt;');
+
+ open(HTML, ">$html") || &'error("cannot create file <$html>.\n");
+ local($old) = select(HTML);
+ #
+ # load tags belonging to this file.
+ #
+ $file =~ s/^\.\///;
+ &anchor'load($file);
+ open(C, "$expand '$file' |") || &'error("cannot open file <$file>.\n");
+ #
+ # print the header
+ #
+ print "<HTML>\n<HEAD><TITLE>$file</TITLE></HEAD>\n";
+ print "<BODY><A NAME=TOP><H2>$file</H2>\n";
+ print &link_format(&anchor'getlinks(0));
+ print "\n<HR>\n";
+ print "<H2>FUNCTIONS</H2>\n";
+ print "This source file includes following functions.\n";
+ print "<OL>\n";
+ local($lno, $tag, $type);
+ for (($lno, $tag, $type) = &anchor'first(); $lno; ($lno, $tag, $type) = &anchor'next()) {
+ print "<LI><A HREF=#$lno>$tag</A>\n" if ($type eq 'D');
+ }
+ print "</OL>\n";
+ print "<HR>\n";
+ #
+ # print source code
+ #
+ print "<PRE>\n";
+ $INCOMMENT = 0; # initial status is out of comment
+ local($LNO, $TAG, $TYPE) = &anchor'first();
+ while (<C>) {
+ local($converted);
+ s/\r$//;
+ # make link for include file
+ if (!$INCOMMENT && /^#include/) {
+ local($last, $sep) = m![</"]([^</"]+)([">])!;
+ local($link);
+ if (defined $'includes{$last}) {
+ if ($'includes{$last}) {
+ $link = $'includes{$last};
+ $link =~ s/\//$'ESCSEP/g;
+ } else {
+ $link = "../$'INCS/$last";
+ }
+ if ($sep eq '"') {
+ s!"(.*$last)"!"<A HREF=$link.html>$1</A>"!;
+ } else {
+ s!<(.*$last)>!&lt;<A HREF=$link.html>$1</A>&gt;!;
+ }
+ $converted = 1;
+ }
+ }
+ # translate '<', '>' and '&' into entity name
+ if (!$converted) { s/([&<>])/$ctab{$1}/ge; }
+ &protect_line(); # protect quoted char, strings and comments
+ # painting source code
+ s/({|})/$'brace_begin$1$'brace_end/g;
+ local($sharp) = s/^(#\w+)// ? $1 : '';
+ s/\b($'reserved_words)\b/$'reserved_begin$1$'reserved_end/go if ($sharp ne '#include');
+ s/^/$'sharp_begin$sharp$'sharp_end/ if ($sharp); # recover macro
+
+ local($define_line) = 0;
+ local(@links) = ();
+ local($count) = 0;
+ local($lno_printed) = 0;
+
+ if ($'lflag) {
+ print "<A NAME=$.>";
+ $lno_printed = 1;
+ }
+ for (; int($LNO) == $.; ($LNO, $TAG, $TYPE) = &anchor'next()) {
+ if (!$lno_printed) {
+ print "<A NAME=$.>";
+ $lno_printed = 1;
+ }
+ $define_line = $LNO if ($TYPE eq 'D');
+ $db = ($TYPE eq 'D') ? 'GRTAGS' : 'GTAGS';
+ local($line) = &cache'get($db, $TAG);
+ if (defined($line)) {
+ local($href);
+ if ($line) {
+ local($nouse, $lno, $filename) = split(/[ \t]+/, $line);
+ $nouse = ''; # to make perl quiet
+ $filename =~ s/^\.\///;
+ $filename =~ s/\//$'ESCSEP/g;
+ $href = "<A HREF=../$'SRCS/$filename.html#$lno>$TAG</A>";
+ } else {
+ local($dir) = ($TYPE eq 'D') ? $'REFS : $'DEFS;
+ $href = "<A HREF=../$dir/$TAG.html>$TAG</A>";
+ }
+ # set tag marks and save hyperlink into @links
+ if (s/\b$TAG\b/\005$count\005/) {
+ $count++;
+ push(@links, $href);
+ } else {
+ print STDERR "Error: $file $LNO $TAG($TYPE) tag must exist.\n" if ($'wflag);
+ }
+ } else {
+ print STDERR "Warning: $file $LNO $TAG($TYPE) found but not referred.\n" if ($'wflag);
+ }
+ }
+ # implant links
+ local($s);
+ for ($count = 0; @links; $count++) {
+ $s = shift @links;
+ unless (s/\005$count\005/$s/) {
+ print STDERR "Error: $file $LNO $TAG($TYPE) tag must exist.\n" if ($'wflag);
+ }
+ }
+ &unprotect_line();
+ # print a line
+ printf "%${ncol}d ", $. if ($'nflag);
+ print;
+ # print hyperlinks
+ if ($define_line && $file !~ /\.h$/) {
+ print ' ' x ($ncol + 1) if ($'nflag);
+ print &link_format(&anchor'getlinks($define_line));
+ print "\n";
+ }
+ }
+ print "</PRE>\n";
+ print "<HR>\n";
+ print "<A NAME=BOTTOM>\n";
+ print &link_format(&anchor'getlinks(-1));
+ print "\n";
+ print "</BODY>\n</HTML>\n";
+ close(C);
+ close(HTML);
+ select($old);
+
+}
+#
+# protect_line: protect quoted strings
+#
+# io) $_ source line
+#
+# \001 quoted(\) char
+# \002 quoted('') char
+# \003 quoted string
+# \004 comment
+# \032 temporary mark
+#
+sub protect_line {
+ @quoted_char1 = ();
+ while (s/(\\.)/\001/) {
+ push(@quoted_char1, $1);
+ }
+ @quoted_char2 = ();
+ while (s/('[^']')/\002/) {
+ push(@quoted_char2, $1);
+ }
+ @quoted_strings = ();
+ while (s/("[^"]*")/\003/) {
+ push(@quoted_strings, $1);
+ }
+ @comments = ();
+ s/^/\032/ if ($INCOMMENT);
+ while (1) {
+ if ($INCOMMENT == 0) {
+ if (s/\/\*/\032\/\*/) { # start comment
+ $INCOMMENT = 1;
+ } else {
+ last;
+ }
+ } else {
+ # Thanks to Jeffrey Friedl for his code.
+ if (s!\032((/\*)?[^*]*\*+([^/*][^*]*\*+)*/)!\004!) {
+ push(@comments, $1);
+ $INCOMMENT = 0;
+ } else {
+ s/\032(.*)$/\004/; # mark comment
+ push(@comments, $1);
+ }
+ last if ($INCOMMENT);
+ }
+ }
+}
+#
+# unprotect_line: recover quoted strings
+#
+# i) $_ source line
+#
+sub unprotect_line {
+ local($s);
+
+ while (@comments) {
+ $s = shift @comments;
+ s/\004/$'comment_begin$s$'comment_end/;
+ }
+ while (@quoted_strings) {
+ $s = shift @quoted_strings;
+ s/\003/$s/;
+ }
+ while (@quoted_char2) {
+ $s = shift @quoted_char2;
+ s/\002/$s/;
+ }
+ while (@quoted_char1) {
+ $s = shift @quoted_char1;
+ s/\001/$s/;
+ }
+}
+#
+# link_format: format hyperlinks.
+#
+# i) (previous, next, first, last, top, bottom)
+#
+sub link_format {
+ local(@tag) = @_;
+ local(@label) = ('&lt;', '&gt;', '^', 'v', 'top', 'bottom');
+
+ local($line) = "$'comment_begin/* ";
+ while ($label = shift @label) {
+ local($tag) = shift @tag;
+ $line .= "<A HREF=#$tag>" if ($tag);
+ $line .= "[$label]";
+ $line .= "</A>" if ($tag);
+ }
+ $line .= "<A HREF=../mains.html>[index]</A>";
+ $line .= "<A HREF=../help.html>[help]</A>";
+ $line .= " */$'comment_end";
+
+ $line;
+}
+
+#=========================================================================
+# ANCHOR PACKAGE
+#=========================================================================
+package anchor;
+#
+# create: create anchors temporary database
+#
+sub create {
+ $ANCH = "$'tmp/ANCH$$";
+ open(ANCH, ">$ANCH") || &'error("cannot create file $ANCH.\n");
+ close(ANCH);
+ chmod ($ANCH, 0600);
+ open(ANCH, "| btreeop -C $ANCH") || &'error("btreeop -C $ANCH failed.\n");
+ foreach $db ('GTAGS', 'GRTAGS') {
+ local($type) = ($db eq 'GTAGS') ? 'D' : 'R';
+ open(PIPE, "btreeop $'dbpath/$db |") || &'error("btreeop $'dbpath/$db failed.\n");
+ while (<PIPE>) {
+ local($tag, $lno, $filename) = split;
+ print ANCH "$filename $lno $tag $type\n";
+ }
+ close(PIPE);
+ }
+ close(ANCH);
+}
+#
+# finish: remove anchors database
+#
+sub finish {
+ unlink("$ANCH") if (defined($ANCH));
+}
+#
+# load: load anchors in a file from database
+#
+# i) $file source file
+# go) FIRST first definition
+# go) LAST last definition
+#
+sub load {
+ local($file) = @_;
+
+ $file = './' . $file if ($file !~ /^\.\//);
+
+ @ANCHORS = ();
+ open(ANCH, "btreeop -K $file $ANCH |") || &'error("btreeop -K $file $ANCH failed.\n");
+$n = 0;
+ while (<ANCH>) {
+ local($filename, $lno, $tag, $type) = split;
+ local($line);
+ # don't refer to macros which is defined in other C source.
+ if ($type eq 'R' && ($line = &cache'get('GTAGS', $tag))) {
+ local($nouse1, $nouse2, $f, $def) = split(/[ \t]+/, $line);
+ if ($f !~ /\.h$/ && $f !~ $filename && $def =~ /^#/) {
+ print STDERR "Information: $filename $lno $tag($type) skipped, because this is a macro which is defined in other C source.\n" if ($'wflag);
+ next;
+ }
+ }
+ push(@ANCHORS, "$lno,$tag,$type");
+ }
+ close(ANCH);
+ local(@keys);
+ foreach (@ANCHORS) {
+ push(@keys, (split(/,/))[0]);
+ }
+ sub compare { $keys[$a] <=> $keys[$b]; }
+ @ANCHORS = @ANCHORS[sort compare 0 .. $#keys];
+ local($c);
+ $FIRST = $LAST = 0;
+ for ($c = 0; $c < @ANCHORS; $c++) {
+ local($lno, $tag, $type) = split(/,/, $ANCHORS[$c]);
+ if ($type eq 'D') {
+ $FIRST = $lno;
+ last;
+ }
+ }
+ for ($c = $#ANCHORS; $c >= 0; $c--) {
+ local($lno, $tag, $type) = split(/,/, $ANCHORS[$c]);
+ if ($type eq 'D') {
+ $LAST = $lno;
+ last;
+ }
+ }
+}
+#
+# first: get first anchor
+#
+sub first {
+ $CURRENT = 0;
+ local($lno, $tag, $type) = split(/,/, $ANCHORS[$CURRENT]);
+ $CURRENTDEF = $CURRENT if ($type eq 'D');
+
+ ($lno, $tag, $type);
+}
+#
+# next: get next anchor
+#
+sub next {
+ if (++$CURRENT > $#ANCHORS) {
+ return ('', '', '');
+ }
+ local($lno, $tag, $type) = split(/,/, $ANCHORS[$CURRENT]);
+ $CURRENTDEF = $CURRENT if ($type eq 'D');
+
+ ($lno, $tag, $type);
+}
+#
+# getlinks: get links
+#
+# i) linenumber >= 1: line number
+# 0: header, -1: tailer
+# gi) @ANCHORS tag table in current file
+# r) (previous, next, first, last, top, bottom)
+#
+sub getlinks {
+ local($linenumber) = @_;
+ local($prev, $next, $first, $last, $top, $bottom);
+
+ $prev = $next = $first = $last = $top = $bottom = 0;
+ if ($linenumber >= 1) {
+ local($c, $p, $n);
+ if ($CURRENTDEF == 0) {
+ for ($c = 0; $c <= $#ANCHORS; $c++) {
+ local($lno, $tag, $type) = split(/,/, $ANCHORS[$c]);
+ if ($lno == $linenumber && $type eq 'D') {
+ last;
+ }
+ }
+ $CURRENTDEF = $c;
+ } else {
+ for ($c = $CURRENTDEF; $c >= 0; $c--) {
+ local($lno, $tag, $type) = split(/,/, $ANCHORS[$c]);
+ if ($lno == $linenumber && $type eq 'D') {
+ last;
+ }
+ }
+ }
+ $p = $n = $c;
+ while (--$p >= 0) {
+ local($lno, $tag, $type) = split(/,/, $ANCHORS[$p]);
+ if ($type eq 'D') {
+ $prev = $lno;
+ last;
+ }
+ }
+ while (++$n <= $#ANCHORS) {
+ local($lno, $tag, $type) = split(/,/, $ANCHORS[$n]);
+ if ($type eq 'D') {
+ $next = $lno;
+ last;
+ }
+ }
+ }
+ $first = $FIRST if ($FIRST > 0 && $linenumber != $FIRST);
+ $last = $LAST if ($LAST > 0 && $linenumber != $LAST);
+ $top = 'TOP' if ($linenumber != 0);
+ $bottom = 'BOTTOM' if ($linenumber != -1);
+ if ($FIRST > 0 && $FIRST == $LAST) {
+ $last = '' if ($linenumber == 0);
+ $first = '' if ($linenumber == -1);
+ }
+
+ ($prev, $next, $first, $last, $top, $bottom);
+}
+
+#=========================================================================
+# CACHE PACKAGE
+#=========================================================================
+package cache;
+#
+# open: open tag cache
+#
+# i) size cache size
+# -1: all cache
+# 0: no cache
+# other: sized cache
+#
+sub open {
+ ($cachesize) = @_;
+
+ if ($cachesize == -1) {
+ return;
+ }
+ undef %CACH if defined(%CACH);
+ $cachecount = 0;
+}
+#
+# put: put tag into cache
+#
+# i) $db database name
+# i) $tag tag name
+# i) $line tag line
+#
+sub put {
+ local($db, $tag, $line) = @_;
+ local($label) = ($db eq 'GTAGS') ? 'D' : 'R';
+
+ $cachecount++;
+ if ($cachesize >= 0 && $cachecount > $cachesize) {
+ $CACH = "$'tmp/CACH$$";
+ dbmopen(%CACH, $CACH, 0600) || &'error("make cache database.\n");
+ $cachesize = -1;
+ }
+ $CACH{$label.$tag} = $line;
+}
+#
+# get: get tag from cache
+#
+# i) $db database name
+# i) $tag tag name
+# r) tag line
+#
+sub get {
+ local($db, $tag) = @_;
+ local($label) = ($db eq 'GTAGS') ? 'D' : 'R';
+
+ defined($CACH{$label.$tag}) ? $CACH{$label.$tag} : undef;
+}
+#
+# close: close cache
+#
+sub close {
+ #dbmclose(%CACH);
+ unlink("$CACH.db") if (defined($CACH));
+}
diff --git a/contrib/global/include/ansi.h b/contrib/global/include/ansi.h
new file mode 100644
index 0000000..2d71f77
--- /dev/null
+++ b/contrib/global/include/ansi.h
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ansi.h 8.2 (Berkeley) 1/4/94
+ * $Id: ansi.h,v 1.10 1996/05/01 00:47:05 bde Exp $
+ */
+
+#ifndef _MACHINE_ANSI_H_
+#define _MACHINE_ANSI_H_
+
+/*
+ * Types which are fundamental to the implementation and must be declared
+ * in more than one standard header are defined here. Standard headers
+ * then use:
+ * #ifdef _BSD_SIZE_T_
+ * typedef _BSD_SIZE_T_ size_t;
+ * #undef _BSD_SIZE_T_
+ * #endif
+ */
+#define _BSD_CLOCK_T_ unsigned long /* clock() */
+#define _BSD_PTRDIFF_T_ int /* ptr1 - ptr2 */
+#define _BSD_RUNE_T_ _BSD_CT_RUNE_T_ /* rune_t (see below) */
+#define _BSD_SIZE_T_ unsigned int /* sizeof() */
+#define _BSD_SSIZE_T_ int /* byte count or error */
+#define _BSD_TIME_T_ long /* time() */
+#define _BSD_WCHAR_T_ _BSD_CT_RUNE_T_ /* wchar_t (see below) */
+
+/*
+ * Types which are fundamental to the implementation and must be used
+ * in more than one standard header although they are only declared in
+ * one (perhaps nonstandard) header are defined here. Standard headers
+ * use _BSD_XXX_T_ without undef'ing it.
+ */
+#define _BSD_CT_RUNE_T_ int /* arg type for ctype funcs */
+#define _BSD_OFF_T_ long long /* file offset */
+#define _BSD_PID_T_ int /* process [group] */
+#define _BSD_VA_LIST_ char * /* va_list */
+
+/*
+ * The rune type is declared to be an ``int'' instead of the more natural
+ * ``unsigned long'' or ``long''. Two things are happening here. It is not
+ * unsigned so that EOF (-1) can be naturally assigned to it and used. Also,
+ * it looks like 10646 will be a 31 bit standard. This means that if your
+ * ints cannot hold 32 bits, you will be in trouble. The reason an int was
+ * chosen over a long is that the is*() and to*() routines take ints (says
+ * ANSI C), but they use _BSD_CT_RUNE_T_ instead of int. By changing it
+ * here, you lose a bit of ANSI conformance, but your programs will still
+ * work.
+ */
+
+/*
+ * Frequencies of the clock ticks reported by clock() and times(). They
+ * are the same as stathz for bogus historical reasons. They should be
+ * 1e6 because clock() and times() are implemented using getrusage() and
+ * there is no good reason why they should be less accurate. There is
+ * the bad reason that (broken) programs might not like clock_t or
+ * CLOCKS_PER_SEC being ``double'' (``unsigned long'' is not large enough
+ * to hold the required 24 hours worth of ticks if the frequency is
+ * 1000000ul, and ``unsigned long long'' would be nonstandard).
+ */
+#define _BSD_CLK_TCK_ 128
+#define _BSD_CLOCKS_PER_SEC_ 128
+
+#endif /* !_MACHINE_ANSI_H_ */
diff --git a/contrib/global/include/cdefs.h b/contrib/global/include/cdefs.h
new file mode 100644
index 0000000..fe2cd66
--- /dev/null
+++ b/contrib/global/include/cdefs.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)cdefs.h 8.8 (Berkeley) 1/9/95
+ * $Id: cdefs.h,v 1.11 1996/08/18 16:14:03 peter Exp $
+ */
+
+#ifndef _SYS_CDEFS_H_
+#define _SYS_CDEFS_H_
+
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS };
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments. __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define __P(protos) protos /* full-blown ANSI C */
+#define __CONCAT1(x,y) x ## y
+#define __CONCAT(x,y) __CONCAT1(x,y)
+#define __STRING(x) #x
+
+#define __const const /* define reserved names to standard */
+#define __signed signed
+#define __volatile volatile
+#if defined(__cplusplus)
+#define __inline inline /* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define __inline /* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
+#else /* !(__STDC__ || __cplusplus) */
+#define __P(protos) () /* traditional C preprocessor */
+#define __CONCAT(x,y) x/**/y
+#define __STRING(x) "x"
+
+#ifndef __GNUC__
+#define __const /* delete pseudo-ANSI C keywords */
+#define __inline
+#define __signed
+#define __volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef NO_ANSI_KEYWORDS
+#define const /* delete ANSI C keywords */
+#define inline
+#define signed
+#define volatile
+#endif /* !NO_ANSI_KEYWORDS */
+#endif /* !__GNUC__ */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2.5 uses a new, peculiar __attribute__((attrs)) style. All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
+ */
+#if __GNUC__ < 2
+#define __dead
+#define __dead2
+#define __pure
+#define __pure2
+#define __unused
+#define __attribute__(x)
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 5
+#define __dead __volatile
+#define __dead2
+#define __pure __const
+#define __pure2
+#define __unused
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7
+#define __dead
+#define __dead2 __attribute__((__noreturn__))
+#define __pure
+#define __pure2 __attribute__((__const__))
+#define __unused
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ >= 7 || __GNUC__ >= 3
+#define __dead
+#define __dead2 __attribute__((__noreturn__))
+#define __pure
+#define __pure2 __attribute__((__const__))
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifdef __GNUC__
+#ifdef __STDC__
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_" #alias "\",11,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs \"" msg "\",30,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#else
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_/**/alias\",11,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs msg,30,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#endif
+#endif
+
+#endif /* !_SYS_CDEFS_H_ */
diff --git a/contrib/global/include/err.h b/contrib/global/include/err.h
new file mode 100644
index 0000000..f03c67d
--- /dev/null
+++ b/contrib/global/include/err.h
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)err.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _ERR_H_
+#define _ERR_H_
+
+/*
+ * Don't use va_list in the err/warn prototypes. Va_list is typedef'd in two
+ * places (<machine/varargs.h> and <machine/stdarg.h>), so if we include one
+ * of them here we may collide with the utility's includes. It's unreasonable
+ * for utilities to have to include one of them to include err.h, so we get
+ * _BSD_VA_LIST_ from <machine/ansi.h> and use it.
+ */
+#include <ansi.h>
+#include <cdefs.h>
+
+__BEGIN_DECLS
+void err __P((int, const char *, ...)) __dead2;
+void verr __P((int, const char *, _BSD_VA_LIST_)) __dead2;
+void errx __P((int, const char *, ...)) __dead2;
+void verrx __P((int, const char *, _BSD_VA_LIST_)) __dead2;
+void warn __P((const char *, ...));
+void vwarn __P((const char *, _BSD_VA_LIST_));
+void warnx __P((const char *, ...));
+void vwarnx __P((const char *, _BSD_VA_LIST_));
+void err_set_file __P((void *));
+void err_set_exit __P((void (*)(int)));
+__END_DECLS
+
+#endif /* !_ERR_H_ */
diff --git a/contrib/global/nvi-1.34.diff b/contrib/global/nvi-1.34.diff
new file mode 100644
index 0000000..f289e9a
--- /dev/null
+++ b/contrib/global/nvi-1.34.diff
@@ -0,0 +1,900 @@
+diff -c -r -N /usr/src/usr.bin/vi/USD.doc/vi.man/vi.1 ./USD.doc/vi.man/vi.1
+*** /usr/src/usr.bin/vi/USD.doc/vi.man/vi.1 Wed Aug 17 08:36:39 1994
+--- ./USD.doc/vi.man/vi.1 Sat Dec 14 11:54:14 1996
+***************
+*** 39,59 ****
+ .Nd text editors
+ .Sh SYNOPSIS
+ .Nm \&ex
+! .Op Fl eFRrsv
+ .Op Fl c Ar cmd
+ .Op Fl t Ar tag
+ .Op Fl w Ar size
+ .\".Op Fl X Ar \&aw
+ .Op Ar "file ..."
+ .Nm \&vi
+! .Op Fl eFRrv
+ .Op Fl c Ar cmd
+ .Op Fl t Ar tag
+ .Op Fl w Ar size
+ .\".Op Fl X Ar \&aw
+ .Op Ar "file ..."
+ .Nm view
+! .Op Fl eFRrv
+ .Op Fl c Ar cmd
+ .Op Fl t Ar tag
+ .Op Fl w Ar size
+--- 39,59 ----
+ .Nd text editors
+ .Sh SYNOPSIS
+ .Nm \&ex
+! .Op Fl eFGRrsv
+ .Op Fl c Ar cmd
+ .Op Fl t Ar tag
+ .Op Fl w Ar size
+ .\".Op Fl X Ar \&aw
+ .Op Ar "file ..."
+ .Nm \&vi
+! .Op Fl eFGRrv
+ .Op Fl c Ar cmd
+ .Op Fl t Ar tag
+ .Op Fl w Ar size
+ .\".Op Fl X Ar \&aw
+ .Op Ar "file ..."
+ .Nm view
+! .Op Fl eFGRrv
+ .Op Fl c Ar cmd
+ .Op Fl t Ar tag
+ .Op Fl w Ar size
+***************
+*** 124,129 ****
+--- 124,131 ----
+ Don't copy the entire file when first starting to edit.
+ (The default is to make a copy in case someone else modifies
+ the file during your edit session.)
++ .It Fl G
++ Start editing in gtags mode, as if the gtagsmode option was set.
+ .It Fl R
+ Start editing in read-only mode, as if the command name was
+ .Nm view ,
+***************
+*** 377,382 ****
+--- 379,385 ----
+ Move the cursor down
+ .Li count
+ lines to the first nonblank character of that line.
++ In gtags select mode, <control-M> select current line as a tag.
+ .It Sy "[count] <control-P>"
+ .It Sy "[count] k"
+ Move the cursor up
+***************
+*** 402,408 ****
+ .Nm \&ex
+ commands or cancel partial commands.
+ .It Sy "<control-]>"
+! Push a tag reference onto the tag stack.
+ .It Sy "<control-^>"
+ Switch to the most recently edited file.
+ .It Sy "[count] <space>"
+--- 405,412 ----
+ .Nm \&ex
+ commands or cancel partial commands.
+ .It Sy "<control-]>"
+! Push a tag reference onto the tag stack. In gtagsmode, if at the first column
+! of line, locate function references otherwise function definitions.
+ .It Sy "<control-^>"
+ Switch to the most recently edited file.
+ .It Sy "[count] <space>"
+***************
+*** 780,785 ****
+--- 784,793 ----
+ Grow or shrink the current screen.
+ .It Sy "rew[ind][!]"
+ Rewind the argument list.
++ .It Sy "rta[g][!] tagstring"
++ Edit the file refering the specified tag. (Only in gtagsmode)
++ .It Sy "se[lect]"
++ Select a tag from gtags list.
+ .It Sy "se[t] [option[=[value]] ...] [nooption ...] [option? ...] [all]"
+ Display or set editor options.
+ .It Sy "sh[ell]"
+***************
+*** 901,906 ****
+--- 909,916 ----
+ style) expressions.
+ .It Sy "flash [on]"
+ Flash the screen instead of beeping the keyboard on error.
++ .It Sy "gtagsmode, gt [off]"
++ Use GTAGS and GRTAGS instead of tags.
+ .It Sy "hardtabs, ht [8]"
+ Set the spacing between hardware tab settings.
+ .It Sy "ignorecase, ic [off]"
+diff -c -r -N /usr/src/usr.bin/vi/common/Makefile ./common/Makefile
+*** /usr/src/usr.bin/vi/common/Makefile Mon Sep 12 07:01:45 1994
+--- ./common/Makefile Sat Dec 14 11:55:27 1996
+***************
+*** 9,15 ****
+ LINKS+= ${BINDIR}/${VI} ${BINDIR}/view
+ MAN1= ${.CURDIR}/../USD.doc/vi.man/vi.1
+
+! CFLAGS+=-I. -I${.CURDIR}
+ DPADD+= ${LIBCURSES} ${LIBTERMCAP} ${LIBUTIL}
+ LDADD+= -lcurses -ltermcap -lutil
+
+--- 9,15 ----
+ LINKS+= ${BINDIR}/${VI} ${BINDIR}/view
+ MAN1= ${.CURDIR}/../USD.doc/vi.man/vi.1
+
+! CFLAGS+=-I. -I${.CURDIR} -DGTAGS
+ DPADD+= ${LIBCURSES} ${LIBTERMCAP} ${LIBUTIL}
+ LDADD+= -lcurses -ltermcap -lutil
+
+diff -c -r -N /usr/src/usr.bin/vi/common/exf.c ./common/exf.c
+*** /usr/src/usr.bin/vi/common/exf.c Tue May 30 15:35:44 1995
+--- ./common/exf.c Sat Dec 14 11:54:15 1996
+***************
+*** 156,162 ****
+--- 156,169 ----
+ * Required FRP initialization; the only flag we keep is the
+ * cursor information.
+ */
++ #ifdef GTAGS
++ /*
++ * we must keep gtagstmp information too.
++ */
++ F_CLR(frp, ~(FR_CURSORSET|FR_GTAGSTMP));
++ #else
+ F_CLR(frp, ~FR_CURSORSET);
++ #endif
+
+ /*
+ * Required EXF initialization:
+***************
+*** 290,295 ****
+--- 297,305 ----
+ * an error.
+ */
+ if (rcv_name == NULL)
++ #ifdef GTAGS
++ if (!F_ISSET(frp, FR_GTAGSTMP))
++ #endif
+ switch (file_lock(oname,
+ &ep->fcntl_fd, ep->db->fd(ep->db), 0)) {
+ case LOCK_FAILED:
+diff -c -r -N /usr/src/usr.bin/vi/common/gs.h ./common/gs.h
+*** /usr/src/usr.bin/vi/common/gs.h Wed Aug 17 08:36:42 1994
+--- ./common/gs.h Sat Dec 14 11:54:15 1996
+***************
+*** 48,53 ****
+--- 48,56 ----
+
+ sigset_t blockset; /* Signal mask. */
+
++ #ifdef GTAGS
++ char *gtagstmp; /* gtagstmp made by -t option */
++ #endif
+ #ifdef DEBUG
+ FILE *tracefp; /* Trace file pointer. */
+ #endif
+diff -c -r -N /usr/src/usr.bin/vi/common/main.c ./common/main.c
+*** /usr/src/usr.bin/vi/common/main.c Tue May 30 15:35:45 1995
+--- ./common/main.c Sat Dec 14 11:54:15 1996
+***************
+*** 98,103 ****
+--- 98,106 ----
+ SCR *sp;
+ u_int flags, saved_vi_mode;
+ int ch, eval, flagchk, readonly, silent, snapshot;
++ #ifdef GTAGS
++ int gtags = 0;
++ #endif
+ char *excmdarg, *myname, *p, *tag_f, *trace_f, *wsizearg;
+ char path[MAXPATHLEN];
+
+***************
+*** 134,140 ****
+--- 137,147 ----
+ excmdarg = tag_f = trace_f = wsizearg = NULL;
+ silent = 0;
+ snapshot = 1;
++ #ifdef GTAGS
++ while ((ch = getopt(argc, argv, "c:eFGRrsT:t:vw:X:")) != EOF)
++ #else
+ while ((ch = getopt(argc, argv, "c:eFRrsT:t:vw:X:")) != EOF)
++ #endif
+ switch (ch) {
+ case 'c': /* Run the command. */
+ excmdarg = optarg;
+***************
+*** 146,151 ****
+--- 153,163 ----
+ case 'F': /* No snapshot. */
+ snapshot = 0;
+ break;
++ #ifdef GTAGS
++ case 'G': /* gtags mode. */
++ gtags = 1;
++ break;
++ #endif
+ case 'R': /* Readonly. */
+ readonly = 1;
+ break;
+***************
+*** 245,250 ****
+--- 257,266 ----
+ goto err;
+ if (readonly) /* Global read-only bit. */
+ O_SET(sp, O_READONLY);
++ #ifdef GTAGS
++ if (gtags) /* Global gtags bit. */
++ O_SET(sp, O_GTAGSMODE);
++ #endif
+ if (silent) { /* Ex batch mode. */
+ O_CLR(sp, O_AUTOPRINT);
+ O_CLR(sp, O_PROMPT);
+***************
+*** 515,520 ****
+--- 531,539 ----
+ LIST_INIT(&gp->cutq);
+ LIST_INIT(&gp->seqq);
+
++ #ifdef GTAGS
++ gp->gtagstmp = NULL;
++ #endif
+ /* Set a flag if we're reading from the tty. */
+ if (isatty(STDIN_FILENO))
+ F_SET(gp, G_STDIN_TTY);
+***************
+*** 554,559 ****
+--- 573,584 ----
+ SCR *sp;
+ char *tty;
+
++ #ifdef GTAGS
++ if (gp->gtagstmp) {
++ if (!strncmp(gp->gtagstmp, _PATH_GTAGSTMP, strlen(_PATH_GTAGSTMP)))
++ (void)unlink(gp->gtagstmp);
++ }
++ #endif
+ /* Default buffer storage. */
+ (void)text_lfree(&gp->dcb_store.textq);
+
+diff -c -r -N /usr/src/usr.bin/vi/common/msg.c ./common/msg.c
+*** /usr/src/usr.bin/vi/common/msg.c Thu Aug 18 10:10:54 1994
+--- ./common/msg.c Sat Dec 14 11:54:15 1996
+***************
+*** 338,343 ****
+--- 338,352 ----
+ #else
+ pid = "";
+ #endif
++ #ifdef GTAGS
++ if (F_ISSET(sp->frp, FR_GTAGSTMP)) {
++ if (file_lline(sp, ep, &last)) {
++ return (1);
++ }
++ msgq(sp, M_INFO, "[GTAGS SELECT MODE] %d lines", last);
++ return (0);
++ }
++ #endif
+ /*
+ * See nvi/exf.c:file_init() for a description of how and
+ * when the read-only bit is set.
+diff -c -r -N /usr/src/usr.bin/vi/common/options.c ./common/options.c
+*** /usr/src/usr.bin/vi/common/options.c Tue May 30 15:35:46 1995
+--- ./common/options.c Sat Dec 14 11:54:15 1996
+***************
+*** 103,108 ****
+--- 103,112 ----
+ {"extended", NULL, OPT_0BOOL, 0},
+ /* O_FLASH HPUX */
+ {"flash", NULL, OPT_1BOOL, 0},
++ #ifdef GTAGS
++ /* O_GTAGSMODE SPECIAL */
++ {"gtagsmode", NULL, OPT_0BOOL, 0},
++ #endif
+ /* O_HARDTABS 4BSD */
+ {"hardtabs", NULL, OPT_NUM, 0},
+ /* O_IGNORECASE 4BSD */
+***************
+*** 228,233 ****
+--- 232,240 ----
+ {"eb", O_ERRORBELLS}, /* 4BSD */
+ {"ed", O_EDCOMPATIBLE}, /* 4BSD */
+ {"ex", O_EXRC}, /* System V (undocumented) */
++ #ifdef GTAGS
++ {"gt", O_GTAGSMODE}, /* Special */
++ #endif
+ {"ht", O_HARDTABS}, /* 4BSD */
+ {"ic", O_IGNORECASE}, /* 4BSD */
+ {"li", O_LINES}, /* 4.4BSD */
+diff -c -r -N /usr/src/usr.bin/vi/common/pathnames.h ./common/pathnames.h
+*** /usr/src/usr.bin/vi/common/pathnames.h Wed Aug 17 08:36:43 1994
+--- ./common/pathnames.h Sat Dec 14 11:54:15 1996
+***************
+*** 43,45 ****
+--- 43,48 ----
+ #define _PATH_TAGS "tags"
+ #define _PATH_TMP "/tmp"
+ #define _PATH_TTY "/dev/tty"
++ #ifdef GTAGS
++ #define _PATH_GTAGSTMP "/var/tmp/gtags"
++ #endif
+diff -c -r -N /usr/src/usr.bin/vi/common/screen.h ./common/screen.h
+*** /usr/src/usr.bin/vi/common/screen.h Wed Aug 17 08:36:43 1994
+--- ./common/screen.h Sat Dec 14 11:54:15 1996
+***************
+*** 87,92 ****
+--- 87,95 ----
+ #define FR_TMPEXIT 0x100 /* Modified temporary file, no exit. */
+ #define FR_TMPFILE 0x200 /* If file has no name. */
+ #define FR_UNLOCKED 0x400 /* File couldn't be locked. */
++ #ifdef GTAGS
++ #define FR_GTAGSTMP 0x800 /* File is gtags temporary file. */
++ #endif
+ u_int16_t flags;
+ };
+
+diff -c -r -N /usr/src/usr.bin/vi/ex/ex_tag.c ./ex/ex_tag.c
+*** /usr/src/usr.bin/vi/ex/ex_tag.c Thu Aug 18 10:13:20 1994
+--- ./ex/ex_tag.c Sat Dec 14 11:54:15 1996
+***************
+*** 64,69 ****
+--- 64,72 ----
+ #include "vi.h"
+ #include "excmd.h"
+ #include "tag.h"
++ #ifdef GTAGS
++ #include "pathnames.h"
++ #endif
+
+ static char *binary_search __P((char *, char *, char *));
+ static int compare __P((char *, char *, char *));
+***************
+*** 71,76 ****
+--- 74,288 ----
+ static int search __P((SCR *, char *, char *, char **));
+ static int tag_get __P((SCR *, char *, char **, char **, char **));
+
++ #ifdef DEBUG
++ void
++ trace(fp)
++ FILE *fp;
++ {
++ SCR *sp;
++ TAG *tp;
++ FREF *frp;
++ int scr, fref, tag;
++
++ fprintf(fp, "------------------------------------\n");
++ scr = 0;
++ for (sp = __global_list->dq.cqh_first; sp != (void *)&__global_list->dq; sp = sp->q.cqe_next) {
++ fprintf(fp, "screen %d {\n", ++scr);
++ fref = 0;
++ for (frp = sp->frefq.cqh_first;
++ frp != (FREF *)&sp->frefq; frp = frp->q.cqe_next) {
++ fprintf(fp, " FREF %d ", ++fref);
++ if (F_ISSET(frp, FR_GTAGSTMP))
++ fprintf(fp, "<%s>\n", frp->name);
++ else
++ fprintf(fp, "%s\n", frp->name);
++ }
++ tag = 0;
++ if (!EXP(sp))
++ continue;
++ fprintf(fp, " ................................\n");
++ for (tp = EXP(sp)->tagq.tqh_first; tp != NULL; tp = tp->q.tqe_next) {
++ fprintf(fp, " TAG %d ", ++tag);
++ if (F_ISSET(tp->frp, FR_GTAGSTMP))
++ fprintf(fp, "<%s>\n", tp->frp->name);
++ else
++ fprintf(fp, "%s\n", tp->frp->name);
++ }
++ fprintf(fp, "}\n");
++ }
++ fprintf(fp, "------------------------------------\n");
++ }
++ #endif
++ #ifdef GTAGS
++ /*
++ * getentry --
++ * get tag information from current line.
++ *
++ * gtags temporary file format.
++ * <tag> <lineno> <file> <image>
++ *
++ * sample.
++ * +------------------------------------------------
++ * |main 30 main.c main(argc, argv)
++ * |func 21 subr.c func(arg)
++ */
++ static int
++ getentry(buf, tag, file, line)
++ char *buf, *tag, *file, *line;
++ {
++ char *p;
++
++ p = tag;
++ while (*buf && !isspace(*buf)) /* tag name */
++ *p++ = *buf++;
++ *p = 0;
++ while (*buf && isspace(*buf)) /* skip blanks */
++ buf++;
++ p = line;
++ while (*buf && !isspace(*buf)) /* line no */
++ *p++ = *buf++;
++ *p = 0;
++ while (*buf && isspace(*buf)) /* skip blanks */
++ buf++;
++ p = file;
++ while (*buf && !isspace(*buf)) /* file name */
++ *p++ = *buf++;
++ *p = 0;
++
++ /* value check */
++ if (strlen(tag) && strlen(line) && strlen(file) && atoi(line) > 0)
++ return 1; /* OK */
++ return 0; /* ERROR */
++ }
++
++ /*
++ * gtag_get --
++ * Get a gtag from the GTAGS files.
++ */
++ static int
++ gtag_get(sp, ref, gtagselect, tag, tagp, filep, searchp)
++ SCR *sp;
++ int ref;
++ int *gtagselect;
++ char *tag, **tagp, **filep, **searchp;
++ {
++ static char name[80], file[200], line[10], gtagstmp[80];
++ char command[200];
++ char buf[BUFSIZ+1];
++ FILE *fp;
++
++ sprintf(gtagstmp, "%s.XXXXXXXX", _PATH_GTAGSTMP);
++ if (mktemp(gtagstmp) == 0) {
++ msgq(sp, M_ERR, "cannot generate temporary file name");
++ return (1);
++ }
++ sprintf(command, "global -%s '%s' > %s; chmod 600 %s",
++ ref ? "rx" : "x", tag, gtagstmp, gtagstmp);
++ if (system(command)) {
++ msgq(sp, M_ERR, "cannot exec global");
++ goto err;
++ }
++ if (!(fp = fopen(gtagstmp, "r"))) {
++ msgq(sp, M_ERR, "tag file cannot open.");
++ goto err;
++ }
++ if (!(fgets(buf, BUFSIZ, fp))) {
++ msgq(sp, M_ERR, "%s: tag not found", tag);
++ fclose(fp);
++ goto err;
++ }
++
++ if (getentry(buf, name, file, line) == 0) {
++ msgq(sp, M_ERR, "%s: illegal tag entry", tag);
++ fclose(fp);
++ goto err;
++ }
++
++ if (!(fgets(buf, BUFSIZ, fp))) { /* just one line */
++ fclose(fp);
++ (void)unlink(gtagstmp);
++ *gtagselect = 0; /* go to user's file immediately */
++ *tagp = strdup(name);
++ *filep = file;
++ *searchp = line;
++ if (*tagp == NULL) {
++ msgq(sp, M_SYSERR, NULL);
++ return (1);
++ }
++ return (0);
++ }
++ fclose(fp);
++ *gtagselect = 1; /* go to gtags select mode */
++ *tagp = strdup(name);
++ *filep = gtagstmp;
++ *searchp = "1";
++ if (*tagp == NULL) {
++ msgq(sp, M_SYSERR, NULL);
++ return (1);
++ }
++ return (0);
++ err:
++ (void)unlink(gtagstmp);
++ return (1);
++ }
++
++ /*
++ * ex_gtagselect --
++ * The tag code can be entered from gtag select mode.
++ */
++ int
++ ex_gtagselect(sp, ep, cmdp)
++ SCR *sp;
++ EXF *ep;
++ EXCMDARG *cmdp;
++ {
++ if (!F_ISSET(sp->frp, FR_GTAGSTMP)) {
++ msgq(sp, M_ERR, "illegal tag entry");
++ return (1);
++ }
++ cmdp->cmd = &cmds[C_TAG];
++ cmdp->flags |= (E_GTAGSELECT|E_FORCE);
++ return ex_tagpush(sp, ep, cmdp);
++ }
++
++ /*
++ * should_delete --
++ * 1: should delete, 0: should not delete
++ */
++ int
++ should_delete(gtagstmp)
++ char *gtagstmp;
++ {
++ SCR *sp;
++ TAG *tp;
++ int tagcnt = 0;
++
++ /* make sure */
++ if (strncmp(gtagstmp, _PATH_GTAGSTMP, strlen(_PATH_GTAGSTMP)))
++ return 0;
++ /* this gtag is generated by -t option. don't delete here */
++ if (__global_list->gtagstmp && !strcmp(gtagstmp, __global_list->gtagstmp))
++ return 0;
++
++ for (sp = __global_list->dq.cqh_first; sp != (void *)&__global_list->dq; sp = sp->q.cqe_next) {
++ if (!EXP(sp))
++ continue;
++ for (tp = EXP(sp)->tagq.tqh_first; tp != NULL; tp = tp->q.tqe_next) {
++ if (!tp->frp || !F_ISSET(tp->frp, FR_GTAGSTMP))
++ continue;
++ if (!strcmp(tp->frp->name, gtagstmp))
++ ++tagcnt;
++ }
++ }
++ if (tagcnt == 1)
++ return 1;
++ if (tagcnt > 1)
++ return 0;
++ /* IMPOSSIBLE */
++ return 0;
++ }
++ #endif
++
+ /*
+ * ex_tagfirst --
+ * The tag code can be entered from main, i.e. "vi -t tag".
+***************
+*** 86,96 ****
+--- 298,317 ----
+ u_int flags;
+ int sval;
+ char *p, *tag, *name, *search;
++ #ifdef GTAGS
++ int gtagselect = 0;
++ #endif
+
+ /* Taglength may limit the number of characters. */
+ if ((tl = O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(tagarg) > tl)
+ tagarg[tl] = '\0';
+
++ #ifdef GTAGS
++ if (O_ISSET(sp, O_GTAGSMODE)) {
++ if (gtag_get(sp, 0, &gtagselect, tagarg, &tag, &name, &search))
++ return (1);
++ } else
++ #endif
+ /* Get the tag information. */
+ if (tag_get(sp, tagarg, &tag, &name, &search))
+ return (1);
+***************
+*** 106,111 ****
+--- 327,336 ----
+ * The historic tags file format (from a long, long time ago...)
+ * used a line number, not a search string. I got complaints, so
+ * people are still using the format.
++ #ifdef GTAGS
++ * Yes, gtags use the old format. Search string is very flexible
++ * but is not suitable to treat duplicate entries.
++ #endif
+ */
+ if (isdigit(search[0])) {
+ m.lno = atoi(search);
+***************
+*** 132,137 ****
+--- 357,371 ----
+ frp->lno = m.lno;
+ frp->cno = m.cno;
+ F_SET(frp, FR_CURSORSET);
++ #ifdef GTAGS
++ if (gtagselect) {
++ F_SET(frp, FR_GTAGSTMP);
++ if (!(sp->gp->gtagstmp = strdup(name))) {
++ msgq(sp, M_SYSERR, NULL);
++ return (1);
++ }
++ }
++ #endif
+
+ /* Might as well make this the default tag. */
+ if ((EXP(sp)->tlast = strdup(tagarg)) == NULL) {
+***************
+*** 142,153 ****
+--- 376,399 ----
+ }
+
+ /* Free a tag or tagf structure from a queue. */
++ #ifdef GTAGS
+ #define FREETAG(tp) { \
++ if (F_ISSET(tp->frp, FR_GTAGSTMP)) \
++ if (should_delete(tp->frp->name)) \
++ unlink(tp->frp->name); \
+ TAILQ_REMOVE(&exp->tagq, (tp), q); \
+ if ((tp)->search != NULL) \
+ free((tp)->search); \
+ FREE((tp), sizeof(TAGF)); \
+ }
++ #else
++ #define FREETAG(tp) { \
++ TAILQ_REMOVE(&exp->tagq, (tp), q); \
++ if ((tp)->search != NULL) \
++ free((tp)->search); \
++ FREE((tp), sizeof(TAGF)); \
++ }
++ #endif
+ #define FREETAGF(tfp) { \
+ TAILQ_REMOVE(&exp->tagfq, (tfp), q); \
+ free((tfp)->name); \
+***************
+*** 182,189 ****
+--- 428,464 ----
+ int sval;
+ long tl;
+ char *name, *p, *search, *tag;
++ #ifdef GTAGS
++ int gtagselect = 0;
++ char *line;
++ size_t len;
++ char tagbuf[80], namebuf[200], linebuf[10];
++ #endif
+
+ exp = EXP(sp);
++ #ifdef GTAGS
++ /*
++ * Enter from gtag select mode.
++ * get tag information from current line.
++ */
++ if (F_ISSET(cmdp, E_GTAGSELECT)) {
++ if ((line = file_gline(sp, ep, sp->lno, &len)) == NULL) {
++ GETLINE_ERR(sp, sp->lno);
++ return (1);
++ }
++ if (getentry(line, tagbuf, namebuf, linebuf) == 0) {
++ msgq(sp, M_ERR, "illegal tag entry");
++ return (1);
++ }
++ if (!(tag = strdup(tagbuf))) {
++ msgq(sp, M_SYSERR, NULL);
++ return (1);
++ }
++ name = namebuf;
++ search = linebuf;
++ goto getfref;
++ }
++ #endif
+ switch (cmdp->argc) {
+ case 1:
+ if (exp->tlast != NULL)
+***************
+*** 207,216 ****
+--- 482,504 ----
+ if ((tl = O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(exp->tlast) > tl)
+ exp->tlast[tl] = '\0';
+
++ #ifdef GTAGS
++ if (O_ISSET(sp, O_GTAGSMODE)) {
++ if (gtag_get(sp, F_ISSET(cmdp->cmd, E_REFERENCE), &gtagselect,
++ exp->tlast, &tag, &name, &search))
++ return (1);
++ } else if (F_ISSET(cmdp->cmd, E_REFERENCE)) {
++ msgq(sp, M_ERR, "Please set gtagsmode");
++ return (1);
++ } else
++ #endif
+ /* Get the tag information. */
+ if (tag_get(sp, exp->tlast, &tag, &name, &search))
+ return (1);
+
++ #ifdef GTAGS
++ getfref:
++ #endif
+ /* Get the (possibly new) FREF structure. */
+ if ((frp = file_add(sp, name)) == NULL)
+ goto err;
+***************
+*** 305,310 ****
+--- 593,603 ----
+ sp->cno = m.cno;
+ break;
+ }
++ #ifdef GTAGS
++ if (gtagselect) {
++ F_SET(frp, FR_GTAGSTMP);
++ }
++ #endif
+ return (0);
+ }
+
+***************
+*** 490,495 ****
+--- 783,793 ----
+ for (cnt = 1, tp = exp->tagq.tqh_first; tp != NULL;
+ ++cnt, tp = tp->q.tqe_next) {
+ len = strlen(name = tp->frp->name); /* The original name. */
++ #ifdef GTAGS
++ if (F_ISSET(tp->frp, FR_GTAGSTMP)) {
++ (void)ex_printf(EXCOOKIE, "%2d [GTAGS]\n", cnt);
++ } else
++ #endif
+ if (len > maxlen || len + tp->slen > sp->cols)
+ if (tp == NULL || tp->search == NULL)
+ (void)ex_printf(EXCOOKIE,
+diff -c -r -N /usr/src/usr.bin/vi/ex/excmd.c ./ex/excmd.c
+*** /usr/src/usr.bin/vi/ex/excmd.c Thu Aug 18 10:13:29 1994
+--- ./ex/excmd.c Sat Dec 14 11:54:15 1996
+***************
+*** 319,324 ****
+--- 319,331 ----
+ "!",
+ "rew[ind][!]",
+ "re-edit all the files in the file argument list"},
++ #ifdef GTAGS
++ /* C_RTAG */
++ {"rtag", ex_tagpush, E_NOGLOBAL|E_REFERENCE,
++ "!w1o",
++ "rta[g][!] [string]",
++ "edit the file containing the tag"},
++ #endif
+ /* C_SUBSTITUTE */
+ {"substitute", ex_substitute, E_ADDR2|E_NORC,
+ "s",
+***************
+*** 329,334 ****
+--- 336,348 ----
+ "!f1o",
+ "sc[ript][!] [file]",
+ "run a shell in a screen"},
++ #ifdef GTAGS
++ /* C_GTAGSELECT */
++ {"select", ex_gtagselect, E_NOGLOBAL,
++ "",
++ "sel[ect]",
++ "edit the file containing the tag"},
++ #endif
+ /* C_SET */
+ {"set", ex_set, E_NOGLOBAL,
+ "wN",
+diff -c -r -N /usr/src/usr.bin/vi/ex/excmd.h.stub ./ex/excmd.h.stub
+*** /usr/src/usr.bin/vi/ex/excmd.h.stub Wed Aug 17 08:36:28 1994
+--- ./ex/excmd.h.stub Sat Dec 14 11:54:15 1996
+***************
+*** 69,74 ****
+--- 69,79 ----
+ #define E_NORC 0x0800000 /* Not from a .exrc or EXINIT. */
+ #define E_ZERO 0x1000000 /* 0 is a legal addr1. */
+ #define E_ZERODEF 0x2000000 /* 0 is default addr1 of empty files. */
++
++ #ifdef GTAGS
++ #define E_REFERENCE 0x4000000 /* locate function references */
++ #define E_GTAGSELECT 0x8000000 /* current line is gtags entry */
++ #endif
+ u_int32_t flags;
+ char *syntax; /* Syntax script. */
+ char *usage; /* Usage line. */
+***************
+*** 234,239 ****
+--- 239,245 ----
+ EXPROTO(ex_fg);
+ EXPROTO(ex_file);
+ EXPROTO(ex_global);
++ EXPROTO(ex_gtagselect);
+ EXPROTO(ex_help);
+ EXPROTO(ex_insert);
+ EXPROTO(ex_join);
+diff -c -r -N /usr/src/usr.bin/vi/svi/svi_refresh.c ./svi/svi_refresh.c
+*** /usr/src/usr.bin/vi/svi/svi_refresh.c Tue May 30 15:35:56 1995
+--- ./svi/svi_refresh.c Sat Dec 14 11:54:16 1996
+***************
+*** 725,731 ****
+--- 725,736 ----
+ EXF *ep;
+ {
+ size_t cols, curlen, endpoint, len, midpoint;
++ #ifdef GTAGS
++ char *p, buf[30];
++ recno_t last;
++ #else
+ char *p, buf[20];
++ #endif
+
+ /* Clear the mode line. */
+ MOVE(sp, INFOLINE(sp), 0);
+***************
+*** 746,751 ****
+--- 751,765 ----
+
+ curlen = 0;
+ if (sp->q.cqe_next != (void *)&sp->gp->dq) {
++ #ifdef GTAGS
++ if (F_ISSET(sp->frp, FR_GTAGSTMP)) {
++ if (file_lline(sp, ep, &last)) {
++ return (1);
++ }
++ sprintf(buf, "[GTAGS SELECT MODE] %d lines", last);
++ p = buf;
++ } else {
++ #endif
+ for (p = sp->frp->name; *p != '\0'; ++p);
+ while (--p > sp->frp->name) {
+ if (*p == '/') {
+***************
+*** 758,764 ****
+ break;
+ }
+ }
+!
+ MOVE(sp, INFOLINE(sp), 0);
+ standout();
+ for (; *p != '\0'; ++p)
+--- 772,780 ----
+ break;
+ }
+ }
+! #ifdef GTAGS
+! }
+! #endif
+ MOVE(sp, INFOLINE(sp), 0);
+ standout();
+ for (; *p != '\0'; ++p)
+diff -c -r -N /usr/src/usr.bin/vi/vi/v_ex.c ./vi/v_ex.c
+*** /usr/src/usr.bin/vi/vi/v_ex.c Thu Aug 18 10:15:03 1994
+--- ./vi/v_ex.c Sat Dec 14 11:54:16 1996
+***************
+*** 298,303 ****
+--- 298,308 ----
+ ARGS *ap[2], a;
+ EXCMDARG cmd;
+
++ #ifdef GTAGS
++ if (O_ISSET(sp, O_GTAGSMODE) && vp->m_start.cno == 0)
++ excmd(&cmd, C_RTAG, 0, OOBLNO, 0, 0, ap, &a, vp->keyword);
++ else
++ #endif
+ excmd(&cmd, C_TAG, 0, OOBLNO, 0, 0, ap, &a, vp->keyword);
+ return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
+ }
+diff -c -r -N /usr/src/usr.bin/vi/vi/v_scroll.c ./vi/v_scroll.c
+*** /usr/src/usr.bin/vi/vi/v_scroll.c Thu Aug 18 10:15:15 1994
+--- ./vi/v_scroll.c Sat Dec 14 11:54:16 1996
+***************
+*** 255,260 ****
+--- 255,269 ----
+ EXF *ep;
+ VICMDARG *vp;
+ {
++ #ifdef GTAGS
++ EXCMDARG cmd;
++
++ if (F_ISSET(sp->frp, FR_GTAGSTMP)) {
++ memset(&cmd, 0, sizeof(EXCMDARG));
++ cmd.cmd = &cmds[C_GTAGSELECT];
++ return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
++ }
++ #endif
+ /*
+ * If it's a script window, exec the line,
+ * otherwise it's the same as v_down().
diff --git a/contrib/global/nvi-1.79.diff b/contrib/global/nvi-1.79.diff
new file mode 100644
index 0000000..a0c8d55
--- /dev/null
+++ b/contrib/global/nvi-1.79.diff
@@ -0,0 +1,664 @@
+diff -c -r -N /usr/local/src/nvi-1.79/build/Makefile.in ./build/Makefile.in
+*** /usr/local/src/nvi-1.79/build/Makefile.in Wed Oct 23 22:43:38 1996
+--- ./build/Makefile.in Wed Apr 16 21:20:09 1997
+***************
+*** 3,9 ****
+ srcdir= @srcdir@/..
+ CC= @CC@
+ OPTFLAG=@OPTFLAG@
+! CFLAGS= -c $(OPTFLAG) @CFLAGS@ -I. -I$(srcdir)/include @CPPFLAGS@
+ LDFLAGS=@LDFLAGS@
+ PERL= @vi_cv_path_perl@
+ PERLLIB=@vi_cv_perllib@
+--- 3,9 ----
+ srcdir= @srcdir@/..
+ CC= @CC@
+ OPTFLAG=@OPTFLAG@
+! CFLAGS= -c $(OPTFLAG) @CFLAGS@ -I. -I$(srcdir)/include @CPPFLAGS@ -DGTAGS
+ LDFLAGS=@LDFLAGS@
+ PERL= @vi_cv_path_perl@
+ PERLLIB=@vi_cv_perllib@
+diff -c -r -N /usr/local/src/nvi-1.79/common/main.c ./common/main.c
+*** /usr/local/src/nvi-1.79/common/main.c Sat Oct 12 07:28:28 1996
+--- ./common/main.c Wed Apr 16 21:20:09 1997
+***************
+*** 64,69 ****
+--- 64,72 ----
+ size_t len;
+ u_int flags;
+ int ch, flagchk, lflag, secure, startup, readonly, rval, silent;
++ #ifdef GTAGS
++ int gtags = 0;
++ #endif
+ char *tag_f, *wsizearg, path[256];
+
+ /* Initialize the busy routine, if not defined by the screen. */
+***************
+*** 113,123 ****
+--- 116,134 ----
+ /* Set the file snapshot flag. */
+ F_SET(gp, G_SNAPSHOT);
+
++ #ifdef GTAGS
++ #ifdef DEBUG
++ while ((ch = getopt(argc, argv, "c:D:eFGlRrSsT:t:vw:")) != EOF)
++ #else
++ while ((ch = getopt(argc, argv, "c:eFGlRrSst:vw:")) != EOF)
++ #endif
++ #else
+ #ifdef DEBUG
+ while ((ch = getopt(argc, argv, "c:D:eFlRrSsT:t:vw:")) != EOF)
+ #else
+ while ((ch = getopt(argc, argv, "c:eFlRrSst:vw:")) != EOF)
+ #endif
++ #endif
+ switch (ch) {
+ case 'c': /* Run the command. */
+ /*
+***************
+*** 154,159 ****
+--- 165,175 ----
+ case 'F': /* No snapshot. */
+ F_CLR(gp, G_SNAPSHOT);
+ break;
++ #ifdef GTAGS
++ case 'G': /* gtags mode. */
++ gtags = 1;
++ break;
++ #endif
+ case 'l': /* Set lisp, showmatch options. */
+ lflag = 1;
+ break;
+***************
+*** 252,257 ****
+--- 268,277 ----
+ }
+ if (readonly)
+ *oargp++ = O_READONLY;
++ #ifdef GTAGS
++ if (gtags)
++ *oargp++ = O_GTAGSMODE;
++ #endif
+ if (secure)
+ *oargp++ = O_SECURE;
+ *oargp = -1; /* Options initialization. */
+diff -c -r -N /usr/local/src/nvi-1.79/common/options.c ./common/options.c
+*** /usr/local/src/nvi-1.79/common/options.c Tue Oct 15 03:56:29 1996
+--- ./common/options.c Wed Apr 16 21:20:09 1997
+***************
+*** 80,85 ****
+--- 80,89 ----
+ {"filec", NULL, OPT_STR, 0},
+ /* O_FLASH HPUX */
+ {"flash", NULL, OPT_1BOOL, 0},
++ #ifdef GTAGS
++ /* O_GTAGSMODE FreeBSD2.2 */
++ {"gtagsmode", NULL, OPT_0BOOL, 0},
++ #endif
+ /* O_HARDTABS 4BSD */
+ {"hardtabs", NULL, OPT_NUM, 0},
+ /* O_ICLOWER 4.4BSD */
+***************
+*** 244,249 ****
+--- 248,256 ----
+ {"eb", O_ERRORBELLS}, /* 4BSD */
+ {"ed", O_EDCOMPATIBLE}, /* 4BSD */
+ {"ex", O_EXRC}, /* System V (undocumented) */
++ #ifdef GTAGS
++ {"gt", O_GTAGSMODE}, /* FreeBSD2.2 */
++ #endif
+ {"ht", O_HARDTABS}, /* 4BSD */
+ {"ic", O_IGNORECASE}, /* 4BSD */
+ {"li", O_LINES}, /* 4.4BSD */
+diff -c -r -N /usr/local/src/nvi-1.79/docs/USD.doc/vi.man/vi.1 ./docs/USD.doc/vi.man/vi.1
+*** /usr/local/src/nvi-1.79/docs/USD.doc/vi.man/vi.1 Fri Oct 11 10:34:05 1996
+--- ./docs/USD.doc/vi.man/vi.1 Wed Apr 16 21:20:09 1997
+***************
+*** 17,23 ****
+ .SH SYNOPSIS
+ .B ex
+ [\c
+! .B -eFRrSsv\c
+ ] [\c
+ .BI -c " cmd"\c
+ ] [\c
+--- 17,23 ----
+ .SH SYNOPSIS
+ .B ex
+ [\c
+! .B -eFGRrSsv\c
+ ] [\c
+ .BI -c " cmd"\c
+ ] [\c
+***************
+*** 28,34 ****
+ .br
+ .B vi
+ [\c
+! .B -eFlRrSv\c
+ ] [\c
+ .BI -c " cmd"\c
+ ] [\c
+--- 28,34 ----
+ .br
+ .B vi
+ [\c
+! .B -eFGlRrSv\c
+ ] [\c
+ .BI -c " cmd"\c
+ ] [\c
+***************
+*** 39,45 ****
+ .br
+ .B view
+ [\c
+! .B -eFRrSv\c
+ ] [\c
+ .BI -c " cmd"\c
+ ] [\c
+--- 39,45 ----
+ .br
+ .B view
+ [\c
+! .B -eFGRrSv\c
+ ] [\c
+ .BI -c " cmd"\c
+ ] [\c
+***************
+*** 121,126 ****
+--- 121,129 ----
+ .B \-l
+ Start editing with the lisp and showmatch options set.
+ .TP
++ .B \-G
++ Start editing in gtags mode, as if the gtagsmode option was set.
++ .TP
+ .B \-R
+ Start editing in read-only mode, as if the command name was
+ .IR view ,
+***************
+*** 429,434 ****
+--- 432,439 ----
+ .TP
+ .B "<control-]>"
+ Push a tag reference onto the tag stack.
++ In gtagsmode, if at the first column of line,
++ locate function references otherwise function definitions.
+ .TP
+ .B "<control-^>"
+ Switch to the most recently edited file.
+***************
+*** 940,945 ****
+--- 945,953 ----
+ .B "rew[ind][!]"
+ Rewind the argument list.
+ .TP
++ .B "rta[g][!] tagstring"
++ Edit the file refering the specified tag. (Only in gtagsmode)
++ .TP
+ .B "se[t] [option[=[value]] ...] [nooption ...] [option? ...] [all]"
+ Display or set editor options.
+ .TP
+***************
+*** 1109,1114 ****
+--- 1117,1125 ----
+ .TP
+ .B "flash [on]"
+ Flash the screen instead of beeping the keyboard on error.
++ .TP
++ .B "gtagsmode, gt [off]"
++ Use GTAGS and GRTAGS instead of tags.
+ .TP
+ .B "hardtabs, ht [8]"
+ Set the spacing between hardware tab settings.
+diff -c -r -N /usr/local/src/nvi-1.79/ex/ex.h ./ex/ex.h
+*** /usr/local/src/nvi-1.79/ex/ex.h Tue Aug 13 09:24:00 1996
+--- ./ex/ex.h Wed Apr 16 21:20:09 1997
+***************
+*** 152,157 ****
+--- 152,160 ----
+ #define E_SEARCH_WMSG 0x01000000 /* Display search-wrapped message. */
+ #define E_USELASTCMD 0x02000000 /* Use the last command. */
+ #define E_VISEARCH 0x04000000 /* It's really a vi search command. */
++ #ifdef GTAGS
++ #define E_REFERENCE 0x08000000 /* locate function references */
++ #endif
+ u_int32_t flags; /* Current flags. */
+ };
+
+diff -c -r -N /usr/local/src/nvi-1.79/ex/ex_cmd.c ./ex/ex_cmd.c
+*** /usr/local/src/nvi-1.79/ex/ex_cmd.c Wed Oct 23 22:31:01 1996
+--- ./ex/ex_cmd.c Wed Apr 16 21:20:09 1997
+***************
+*** 302,307 ****
+--- 302,314 ----
+ "!",
+ "rew[ind][!]",
+ "re-edit all the files in the file argument list"},
++ #ifdef GTAGS
++ /* C_RTAG */
++ {"rtag", ex_rtag_push, E_NEWSCREEN,
++ "!w1o",
++ "[Rr]ta[g][!] [string]",
++ "edit the file containing the tag"},
++ #endif
+ /*
+ * !!!
+ * Adding new commands starting with 's' may break the substitute command code
+diff -c -r -N /usr/local/src/nvi-1.79/ex/ex_tag.c ./ex/ex_tag.c
+*** /usr/local/src/nvi-1.79/ex/ex_tag.c Mon Sep 16 05:02:43 1996
+--- ./ex/ex_tag.c Wed Apr 16 21:20:09 1997
+***************
+*** 46,51 ****
+--- 46,55 ----
+ static int compare __P((char *, char *, char *));
+ static void ctag_file __P((SCR *, TAGF *, char *, char **, size_t *));
+ static int ctag_search __P((SCR *, char *, size_t, char *));
++ #ifdef GTAGS
++ static int getentry __P((char *, char *, char *, char *));
++ static TAGQ *gtag_slist __P((SCR *, char *, int));
++ #endif
+ static int ctag_sfile __P((SCR *, TAGF *, TAGQ *, char *));
+ static TAGQ *ctag_slist __P((SCR *, char *));
+ static char *linear_search __P((char *, char *, char *));
+***************
+*** 89,94 ****
+--- 93,117 ----
+ return (0);
+ }
+
++ #ifdef GTAGS
++ /*
++ * ex_rtag_push -- ^]
++ * :rtag[!] [string]
++ *
++ * Enter a new TAGQ context based on a ctag string.
++ *
++ * PUBLIC: int ex_rtag_push __P((SCR *, EXCMD *));
++ */
++ int
++ ex_rtag_push(sp, cmdp)
++ SCR *sp;
++ EXCMD *cmdp;
++ {
++ F_SET(cmdp, E_REFERENCE);
++ return ex_tag_push(sp, cmdp);
++ }
++ #endif
++
+ /*
+ * ex_tag_push -- ^]
+ * :tag[!] [string]
+***************
+*** 138,143 ****
+--- 161,172 ----
+ }
+
+ /* Get the tag information. */
++ #ifdef GTAGS
++ if (O_ISSET(sp, O_GTAGSMODE)) {
++ if ((tqp = gtag_slist(sp, exp->tag_last, F_ISSET(cmdp, E_REFERENCE))) == NULL)
++ return (1);
++ } else
++ #endif
+ if ((tqp = ctag_slist(sp, exp->tag_last)) == NULL)
+ return (1);
+
+***************
+*** 969,974 ****
+--- 998,1116 ----
+ return (0);
+ }
+
++ #ifdef GTAGS
++ /*
++ * getentry --
++ * get tag information from current line.
++ *
++ * gtags temporary file format.
++ * <tag> <lineno> <file> <image>
++ *
++ * sample.
++ * +------------------------------------------------
++ * |main 30 main.c main(argc, argv)
++ * |func 21 subr.c func(arg)
++ */
++ static int
++ getentry(buf, tag, file, line)
++ char *buf, *tag, *file, *line;
++ {
++ char *p;
++
++ p = tag;
++ while (*buf && !isspace(*buf)) /* tag name */
++ *p++ = *buf++;
++ *p = 0;
++ while (*buf && isspace(*buf)) /* skip blanks */
++ buf++;
++ p = line;
++ while (*buf && !isspace(*buf)) /* line no */
++ *p++ = *buf++;
++ *p = 0;
++ while (*buf && isspace(*buf)) /* skip blanks */
++ buf++;
++ p = file;
++ while (*buf && !isspace(*buf)) /* file name */
++ *p++ = *buf++;
++ *p = 0;
++
++ /* value check */
++ if (strlen(tag) && strlen(line) && strlen(file) && atoi(line) > 0)
++ return 1; /* OK */
++ return 0; /* ERROR */
++ }
++
++ /*
++ * gtag_slist --
++ * Search the list of tags files for a tag, and return tag queue.
++ */
++ static TAGQ *
++ gtag_slist(sp, tag, ref)
++ SCR *sp;
++ char *tag;
++ int ref;
++ {
++ EX_PRIVATE *exp;
++ TAGF *tfp;
++ TAGQ *tqp;
++ size_t len;
++ int echk;
++ TAG *tp;
++ static char name[80], file[200], line[10];
++ char command[200];
++ char buf[BUFSIZ+1];
++ FILE *fp;
++
++ /* Allocate and initialize the tag queue structure. */
++ len = strlen(tag);
++ CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
++ CIRCLEQ_INIT(&tqp->tagq);
++ tqp->tag = tqp->buf;
++ memcpy(tqp->tag, tag, (tqp->tlen = len) + 1);
++
++ /*
++ * Find the tag, only display missing file messages once, and
++ * then only if we didn't find the tag.
++ */
++ sprintf(command, "global -%s '%s'", ref ? "rx" : "x", tag);
++ if (fp = popen(command, "r")) {
++ while (fgets(buf, sizeof(buf), fp)) {
++ if (buf[strlen(buf)-1] == '\n') /* chop(buf) */
++ buf[strlen(buf)-1] = 0;
++ else
++ while (fgetc(fp) != '\n')
++ ;
++ if (getentry(buf, name, file, line) == 0) {
++ echk = 1;
++ F_SET(tfp, TAGF_ERR);
++ break;
++ }
++ CALLOC_GOTO(sp, tp,
++ TAG *, 1, sizeof(TAG) + strlen(file) + 1 + strlen(line) + 1);
++ tp->fname = tp->buf;
++ strcpy(tp->fname, file);
++ tp->fnlen = strlen(file);
++ tp->search = tp->fname + tp->fnlen + 1;
++ strcpy(tp->search, line);
++ CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
++ }
++ pclose(fp);
++ }
++
++ /* Check to see if we found anything. */
++ if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
++ msgq_str(sp, M_ERR, tag, "162|%s: tag not found");
++ free(tqp);
++ return (NULL);
++ }
++
++ tqp->current = tqp->tagq.cqh_first;
++ return (tqp);
++
++ alloc_err:
++ return (NULL);
++ }
++ #endif
+ /*
+ * ctag_slist --
+ * Search the list of tags files for a tag, and return tag queue.
+diff -c -r -N /usr/local/src/nvi-1.79/include/ex_def.h ./include/ex_def.h
+*** /usr/local/src/nvi-1.79/include/ex_def.h Wed Oct 23 22:53:09 1996
+--- ./include/ex_def.h Wed Apr 16 21:20:09 1997
+***************
+*** 47,78 ****
+ #define C_RECOVER 46
+ #define C_RESIZE 47
+ #define C_REWIND 48
+! #define C_SUBSTITUTE 49
+! #define C_SCRIPT 50
+! #define C_SET 51
+! #define C_SHELL 52
+! #define C_SOURCE 53
+! #define C_STOP 54
+! #define C_SUSPEND 55
+! #define C_T 56
+! #define C_TAG 57
+! #define C_TAGNEXT 58
+! #define C_TAGPOP 59
+! #define C_TAGPREV 60
+! #define C_TAGTOP 61
+! #define C_TCLCMD 62
+! #define C_UNDO 63
+! #define C_UNABBREVIATE 64
+! #define C_UNMAP 65
+! #define C_V 66
+! #define C_VERSION 67
+! #define C_VISUAL_EX 68
+! #define C_VISUAL_VI 69
+! #define C_VIUSAGE 70
+! #define C_WRITE 71
+! #define C_WN 72
+! #define C_WQ 73
+! #define C_XIT 74
+! #define C_YANK 75
+! #define C_Z 76
+! #define C_SUBTILDE 77
+--- 47,79 ----
+ #define C_RECOVER 46
+ #define C_RESIZE 47
+ #define C_REWIND 48
+! #define C_RTAG 49
+! #define C_SUBSTITUTE 50
+! #define C_SCRIPT 51
+! #define C_SET 52
+! #define C_SHELL 53
+! #define C_SOURCE 54
+! #define C_STOP 55
+! #define C_SUSPEND 56
+! #define C_T 57
+! #define C_TAG 58
+! #define C_TAGNEXT 59
+! #define C_TAGPOP 60
+! #define C_TAGPREV 61
+! #define C_TAGTOP 62
+! #define C_TCLCMD 63
+! #define C_UNDO 64
+! #define C_UNABBREVIATE 65
+! #define C_UNMAP 66
+! #define C_V 67
+! #define C_VERSION 68
+! #define C_VISUAL_EX 69
+! #define C_VISUAL_VI 70
+! #define C_VIUSAGE 71
+! #define C_WRITE 72
+! #define C_WN 73
+! #define C_WQ 74
+! #define C_XIT 75
+! #define C_YANK 76
+! #define C_Z 77
+! #define C_SUBTILDE 78
+diff -c -r -N /usr/local/src/nvi-1.79/include/ex_extern.h ./include/ex_extern.h
+*** /usr/local/src/nvi-1.79/include/ex_extern.h Wed Oct 23 22:53:10 1996
+--- ./include/ex_extern.h Wed Apr 16 21:20:09 1997
+***************
+*** 89,94 ****
+--- 89,95 ----
+ char *, size_t, char **, size_t *, regex_t *, u_int));
+ void re_error __P((SCR *, int, regex_t *));
+ int ex_tag_first __P((SCR *, char *));
++ int ex_rtag_push __P((SCR *, EXCMD *));
+ int ex_tag_push __P((SCR *, EXCMD *));
+ int ex_tag_next __P((SCR *, EXCMD *));
+ int ex_tag_prev __P((SCR *, EXCMD *));
+diff -c -r -N /usr/local/src/nvi-1.79/include/options_def.h ./include/options_def.h
+*** /usr/local/src/nvi-1.79/include/options_def.h Wed Oct 23 22:53:10 1996
+--- ./include/options_def.h Wed Apr 16 21:20:09 1997
+***************
+*** 16,79 ****
+ #define O_EXTENDED 15
+ #define O_FILEC 16
+ #define O_FLASH 17
+! #define O_HARDTABS 18
+! #define O_ICLOWER 19
+! #define O_IGNORECASE 20
+! #define O_KEYTIME 21
+! #define O_LEFTRIGHT 22
+! #define O_LINES 23
+! #define O_LISP 24
+! #define O_LIST 25
+! #define O_LOCKFILES 26
+! #define O_MAGIC 27
+! #define O_MATCHTIME 28
+! #define O_MESG 29
+! #define O_MODELINE 30
+! #define O_MSGCAT 31
+! #define O_NOPRINT 32
+! #define O_NUMBER 33
+! #define O_OCTAL 34
+! #define O_OPEN 35
+! #define O_OPTIMIZE 36
+! #define O_PARAGRAPHS 37
+! #define O_PATH 38
+! #define O_PRINT 39
+! #define O_PROMPT 40
+! #define O_READONLY 41
+! #define O_RECDIR 42
+! #define O_REDRAW 43
+! #define O_REMAP 44
+! #define O_REPORT 45
+! #define O_RULER 46
+! #define O_SCROLL 47
+! #define O_SEARCHINCR 48
+! #define O_SECTIONS 49
+! #define O_SECURE 50
+! #define O_SHELL 51
+! #define O_SHELLMETA 52
+! #define O_SHIFTWIDTH 53
+! #define O_SHOWMATCH 54
+! #define O_SHOWMODE 55
+! #define O_SIDESCROLL 56
+! #define O_SLOWOPEN 57
+! #define O_SOURCEANY 58
+! #define O_TABSTOP 59
+! #define O_TAGLENGTH 60
+! #define O_TAGS 61
+! #define O_TERM 62
+! #define O_TERSE 63
+! #define O_TILDEOP 64
+! #define O_TIMEOUT 65
+! #define O_TTYWERASE 66
+! #define O_VERBOSE 67
+! #define O_W1200 68
+! #define O_W300 69
+! #define O_W9600 70
+! #define O_WARN 71
+! #define O_WINDOW 72
+! #define O_WINDOWNAME 73
+! #define O_WRAPLEN 74
+! #define O_WRAPMARGIN 75
+! #define O_WRAPSCAN 76
+! #define O_WRITEANY 77
+! #define O_OPTIONCOUNT 78
+--- 16,80 ----
+ #define O_EXTENDED 15
+ #define O_FILEC 16
+ #define O_FLASH 17
+! #define O_GTAGSMODE 18
+! #define O_HARDTABS 19
+! #define O_ICLOWER 20
+! #define O_IGNORECASE 21
+! #define O_KEYTIME 22
+! #define O_LEFTRIGHT 23
+! #define O_LINES 24
+! #define O_LISP 25
+! #define O_LIST 26
+! #define O_LOCKFILES 27
+! #define O_MAGIC 28
+! #define O_MATCHTIME 29
+! #define O_MESG 30
+! #define O_MODELINE 31
+! #define O_MSGCAT 32
+! #define O_NOPRINT 33
+! #define O_NUMBER 34
+! #define O_OCTAL 35
+! #define O_OPEN 36
+! #define O_OPTIMIZE 37
+! #define O_PARAGRAPHS 38
+! #define O_PATH 39
+! #define O_PRINT 40
+! #define O_PROMPT 41
+! #define O_READONLY 42
+! #define O_RECDIR 43
+! #define O_REDRAW 44
+! #define O_REMAP 45
+! #define O_REPORT 46
+! #define O_RULER 47
+! #define O_SCROLL 48
+! #define O_SEARCHINCR 49
+! #define O_SECTIONS 50
+! #define O_SECURE 51
+! #define O_SHELL 52
+! #define O_SHELLMETA 53
+! #define O_SHIFTWIDTH 54
+! #define O_SHOWMATCH 55
+! #define O_SHOWMODE 56
+! #define O_SIDESCROLL 57
+! #define O_SLOWOPEN 58
+! #define O_SOURCEANY 59
+! #define O_TABSTOP 60
+! #define O_TAGLENGTH 61
+! #define O_TAGS 62
+! #define O_TERM 63
+! #define O_TERSE 64
+! #define O_TILDEOP 65
+! #define O_TIMEOUT 66
+! #define O_TTYWERASE 67
+! #define O_VERBOSE 68
+! #define O_W1200 69
+! #define O_W300 70
+! #define O_W9600 71
+! #define O_WARN 72
+! #define O_WINDOW 73
+! #define O_WINDOWNAME 74
+! #define O_WRAPLEN 75
+! #define O_WRAPMARGIN 76
+! #define O_WRAPSCAN 77
+! #define O_WRITEANY 78
+! #define O_OPTIONCOUNT 79
+diff -c -r -N /usr/local/src/nvi-1.79/vi/v_ex.c ./vi/v_ex.c
+*** /usr/local/src/nvi-1.79/vi/v_ex.c Mon Sep 16 05:03:02 1996
+--- ./vi/v_ex.c Wed Apr 16 21:20:09 1997
+***************
+*** 226,231 ****
+--- 226,236 ----
+ ARGS *ap[2], a;
+ EXCMD cmd;
+
++ #ifdef GTAGS
++ if (O_ISSET(sp, O_GTAGSMODE) && vp->m_start.cno == 0)
++ ex_cinit(&cmd, C_RTAG, 0, OOBLNO, 0, 0, ap);
++ else
++ #endif
+ ex_cinit(&cmd, C_TAG, 0, OOBLNO, 0, 0, ap);
+ ex_cadd(&cmd, &a, VIP(sp)->keyw, strlen(VIP(sp)->keyw));
+ return (v_exec_ex(sp, vp, &cmd));
diff --git a/contrib/global/systags/Makefile b/contrib/global/systags/Makefile
new file mode 100644
index 0000000..49c9806
--- /dev/null
+++ b/contrib/global/systags/Makefile
@@ -0,0 +1,7 @@
+# @(#)Makefile 1.0 (Berkeley) 4/21/96
+
+beforeinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/systags.sh ${DESTDIR}/usr/bin/systags
+
+.include <bsd.prog.mk>
diff --git a/contrib/global/systags/Makefile.generic b/contrib/global/systags/Makefile.generic
new file mode 100644
index 0000000..140046f
--- /dev/null
+++ b/contrib/global/systags/Makefile.generic
@@ -0,0 +1,10 @@
+# @(#)Makefile 29-Dec-96
+
+PROG = systags
+BINDIR = /usr/bin
+
+all:
+install:
+ cp $(PROG).sh $(BINDIR)/$(PROG)
+ chmod 755 $(BINDIR)/$(PROG)
+clean:
diff --git a/contrib/global/systags/systags.sh b/contrib/global/systags/systags.sh
new file mode 100755
index 0000000..f14c4ad
--- /dev/null
+++ b/contrib/global/systags/systags.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# Copyright (c) 1997 Shigio Yamaguchi. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Shigio Yamaguchi.
+# 4. Neither the name of the author nor the names of any co-contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# systags.sh 7-Jul-97
+#
+# script to make hypertext of kernel source.
+# supporting FreeBSD and Linux.
+#
+case $1 in
+-n) nflag=1; shift;;
+esac
+case $1 in
+"") dir=.;;
+*) dir=$1;;
+esac
+#
+# get release number from source tree.
+#
+if [ -f conf/newvers.sh ]; then
+ os=FreeBSD
+ release=`awk -F= '/^RELEASE=/ {print $2}' < conf/newvers.sh`
+elif [ -f Makefile ] && grep '^vmlinux:' Makefile >/dev/null; then
+ os=Linux
+ version=`awk -F= '/^VERSION *=/ {print $2}' < Makefile`
+ patchlevel=`awk -F= '/^PATCHLEVEL *=/ {print $2}' < Makefile`
+ sublevel=`awk -F= '/^SUBLEVEL *=/ {print $2}' < Makefile`
+ release=`echo "$version.$patchlevel.$sublevel" | tr -d ' '`
+fi
+#
+# remove old files
+#
+case $nflag in
+1) echo "rm -rf $dir/htags.log $dir/GTAGS $dir/GRTAGS $dir/HTML";;
+*) rm -rf $dir/htags.log $dir/GTAGS $dir/GRTAGS $dir/HTML;;
+esac
+#
+# make global database(GTAGS, GRTAGS).
+#
+case $nflag in
+1) echo "gtags -se $dir";;
+*) gtags -se $dir;;
+esac
+case $? in
+0) ;;
+*) exit 1;;
+esac
+#
+# make hypertext.
+# (please replace this title with a suitable one.)
+#
+case $os$release in
+"") program=`/bin/pwd | sed 's/.*\///'`
+ title="Welcome to $program source tour!";;
+*) title="Welcome to $os $release kernel source tour!";;
+esac
+case $nflag in
+1) echo "htags -fnvat '$title' -d $dir $dir > $dir/htags.log 2>&1";;
+*) htags -fnvat "$title" -d $dir $dir> $dir/htags.log 2>&1;;
+esac
OpenPOWER on IntegriCloud