summaryrefslogtreecommitdiffstats
path: root/usr.bin/global
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1997-04-15 12:30:38 +0000
committerjkh <jkh@FreeBSD.org>1997-04-15 12:30:38 +0000
commit29e9ef05d0c260d4547756e194224176c57611ec (patch)
treefec9d4361eb5f7d1b15c25c7d963be41051af145 /usr.bin/global
downloadFreeBSD-src-29e9ef05d0c260d4547756e194224176c57611ec.zip
FreeBSD-src-29e9ef05d0c260d4547756e194224176c57611ec.tar.gz
Shigio Yamaguchi's global tags package. The infrastructure support
for this is already in place, so "make tags" (or "make tags HTML=yes") should work after your next make world. Submitted by: Shigio Yamaguchi <shigio@wafu.netgate.net>
Diffstat (limited to 'usr.bin/global')
-rw-r--r--usr.bin/global/HISTORY131
-rw-r--r--usr.bin/global/MANIFEST16
-rw-r--r--usr.bin/global/Makefile3
-rw-r--r--usr.bin/global/Makefile.inc1
-rw-r--r--usr.bin/global/README527
-rw-r--r--usr.bin/global/VERSION1
-rw-r--r--usr.bin/global/btreeop/Makefile5
-rw-r--r--usr.bin/global/btreeop/btreeop.1142
-rw-r--r--usr.bin/global/btreeop/btreeop.c308
-rw-r--r--usr.bin/global/gctags/C.c840
-rw-r--r--usr.bin/global/gctags/Makefile7
-rw-r--r--usr.bin/global/gctags/ctags.c402
-rw-r--r--usr.bin/global/gctags/ctags.h110
-rw-r--r--usr.bin/global/gctags/fortran.c168
-rw-r--r--usr.bin/global/gctags/gctags.1228
-rw-r--r--usr.bin/global/gctags/lisp.c105
-rw-r--r--usr.bin/global/gctags/print.c122
-rw-r--r--usr.bin/global/gctags/test/ctags.test67
-rw-r--r--usr.bin/global/gctags/tree.c145
-rw-r--r--usr.bin/global/gctags/yacc.c151
-rw-r--r--usr.bin/global/global/Makefile9
-rw-r--r--usr.bin/global/global/global.1130
-rw-r--r--usr.bin/global/global/global.pl213
-rw-r--r--usr.bin/global/gtags/Makefile9
-rw-r--r--usr.bin/global/gtags/gtags.181
-rw-r--r--usr.bin/global/gtags/gtags.sh98
-rw-r--r--usr.bin/global/htags/Makefile9
-rw-r--r--usr.bin/global/htags/htags.199
-rwxr-xr-xusr.bin/global/htags/htags.pl1043
-rw-r--r--usr.bin/global/systags/Makefile7
-rwxr-xr-xusr.bin/global/systags/systags.sh83
31 files changed, 5260 insertions, 0 deletions
diff --git a/usr.bin/global/HISTORY b/usr.bin/global/HISTORY
new file mode 100644
index 0000000..e591c74
--- /dev/null
+++ b/usr.bin/global/HISTORY
@@ -0,0 +1,131 @@
+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 mainly unification of files [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).
+ extended vi
+ - unify the VI entended patch.
+
+version 1.3 support of GTAGSLIBPATH [28-Jul-96]
+
+ [changed]
+ global - search in not only a source tree but also 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 - doesn't skip 'y.tab.c'.(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 - string 'param' follows '&' means specific charactor in hypertext.
+ So, changed internal separator from '&' to '|'.
+ [added]
+ gtags - -s option added. If specified, gtags extract ENTRY() and
+ ALTENTRY() from *.[sS] files.
+ htags - supports 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.
+ 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 and bug fix. [14-Apr-97]
+
+ [fixed bug]
+ extended vi
+ - doesn't hand '\' in a pattern to global.
+ [changed]
+ global
+ - can find tag file in obj directory.
diff --git a/usr.bin/global/MANIFEST b/usr.bin/global/MANIFEST
new file mode 100644
index 0000000..a03c42e
--- /dev/null
+++ b/usr.bin/global/MANIFEST
@@ -0,0 +1,16 @@
+HISTORY Histroy of GLOBAL.
+INSTALL Installation method
+MANIFEST This file.
+Makefile Makefile for generic UNIX(including BSD).
+Makefile.bsd Makefile for BSD.
+Makefile.inc A part of Makefile for 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.
+systags/ Script for kernel.
+nvi-1.34.diff Patch for nvi 1.34.
+nvi-1.76.diff Patch for nvi 1.76.
diff --git a/usr.bin/global/Makefile b/usr.bin/global/Makefile
new file mode 100644
index 0000000..2eb181e
--- /dev/null
+++ b/usr.bin/global/Makefile
@@ -0,0 +1,3 @@
+SUBDIR= gctags global gtags btreeop htags systags
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/global/Makefile.inc b/usr.bin/global/Makefile.inc
new file mode 100644
index 0000000..c24c4b1
--- /dev/null
+++ b/usr.bin/global/Makefile.inc
@@ -0,0 +1 @@
+BINDIR?= /usr/bin
diff --git a/usr.bin/global/README b/usr.bin/global/README
new file mode 100644
index 0000000..4259637
--- /dev/null
+++ b/usr.bin/global/README
@@ -0,0 +1,527 @@
+
+ @@@@@@@-
+ @- @-
+ @- @-
+ @- @- @@@@@- @@@@@@- @@- @-
+ @- F o r a l l h a c h e r s. version 1.8
+ @- @@@@@@-@- @- @- @@@@@- @- @- @-
+ @- @- @- @- @- @- @- @@@@@- @-
+ @- @- @- @- @- @- @-@- @- @-
+ @@@@@@@@- @@@@- @@@@@- @@@@@@-@@@- @@@@- @@@@@@-
+
+ Shigio Yamaguchi 5-Apr-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
+ --------------------------------
+
+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')
+
+GLOBAL is consist of global(1), gtags(1), btreeop(1), gctags(1), htags(1)
+and extended vi(1).
+
+ * '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.76 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.76 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>
+ ":tagpop"
+ ":tagtop"
+ ":display tags"
+
+ 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 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/*) 42MB(!!!)
+
+ 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 IE3.0 doesn't work well about index.)
+
+ 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 or Linux 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 one level nested index and browse assembler source file too.
+
+Thank you for your reading of my poor english.
+And of course, thank you Keith Bostic (the author of nvi(1) and db(3)).
+----------------------------------------------------------------------------
+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/usr.bin/global/VERSION b/usr.bin/global/VERSION
new file mode 100644
index 0000000..ea3769f
--- /dev/null
+++ b/usr.bin/global/VERSION
@@ -0,0 +1 @@
+1.81
diff --git a/usr.bin/global/btreeop/Makefile b/usr.bin/global/btreeop/Makefile
new file mode 100644
index 0000000..c9e0409
--- /dev/null
+++ b/usr.bin/global/btreeop/Makefile
@@ -0,0 +1,5 @@
+# @(#)Makefile 1.0 (Berkeley) 4/21/96
+
+PROG= btreeop
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/global/btreeop/btreeop.1 b/usr.bin/global/btreeop/btreeop.1
new file mode 100644
index 0000000..b6baa6d
--- /dev/null
+++ b/usr.bin/global/btreeop/btreeop.1
@@ -0,0 +1,142 @@
+.\"
+.\" 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, 1996
+.Dt BTREEOP 1
+.Os BSD 4
+.Sh NAME
+.Nm btreeop
+.Nd btree database maintenance tool
+.Sh SYNOPSIS
+.Nm btreeop
+.Op Fl C
+.Op Fl K Ar key
+.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 and read (sequential or index) 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 C
+create database.
+.It Fl K Ar key
+search data by the key.
+.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 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.
+.El
+.Sh EXAMPLES
+Create database.
+
+ % btreeop -C
+ key1 data1
+ key2 data2
+ key2 data2-2
+ key3 data3
+ ^D
+ %
+
+Sequential read.
+
+ % btreeop
+ key2 data2
+ key3 data3
+ key2 data2-2
+ key1 data1
+ %
+
+Indexed read.
+
+ % btreeop -K key2
+ key2 data2-2
+ key2 data2
+ %
+
+.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 BUGS
+.Nm btreeop
+cannot utilize all features of
+.Xr btree 3
+.Sh AUTHOR
+Shigio Yamaguchi (shigio@wafu.netgate.net)
diff --git a/usr.bin/global/btreeop/btreeop.c b/usr.bin/global/btreeop/btreeop.c
new file mode 100644
index 0000000..1d2faeb
--- /dev/null
+++ b/usr.bin/global/btreeop/btreeop.c
@@ -0,0 +1,308 @@
+/*
+ * 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 5-Apr-97
+ *
+ */
+#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 *progname = "btreeop"; /* command name */
+char *dbname;
+char buf[BUFSIZ+1];
+
+#ifndef __P
+#if defined(__STDC__)
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+void die __P((char *));
+void usage __P((void));
+void entab __P((char *));
+void main __P((int, char **));
+int dbcreate __P((DB *));
+int dbkey __P((DB *, char *));
+int dbscan __P((DB *));
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+
+void
+die(s)
+char *s;
+{
+ fprintf(stderr, "%s: %s\n", progname, s);
+ exit(1);
+}
+
+void
+usage() {
+ fprintf(stderr,
+ "usage: %s [-C][-K key][-b][-c cachesize][-l][-p psize][dbname]\n",
+ progname);
+ 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;
+}
+
+#include <errno.h>
+void
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ char command = 0;
+ char *key = NULL;
+ DB *db;
+ BTREEINFO info;
+ int c;
+
+ 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, "CK:bc:lp:")) != EOF) {
+ switch (c) {
+ case 'K':
+ key = optarg;
+ case 'C':
+ 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;
+ db = dbopen(dbname, command == 'C' ?
+ O_RDWR|O_CREAT|O_TRUNC : O_RDONLY,
+ 0644, DB_BTREE, &info);
+
+ if (db == NULL) {
+ die("dbopen failed.");
+ }
+ switch (command) {
+ case 'C': /* Create database */
+ dbcreate(db);
+ break;
+ case 'K': /* Keyed search */
+ dbkey(db, key);
+ break;
+ default: /* Scan all data */
+ dbscan(db);
+ break;
+ }
+ if (db->close(db)) {
+ die("db->close failed.");
+ }
+ exit(0);
+}
+/*
+ * dbcreate: create database
+ *
+ * i) db
+ * r) 0: normal
+ */
+int
+dbcreate(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.
+ */
+ while (fgets(buf, BUFSIZ, stdin)) {
+ if (buf[strlen(buf)-1] == '\n') /* chop(buf) */
+ buf[strlen(buf)-1] = 0;
+ else
+ while (fgetc(stdin) != '\n')
+ ;
+ for (c = buf; *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.");
+ }
+ }
+ return(0);
+}
+
+/*
+ * dbkey: Keyed search
+ *
+ * i) db
+ * i) skey
+ * r) 0: normal
+ * 1: not found
+ */
+int
+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)) {
+ (void)fprintf(stdout, "%s\n", (char *)dat.data);
+ }
+
+ if (status == RET_ERROR)
+ die("db->seq failed.");
+ return (0);
+}
+
+/*
+ * dbscan: Scan all data
+ *
+ * i) db
+ * r) 0: normal
+ * 1: not found
+ */
+int
+dbscan(db)
+DB *db;
+{
+ DBT dat, key;
+ int status;
+
+ for (status = (*db->seq)(db, &key, &dat, R_FIRST);
+ status == RET_SUCCESS;
+ status = (*db->seq)(db, &key, &dat, R_NEXT)) {
+ (void)fprintf(stdout, "%s\n", (char *)dat.data);
+ }
+ if (status == RET_ERROR)
+ die("db->seq failed.");
+ return (0);
+}
diff --git a/usr.bin/global/gctags/C.c b/usr.bin/global/gctags/C.c
new file mode 100644
index 0000000..87652b5
--- /dev/null
+++ b/usr.bin/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/usr.bin/global/gctags/Makefile b/usr.bin/global/gctags/Makefile
new file mode 100644
index 0000000..bc0cbbf
--- /dev/null
+++ b/usr.bin/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
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/global/gctags/ctags.c b/usr.bin/global/gctags/ctags.c
new file mode 100644
index 0000000..e0f0428
--- /dev/null
+++ b/usr.bin/global/gctags/ctags.c
@@ -0,0 +1,402 @@
+/*
+ * 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 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 char sccsid[] = "@(#)ctags.c 8.3 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+
+#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 *));
+int main __P((int, char **));
+
+int
+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 */
+
+#ifndef lint
+ copyright[0] = copyright[0]; /* to satisfy compiler */
+#endif
+ aflag = uflag = NO;
+#ifdef GTAGS
+ while ((ch = getopt(argc, argv, "BDFadef:rtuwvxy")) != EOF)
+#else
+ while ((ch = getopt(argc, argv, "BFadf:tuwvx")) != EOF)
+#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:
+ goto usage;
+ }
+ argv += optind;
+ argc -= optind;
+ if (!argc) {
+usage: (void)fprintf(stderr,
+#ifdef GTAGS
+ "usage: ctags [-BDFadrtuwvx] [-f tagsfile] file ...\n");
+#else
+ "usage: ctags [-BFadtuwvx] [-f tagsfile] file ...\n");
+#endif
+ exit(1);
+ }
+#ifdef GTAGS
+ if (rflag)
+ gtagopen();
+#endif
+ init();
+
+ for (exit_val = step = 0; step < argc; ++step)
+ if (!(inf = fopen(argv[step], "r"))) {
+ fprintf(stderr, "gctags: %s cannot open\n", 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"))) {
+ fprintf(stderr, "gctags: %s cannot open\n", 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);
+}
+
+/*
+ * 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();
+ }
+/* 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) {
+ fprintf(stderr, "GTAGS file needed.\n");
+ exit(1);
+ }
+}
+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:
+ fprintf(stderr, "db->get failed.\n");
+ exit(1);
+ case RET_SPECIAL: /* not exist */
+ break;
+ }
+ return 0;
+}
+void
+gtagclose()
+{
+ if (db->close(db)) {
+ fprintf(stderr, "GTAGS cannot close.(dbclose)\n");
+ exit(1);
+ }
+}
+#endif
diff --git a/usr.bin/global/gctags/ctags.h b/usr.bin/global/gctags/ctags.h
new file mode 100644
index 0000000..7fa84b8
--- /dev/null
+++ b/usr.bin/global/gctags/ctags.h
@@ -0,0 +1,110 @@
+/*
+ * 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));
+void gtagopen __P((void));
+int isdefined __P((char *));
+void gtagclose __P((void));
diff --git a/usr.bin/global/gctags/fortran.c b/usr.bin/global/gctags/fortran.c
new file mode 100644
index 0000000..2a33aff
--- /dev/null
+++ b/usr.bin/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/usr.bin/global/gctags/gctags.1 b/usr.bin/global/gctags/gctags.1
new file mode 100644
index 0000000..927efc5
--- /dev/null
+++ b/usr.bin/global/gctags/gctags.1
@@ -0,0 +1,228 @@
+.\" 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 June 6, 1993
+.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, and lisp 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
+forece a function to end when reach a '}' at the first column. (C source only)
+.It Fl f
+Places 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. 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 ex 1 ,
+.Xr vi 1 ,
+.Xr gtags 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.
+.Sh HISTORY
+The
+.Nm Ctags
+command appeared in
+.Bx 3.0 .
+The
+.Nm
+command appeared in GLOBAL 1.6 .
diff --git a/usr.bin/global/gctags/lisp.c b/usr.bin/global/gctags/lisp.c
new file mode 100644
index 0000000..ebf5184
--- /dev/null
+++ b/usr.bin/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/usr.bin/global/gctags/print.c b/usr.bin/global/gctags/print.c
new file mode 100644
index 0000000..692d36b
--- /dev/null
+++ b/usr.bin/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/usr.bin/global/gctags/test/ctags.test b/usr.bin/global/gctags/test/ctags.test
new file mode 100644
index 0000000..1f334ac
--- /dev/null
+++ b/usr.bin/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/usr.bin/global/gctags/tree.c b/usr.bin/global/gctags/tree.c
new file mode 100644
index 0000000..831691a
--- /dev/null
+++ b/usr.bin/global/gctags/tree.c
@@ -0,0 +1,145 @@
+/*
+ * 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 <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)))) {
+ fprintf(stderr, "too many entries to sort");
+ put_entries(head);
+ free_tree(head);
+ /*NOSTRICT*/
+ if (!(head = np = (NODE *)malloc(sizeof(NODE)))) {
+ fprintf(stderr, "gctags: out of space\n");
+ exit(1);
+ }
+ }
+ 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))) {
+ fprintf(stderr, "gctags: out of space\n");
+ exit(1);
+ }
+ np->file = curfile;
+ np->lno = ln;
+ np->left = np->right = 0;
+ if (!(np->pat = strdup(lbuf))) {
+ fprintf(stderr, "gctags: out of space\n");
+ exit(1);
+ }
+ 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/usr.bin/global/gctags/yacc.c b/usr.bin/global/gctags/yacc.c
new file mode 100644
index 0000000..9dcdd5a
--- /dev/null
+++ b/usr.bin/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/usr.bin/global/global/Makefile b/usr.bin/global/global/Makefile
new file mode 100644
index 0000000..256ea71
--- /dev/null
+++ b/usr.bin/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/usr.bin/global/global/global.1 b/usr.bin/global/global/global.1
new file mode 100644
index 0000000..f86f40a
--- /dev/null
+++ b/usr.bin/global/global/global.1
@@ -0,0 +1,130 @@
+.\"
+.\" 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 Jul 28, 1996
+.Dt GLOBAL 1
+.Os BSD 4
+.Sh NAME
+.Nm global
+.Nd print the locations of specified function in C and Yacc source files.
+.Sh SYNOPSIS
+.Nm global
+.Op Fl acrx
+.Ar name
+.Sh DESCRIPTION
+.Nm Global
+find the locatins 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
+print candidate function names which start with specified string.
+If string is not specified, print all function names.
+.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 gtags 1 ,
+.Xr btreeop 1
+.Sh AUTHORS
+Shigio Yamaguchi (shigio@wafu.netgate.net)
diff --git a/usr.bin/global/global/global.pl b/usr.bin/global/global/global.pl
new file mode 100644
index 0000000..f1e0cb9
--- /dev/null
+++ b/usr.bin/global/global/global.pl
@@ -0,0 +1,213 @@
+#!/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 14-Apr-97
+#
+sub getcwd {
+ local($dir);
+ chop($dir = `/bin/pwd`);
+ $dir;
+}
+$com = $0;
+$com =~ s/.*\///;
+$usage = "usage:\t$com [-a][-r][-x] pattern\n\t$com -c [name]\n";
+#
+# options check
+#
+while ($ARGV[0] =~ /^-/) {
+ $opt = shift;
+ if ($opt =~ /a/) { $aflag = 1; }
+ if ($opt =~ /c/) { $cflag = 1; }
+ if ($opt =~ /r/) { $rflag = 1; }
+ if ($opt =~ /x/) { $xflag = 1; }
+}
+if (@ARGV == 0) {
+ die($usage) if (! $cflag);
+} elsif ($ARGV[0] =~ /[][.*\^\$+?|(){}\\]/) { # include regular expression ?
+ $regex = 1;
+}
+if ($cflag) {
+ die($usage) if ($aflag || $rflag || $xflag);
+ die("$com: regular expression not allowed with -c option.\n") if ($regex);
+}
+$current = &getcwd;
+#
+# get $dbpath and $root
+#
+if (defined($ENV{'GTAGSROOT'})) {
+ $root = $ENV{'GTAGSROOT'};
+ if (defined($ENV{'GTAGSDBPATH'})) {
+ $dbpath = $ENV{'GTAGSDBPATH'};
+ } else {
+ $dbpath = $root;
+ }
+ unless ($current =~ /$root/) {
+ die("$com: illegal GTAGSROOT.\n");
+ }
+ chdir($dbpath) || die("$com: directory $dbpath not found.\n");
+ $dbpath = &getcwd;
+ chdir($current);
+ chdir($root) || die("$com: directory $root not found.\n");
+ $root = &getcwd;
+}
+chdir($current) || die("$com: cannot return current directory.\n");
+$gtagsname = ($rflag) ? 'GRTAGS' : 'GTAGS';
+#
+# make a sed command to make paths into relative
+#
+if (! defined($root)) {
+ chdir($current);
+ while (! -r $gtagsname && ! -r "obj/$gtagsname") {
+ if (&getcwd =~ m!^/$!) { die "$com: $gtagsname not found.\n"; }
+ chdir('..');
+ }
+ $dbpath = $root = &getcwd;
+ $dbpath = "$dbpath/obj" if (! -r $gtagsname);
+}
+$cur = $current;
+$cur =~ s!$root!!;
+$cur =~ s!^/!!;
+@step = split('/', $cur);
+$downpath = '\\.\\./' x @step;
+push(@com, "-e 's!\\./!$downpath!'");
+foreach $step (@step) {
+ push(@com, "-e 's!\\.\\./$step/!!'");
+}
+#
+# complete function name
+#
+if ($cflag) {
+ open(PIPEIN, "btreeop $dbpath/GTAGS | awk '{print \$1}' | sort | uniq |") || die("$com: btreeop cannot exec.\n");
+ while (<PIPEIN>) {
+ print if (@ARGV == 0 || $_ =~ /^$ARGV[0]/o);
+ }
+ close(PIPEIN);
+ exit(0);
+}
+#
+# search in current source tree.
+#
+$cnt = &search($ARGV[0], $dbpath, $gtagsname, @com);
+#
+# search in library path.
+#
+if ($cnt == 0 && ! $regex && ! $rflag && defined($ENV{'GTAGSLIBPATH'})) {
+ foreach $lib (split(':', $ENV{'GTAGSLIBPATH'})) {
+ next unless (-f "$lib/GTAGS");
+ next if ($dbpath eq $lib);
+ chdir($lib) || die("$com: cannot chdir to $lib.\n");
+ $dbpath = &getcwd;
+ $common = &common($dbpath, $current);
+ $up = $dbpath;
+ $up =~ s/$common//;
+ $down = $current;
+ $down =~ s/$common//;
+ $down =~ s![^/]+!..!g;
+ next if ($down eq '' || $up eq '');
+ $cnt = &search($ARGV[0], $dbpath, 'GTAGS', ("-e 's!\\./!$down/$up/!'"));
+ last if ($cnt > 0);
+ }
+}
+exit(0);
+#
+# 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) $gtagsname gtags name (GTAGS or GRTAGS)
+# i) @com sed's command
+# gi) $xflag -x option
+# gi) $rflag -r option
+# gi) $regex regular expression
+# r) count of output lines
+#
+sub search {
+ local($pattern, $dbpath, $gtagsname, @com) = @_;
+ local($cnt);
+ #
+ # make input filter
+ #
+ if ($regex) { # regular expression
+ $infilter = "btreeop $dbpath/$gtagsname |";
+ } else {
+ $infilter = "btreeop -K '$pattern' $dbpath/$gtagsname |";
+ }
+ #
+ # make output filter
+ # gtags fields is same to ctags -x format.
+ # 0:tag, 1:lineno, 2:filename, 3: pattern.
+ #
+ if ($xflag) {
+ $outfilter = "| sort +0b -1 +2b -3 +1n -2";
+ } else {
+ $outfilter = "| awk '{print \$3}' | sort | uniq";
+ }
+ #
+ # if absolute path needed
+ #
+ if ($aflag) {
+ @com = ("-e 's!\\.!$dbpath!'");
+ }
+ $outfilter .= "| sed @com";
+ open(PIPEIN, $infilter) || die("$com: database not found.\n");
+ open(PIPEOUT, $outfilter) || die("$com: pipe cannot open.\n");
+ $cnt = 0;
+ while (<PIPEIN>) {
+ ($tag) = split;
+ if (! $regex || $tag =~ /$pattern/o) {
+ $cnt++;
+ print PIPEOUT $_;
+ }
+ }
+ close(PIPEIN);
+ close(PIPEOUT);
+ $cnt;
+}
diff --git a/usr.bin/global/gtags/Makefile b/usr.bin/global/gtags/Makefile
new file mode 100644
index 0000000..53355f3
--- /dev/null
+++ b/usr.bin/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.sh ${DESTDIR}/${BINDIR}/gtags
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/global/gtags/gtags.1 b/usr.bin/global/gtags/gtags.1
new file mode 100644
index 0000000..dca7a42
--- /dev/null
+++ b/usr.bin/global/gtags/gtags.1
@@ -0,0 +1,81 @@
+.\"
+.\" 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 Feb 17, 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 global 1 ,
+.Xr btreeop 1 ,
+.Xr gctags 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)
diff --git a/usr.bin/global/gtags/gtags.sh b/usr.bin/global/gtags/gtags.sh
new file mode 100644
index 0000000..85458bc
--- /dev/null
+++ b/usr.bin/global/gtags/gtags.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+#
+# 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.sh 17-Feb-97
+#
+com=`echo $0 | sed 's/.*\///'` # command name
+usage="usage: $com [-e][-s][dbpath]"
+#
+# ctags flag
+#
+eflag=
+sflag=
+while :; do
+ case $1 in
+ -*)
+ if echo $1 | grep '[^-es]' >/dev/null; then
+ echo $usage >/dev/tty; exit 1
+ fi
+ case $1 in
+ -*e*) eflag=e;;
+ esac
+ case $1 in
+ -*s*) sflag=1;;
+ esac
+ shift;;
+ *)
+ break;;
+ esac
+done
+export eflag sflag
+case $1 in
+"") dbpath=".";;
+*) dbpath=$1;;
+esac
+if [ -f $dbpath/GTAGS -a -f $dbpath/GRTAGS ]; then
+ if [ ! -w $dbpath/GTAGS ]; then
+ echo "$com: cannot write to GTAGS."
+ exit 1
+ elif [ ! -w $dbpath/GRTAGS ]; then
+ echo "$com: cannot write to GRTAGS."
+ exit 1
+ fi
+elif [ ! -w $dbpath ]; then
+ echo "$com: cannot write to the directory $dbpath."
+ exit 1
+fi
+#
+# make global database
+#
+for db in GTAGS GRTAGS; do
+ # currently only *.c *.h *.y are supported.
+ # *.s *.S is valid only when -s option specified.
+ find . -type f -name "*.[chysS]" -print | while read f; do
+ case $f in
+ *y.tab.c|*y.tab.h)
+ continue;;
+ *.s|*.S)
+ [ ${sflag}x = x -o $db = GRTAGS ] && continue
+ perl -ne '($nouse, $tag) = /^(ENTRY|ALTENTRY)\((\w+)\)/;
+ if ($tag) {printf("%-16s%4d %-16s %s", $tag, $., $ARGV, $_)} ' $f
+ continue;;
+ esac
+ case $db in
+ GRTAGS) flag=${eflag}Dxr;;
+ GTAGS) flag=${eflag}Dx;;
+ esac
+ GTAGDBPATH=$dbpath gctags -$flag $f || exit 1
+ done | btreeop -C $dbpath/$db
+done
+exit 0
diff --git a/usr.bin/global/htags/Makefile b/usr.bin/global/htags/Makefile
new file mode 100644
index 0000000..f53639a
--- /dev/null
+++ b/usr.bin/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/usr.bin/global/htags/htags.1 b/usr.bin/global/htags/htags.1
new file mode 100644
index 0000000..f82b37c
--- /dev/null
+++ b/usr.bin/global/htags/htags.1
@@ -0,0 +1,99 @@
+.\"
+.\" 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 Feb 17, 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 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.
+.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 alphabetical function index. It's suitable to large project.
+.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 -vat '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 DIAGNOSTICS
+.Nm Htags
+exits with a value of 1 if an error occurred, 0 otherwise.
+.Sh SEE ALSO
+.Xr gtags 1 ,
+.Xr btreeop 1
+.Sh BUG
+Generated hypertext is VERY LARGE. In advance, check the space of your disk.
+.Sh AUTHORS
+Shigio Yamaguchi (shigio@wafu.netgate.net)
diff --git a/usr.bin/global/htags/htags.pl b/usr.bin/global/htags/htags.pl
new file mode 100755
index 0000000..9c1a275
--- /dev/null
+++ b/usr.bin/global/htags/htags.pl
@@ -0,0 +1,1043 @@
+#!/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 5-Apr-97
+#
+$com = $0;
+$com =~ s/.*\///;
+$usage = "usage: $com [-a][-v][-w][-t title][-d tagdir][dir]";
+#-------------------------------------------------------------------------
+# 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';
+#-------------------------------------------------------------------------
+# DEFINITION
+#-------------------------------------------------------------------------
+# unit for a path
+$SEP = ' '; # source file path must not include $SEP charactor
+$ESCSEP = &escape($SEP);
+$SRCS = 'S';
+$DEFS = 'D';
+$REFS = 'R';
+$FILES = 'files';
+$FUNCS = 'funcs';
+#-------------------------------------------------------------------------
+# 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 =
+ "// IE3.0 seems to be not able to treat following code.\n" .
+ "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 =
+ "// IE3.0 seems to be not able to treat following code.\n" .
+ "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($msg);
+}
+sub clean {
+ &anchor'finish();
+ &cache'close();
+}
+sub escape {
+ local($c) = @_;
+ '%' . sprintf("%x", ord($c));
+}
+#-------------------------------------------------------------------------
+# PROCESS START
+#-------------------------------------------------------------------------
+#
+# options check
+#
+$aflag = $vflag = $wflag = $sflag = ''; # $sflag is set internally
+while ($ARGV[0] =~ /^-/) {
+ $opt = shift;
+ if ($opt =~ /[^-avwdt]/) {
+ print STDERR "$usage\n";
+ exit 1;
+ }
+ if ($opt =~ /a/) { $aflag = 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 = '.';
+}
+unless (-r "$dbpath/GTAGS" && -r "$dbpath/GRTAGS") {
+ &error("GTAGS and GRTAGS not found. please type 'gtags[RET]'\n");
+}
+$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);
+#-------------------------------------------------------------------------
+# MAKE FILES
+#-------------------------------------------------------------------------
+# HTML/help.html ... help file (2)
+# HTML/funcs.html ... function index (3)
+# HTML/$FUNCS/* ... function index (3)
+# HTML/$REFS/* ... referencies (4)
+# HTML/$DEFS/* ... definitions (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)
+#-------------------------------------------------------------------------
+print STDERR "[", &date, "] ", "Htags started\n" if ($vflag);
+#
+# (1) 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, $REFS, $DEFS, $FILES, $FUNCS) {
+ mkdir("$html/$d", 0775) || &error("cannot make HTML directory\n") if (! -d "$html/$d");
+}
+#
+# (2) make help file
+#
+print STDERR "[", &date, "] ", "(2) making help.html ...\n" if ($vflag);
+&makehelp("$html/help.html");
+#
+# (3) make function index (funcs.html and $FUNCS/*)
+# PRODUCE @funcs
+#
+print STDERR "[", &date, "] ", "(3) making function index ...\n" if ($vflag);
+$func_total = &makefuncindex("$html/funcs.html");
+print STDERR "Total $func_total functions.\n" if ($vflag);
+#
+# (4) make function entries ($DEFS/* and $REFS/*)
+# MAKING TAG CACHE
+#
+print STDERR "[", &date, "] ", "(4) 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($func_total);
+print STDERR "Total $func_total functions.\n" if ($vflag);
+#
+# (5) make file index (files.html and $FILES/*)
+# PRODUCE @files
+#
+print STDERR "[", &date, "] ", "(5) making file index ...\n" if ($vflag);
+$file_total = &makefileindex("$html/files.html");
+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
+#
+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
+#-------------------------------------------------------------------------
+#
+# 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);
+}
+#
+# makefuncindex: make function index (including alphabetic index)
+#
+# i) file function index file
+# go) @funcs
+#
+sub makefuncindex {
+ local($file) = @_;
+ 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 $dbpath/GTAGS | awk '{print \$1}' | sort | uniq |") || &error("btreeop $dbpath/GTAGS failed.\n");
+ local($alpha) = '';
+ @funcs = (); # [A][B][C]...
+ while (<TAGS>) {
+ $count++;
+ chop;
+ local($tag) = $_;
+ print STDERR " [$count] 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);
+ }
+ open(LIST, "btreeop -K $tag $dbpath/GTAGS |") || &error("btreeop -K $tag $dbpath/GTAGS failed.\n");;
+ local($line1, $line2);
+ if ($line1 = <LIST>) {
+ $line2 = <LIST>;
+ }
+ close(LIST);
+ if ($line2) {
+ print "<LI><A HREF=", ($aflag) ? "../" : "", "D/$tag.html>$tag</A>\n";
+ } else {
+ local($nouse, $lno, $filename) = split(/[ \t]+/, $line1);
+ $nouse = ''; # to make perl quiet
+ $filename =~ s/^\.\///;
+ $filename =~ s/\//$ESCSEP/g;
+ print "<LI><A HREF=", ($aflag) ? "../" : "", "$SRCS/$filename.html#$lno>$tag</A>\n";
+ }
+ close(LIST);
+ }
+ 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;
+}
+#
+# makedupindex: make duplicate entries index ($DEFS/* and $REFS/*)
+#
+# i) $total functions total
+# r) $count
+#
+sub makedupindex {
+ local($total) = @_;
+ local($count) = 0;
+
+ open(TAGS, "btreeop $dbpath/GTAGS | awk '{print \$1}' | sort | uniq |") || &error("btreeop $dbpath/GTAGS failed.\n");
+ while (<TAGS>) {
+ $count++;
+ chop;
+ local($tag) = $_;
+ print STDERR " [$count/$total] adding $tag\n" if ($vflag);
+ foreach $db ('GTAGS', 'GRTAGS') {
+ open(LIST, "btreeop -K $tag $dbpath/$db | sort +0b -1 +2b -3 +1n -2|") || &error("btreeop -K $tag $dbpath/$db failed.\n");;
+ local($line1, $line2);
+ if ($line1 = <LIST>) {
+ $line2 = <LIST>;
+ }
+ &cache'put($db, $tag, ($line2) ? '' : $line1) if ($line1);
+ if ($line2) { # two or more entries exist
+ local($type) = ($db eq 'GTAGS') ? $'DEFS : $'REFS;
+ open(FILE, ">$html/$type/$tag.html") || &error("cannot make file <$html/$type/$tag.html>.\n");
+ print FILE "<HTML>\n<HEAD><TITLE>$tag</TITLE></HEAD>\n<BODY>\n";
+ print FILE "<PRE>\n";
+ for (;;) {
+ if ($line1) {
+ $_ = $line1;
+ $line1 = '';
+ } elsif ($line2) {
+ $_ = $line2;
+ $line2 = '';
+ } elsif (!($_ = <LIST>)) {
+ last;
+ }
+ s/\.\///;
+ s/&/&amp;/g;
+ s/</&lt;/g;
+ s/>/&gt;/g;
+ local($nouse, $lno, $filename) = split;
+ $nouse = ''; # to make perl quiet
+ $filename =~ s/\//$ESCSEP/g;
+ s/^$tag/<A HREF=..\/$SRCS\/$filename.html#$lno>$tag<\/A>/;
+ print FILE;
+ }
+ print FILE "</PRE>\n</BODY>\n</HTML>\n";
+ close(FILE);
+ }
+ close(LIST);
+ }
+ }
+ close(TAGS);
+ $count;
+}
+#
+# makefileindex: make file index
+#
+# i) file name
+# go) @files
+#
+sub makefileindex {
+ local($file) = @_;
+ 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 . -name '*.[chysS]' -print | sort |") || &error("cannot exec find.\n");
+ local($lastdir) = '';
+ @files = ();
+ while (<FIND>) {
+ $count++;
+ chop;
+ s/^\.\///;
+ next if /(y\.tab\.c|y\.tab\.h)$/;
+ next if (!$'sflag && /\.[sS]$/);
+ 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;
+ }
+ local($path) = $filename;
+ $path =~ s/\//$ESCSEP/g;
+ if ($dir eq '') {
+ push(@files, "<LI><A HREF=", ($dir) ? "../" : "", "$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);
+
+ $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";
+ $index .= "<H2>MAINS</H2>\n";
+ $index .= "<PRE>\n";
+ open(PIPE, "btreeop -K main $dbpath/GTAGS | sort +0b -1 +2b -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
+#
+sub makehtml {
+ local($total) = @_;
+ local($count) = 0;
+
+ open(FIND, "find . -name '*.[chysS]' -print|") || &error("cannot exec find.\n");
+ while (<FIND>) {
+ $count++;
+ chop;
+ s/^\.\///;
+ next if /y\.tab\.c|y\.tab\.h/;
+ next if (!$'sflag && /\.[sS]$/);
+ 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
+#
+sub src2html {
+ local($file, $html) = @_;
+ local($ncol) = $'ncol;
+
+ 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, $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>) {
+ s/\r$//;
+ s/&/&amp;/g; # '<', '>' and '&' are used for HTML tag
+ s/</&lt;/g;
+ s/>/&gt;/g;
+ &protect_line(); # protect quoted char, strings and comments
+ # painting source code
+ s/({|})/$'brace_begin$1$'brace_end/g;
+ $sharp = s/^(#\w+)// ? $1 : ''; # protect macro
+ 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($first);
+
+ for ($first = 1; int($LNO) == $.; ($LNO, $TAG, $TYPE) = &anchor'next()) {
+ if ($first) {
+ $first = 0;
+ print "<A NAME=$LNO>"
+ }
+ $define_line = $LNO if ($TYPE eq 'D');
+ $db = ($TYPE eq 'D') ? 'GRTAGS' : 'GTAGS';
+ local($line) = &cache'get($db, $TAG);
+ if (defined($line)) {
+ local($href, $dir);
+ 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 {
+ $dir = ($TYPE eq 'D') ? $'REFS : $'DEFS;
+ $href = "<A HREF=../$dir/$TAG.html>$TAG</A>";
+ }
+ # set tag marks and push 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 refered.\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 ", $.;
+ print;
+ # print hyperlinks
+ if ($define_line && $file !~ /\.h$/) {
+ print ' ' x ($ncol + 1);
+ 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 (/(\\.)/) {
+ push(@quoted_char1, $1);
+ s/\\./\001/;
+ }
+ @quoted_char2 = ();
+ while (/('[^']')/) {
+ push(@quoted_char2, $1);
+ s/'[^']'/\002/;
+ }
+ @quoted_strings = ();
+ while (/("[^"]*")/) {
+ push(@quoted_strings, $1);
+ s/"[^"]*"/\003/;
+ }
+ @comments = ();
+ s/^/\032/ if ($INCOMMENT);
+ while (1) {
+ if ($INCOMMENT == 0) {
+ if (/\/\*/) { # start comment
+ s/\/\*/\032\/\*/;
+ $INCOMMENT = 1;
+ } else {
+ last;
+ }
+ } else {
+ # Thanks to Jeffrey Friedl for his code.
+ if (m!\032(/\*)?[^*]*\*+([^/*][^*]*\*+)*/!) {
+ $INCOMMENT = 0;
+ # minimum matching
+ s!\032((/\*)?[^*]*\*+([^/*][^*]*\*+)*/)!\004!;
+ push(@comments, $1);
+ } 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, "| 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
+#
+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);
+ # START for DTFLAG
+ # 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: skip <$filename $lno $tag> because this is a macro which is defined in other C source.\n" if ($'wflag);
+ next;
+ }
+ }
+ # END for DTFLAG
+ 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);
+ 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 ($linenumber != $FIRST);
+ $last = $LAST if ($linenumber != $LAST);
+ $top = 'TOP' if ($linenumber != 0);
+ $bottom = 'BOTTOM' if ($linenumber != -1);
+ if ($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/usr.bin/global/systags/Makefile b/usr.bin/global/systags/Makefile
new file mode 100644
index 0000000..49c9806
--- /dev/null
+++ b/usr.bin/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/usr.bin/global/systags/systags.sh b/usr.bin/global/systags/systags.sh
new file mode 100755
index 0000000..e6e85bf
--- /dev/null
+++ b/usr.bin/global/systags/systags.sh
@@ -0,0 +1,83 @@
+#!/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 17-Feb-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
+#
+# 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 -vwat '$title' -d $dir $dir > $dir/htags.log 2>&1";;
+*) htags -vwat "$title" -d $dir $dir> $dir/htags.log 2>&1;;
+esac
OpenPOWER on IntegriCloud