Import global v2.0 as contributed software. We will maintain it this

way, retiring the sources from usr.bin/global shortly.

Reviewed by: jdp
Discussed-with: obrien
This commit is contained in:
cwt 1997-08-16 04:13:58 +00:00
commit 9061d030a8
48 changed files with 8979 additions and 0 deletions

203
contrib/global/HISTORY Normal file
View File

@ -0,0 +1,203 @@
GLOBAL history
--------------
version 1.0 initial version [21-Apr-96]
version 1.1 only bugfix [2-May-96]
[fixed bug]
global - makes corrupted path name by conversion error.
- description of exit code in online manual is mistaken.
btreeop - cannot treat a long line over BUFSIZ. With the result
that gtags fails.
extended ctags - when using -r option, considers a reserved word
to be a function name. With the result that GRTAGS becomes
too large.
version 1.2 support of 1.34 nvi [7-Jun-96]
[changed]
extended ctags
- change to use bsearch(3) for searching reserved words.
- change to consider '__P' as a reserved word.
- unify the original patch (included in version1.0) and
the bugfix patch (included in version1.1).
[added]
extended vi
- VI tag support.
version 1.3 support of GTAGSLIBPATH [28-Jul-96]
[changed]
global - search not only in a source tree but also in library paths
specified by environment variable GTAGSLIBPATH.
extended ctags
- change print format a little when -x option
version 1.4 support of yacc source file [26-Oct-96]
[changed]
extended ctags
- support of yacc source file.
- this version of ctags is NOT COMPATIBLE with original one.
* search all part of a yacc file for C functions.
(original only 3rd part)
* no longer considers a yacc rule to be an object.
version 1.5 hypertext generator [12-Dec-96]
[fixed bug]
gtags - treat 'y.tab.c' as a C source.(we should treat only *.y)
extended vi
- free stack memory. free(3) in FreeBSD 2.1.5R seems to
show a warning message when receive stack address.
So it spoils the screen.
[added]
htags - new command (hypertext generator of C source file)
gtags - error check code added.
version 1.6 support of 1.76 nvi and reconstruction for other OS [21-Jan-97]
[changed]
htags - cease using <BLOCKQUOTE> because lynx doesn't understand it.
global,htags
- replace 'sort -u' with 'sort | uniq' for compatibility reason.
[fixed bug]
global - makes illegal path name when using GTAGSLIBPATH.
gtags - error message mistaken.
[added]
nvi-1.76.diff
- patch for nvi 1.76 to make extended vi.
gctags - this is the same with extended ctags in older version.
now GLOBAL includes BSD ctags in it. so no longer has
patch file (ctags.diff).
(I brought original ctags from FreeBSD 2.1.5R)
global - -a option added.
version 1.7 make suitable for large project (mainly FreeBSD kernel) [17-Feb-97]
[changed]
htags - htags no longer makes frame.html. Index.html offers frame
function too.
- works MUCH faster than previous version.
[fixed bug]
htags - generate path name including '&param'. (It means special
charactor in hypertertext.)
So, changed internal separator from '&' to '|'.
[added]
gtags - -s option added. If specified, gtags extract ENTRY() and
ALTENTRY() from *.[sS] files.
htags - support one level nested index. It's always valid for file
index when directories found, and valid for function index
only when -a option specified.
- -v and -t option added.
systags.sh
- script to make all tags (GTAGS,GRTAGS,HTML) for kernel source.
(it is only for FreeBSD and Linux)
version 1.8 fix some bugs, add options and make more portable [5-Apr-97]
[changed]
gctags, btreeop, Makefile
- modify for generic UNIX (Linux, Solaris)
- modify to quiet compiler.
Many thanks to
A.E. Brouwer
Oleg Checkulaev
Emile Heyns
gctags - modify to treat '\r' at the end of line.
htags - changed internal separator from '|' to ' '.
because some OS cannot treat '|' in a path.
[fixed bug]
htags - regard a part of path in #include as a reserved word.
- generate illegal links when same tags exist in a line.
- insufficient comment detection.
Thanks to Jeffrey Friedl. I took his code for complete
comment detection.
gctags - regard function name as a definition in extern statement.
- skip macro(no argment) body when -r specified.
gctags, htags
- regard 'entry' as a reserved word.
[added]
global - -c (complete) option added.
htags - -d tagdir option added.
- -w option added.
version 1.81 make global to understand 'obj' directory [14-Apr-97]
[fixed bug]
extended vi
- doesn't hand '\' in a pattern to global.
[changed]
global
- can find tag file in obj directory.
version 1.9 support of 1.79 nvi and some additional options [21-Apr-97]
[fixed bug]
htags - doesn't keep the code formatted correctly.
So, changed to convert tabs in source files into spaces.
(expand(1) needed)
Thanks to Andy Newman.
- cannot print error message correctly.
[changed]
gctags, btreeop
- modify for SunOS 4.1.3.
Thanks to Yoshiharu Ito.
[added]
btreeop - META record is available.
(It will be used in the furture.)
- -A and -D option added.
(It will be used in the future.)
global - 'format version record' is available.
(It will be used in the furture.)
htags - use temporary directory specified by TMPDIR environment
variable.
- -l option added.
Thanks to Jeff Trawick. This option is his idea.
nvi-1.79.diff
- patch for nvi 1.79 to make extended vi.
version 2.0 Support of Emacs and CGI Form [7-Jul-97]
[fixed bug]
gtags, htags
- treat files under 'RCS/' or 'SCCS/' directory.
global - allow relative path of GTAGSDBPATH and GTAGSROOT.
htags - illegal tag generated when no definition found.
[changed]
htags - changed not to print line number by default.
If you need it, -n option should be specified.
- added the command name to error message.
- avoid sort(1)'s bug.
- changed for performance.
systags - use -n, -f option for htags by default.
doesn't use -w option for htags by default.
gtags - rewritten with perl.
gtags, gctags
- move some code for assembler source from gtags to gctags.
gtags, htags, global
- restrict PATH to '/bin:/usr/bin'.
btreeop - expand tabs into spaces of output.
[deleted]
nvi-1.76.diff
[added]
gtags.el- added emacs support (emulation of 1.34 nvi)
htags - added hyperlink for include files.
- added checking if GTAGS is the latest one.
- -f option added.
With this option, you can use input form and dynamic
index. (You need to setup httpd server for it.)
- -n option added.
global - -f option added.
btreeop - -L option added.

148
contrib/global/INSTALL Normal file
View File

@ -0,0 +1,148 @@
Installation of GLOBAL 2.0
3-Jul-1997 Shigio Yamaguchi
---------------------------------------------------------------------------
Guide line (C style)
---------------------------------------------------------------------------
if (Your system == FreeBSD) {
You are lucky!
You need not to do procedure "1. Preparation for generic UNIX".
switch (version) {
case 2.0.5R:
case 2.1.0R:
case 2.1.5R:
There is no problem.
break;
case 2.1.6R:
case 2.1.7R:
I don't know. But it seems same with 2.1.5R.
break;
case 2.2.1R:
It is OK. But your native nvi is version 1.71.
Use 1.79 nvi available on the Internet.
break;
case 2.2.2R:
Your system inlucdes GLOBAL 1.9. You can overwrite it
with this 2.0 package.
But skip procedure "3. Extended vi (OPTIONAL)", because
your /usr/bin/nvi is already extended nvi for GLOBAL.
break;
default:
I don't know. But it semms to be little problem.
}
} else {
You may some error message to make GLOBAL.
But it seems not so difficult to clear it. If you make a patch for it,
please let me know. I would like to include your patch into new
version of GLOBAL.
Thank you in advance.
}
----------------------------------------------------------------------------
Install procedure
----------------------------------------------------------------------------
0. Extracting
% tar xzvf global-2.0.tar.gz
% cd global-2.0
1. Preparation for generic UNIX
If you are a FreeBSD (all version) user, nothing to do here.
Please go to "2. GLOBAL basic".
Otherwise, you must install following items before you install GLOBAL.
a) Generic makefile
This package includes generic makefile. Please do the followings.
% make -f Makefile.generic gen
% vi Makefile <- check install directories (BINDIR, MANDIR)
b) BSD db library version 1.85
If you don't have it, you can fetch it from this site.
http://mongoose.bostic.com/db/packages/db.1.85.tar.gz
c) PERL version 4 or later
If you don't have it, you can fetch it from this site.
ftp://ftp.cis.ufl.edu/pub/perl/CPAN/src/5.0/latest.tar.gz
If you install perl into other than /usr/bin, please rewrite the header
of following commnads.
gtags/gtags.pl global/global.pl htags/htags.pl
2. GLOBAL basic (NEEDED)
% make
# make install
3. Extended vi (OPTIONAL)
GLOBAL supports two version of nvi. There is a little defference between
them when a number of functions located. (please see 'README' file.)
Version 1.34 nvi is included by FreeBSD 2.0.5R, 2.1.0R and 2.1.5R.
Version 1.79 nvi is available on
ftp://ftp.cs.berkeley.edu/ucb/4bsd/nvi-1.79.tar.gz.
If you don't have nvi-1.34, use nvi-1.79.
If you use version 1.34 nvi which is a native command in FreeBSD 2.0.5R,
2.1.0R or 2.1.5R then
% cp -r /usr/src/usr.bin/vi vi <- version 1.34 of nex/nvi
% cd vi
% patch -p < ../nvi-1.34.diff
% make
# make install
else if you use version 1.79 nvi which is the latest version then
fetch from ftp://ftp.cs.berkeley.edu/ucb/4bsd/nvi-1.79.tar.gz and
% tar xzvf nvi-1.79.tar.gz
% cd nvi-1.79
% patch -p < ../nvi-1.79.diff
% cd build
% ./configure
% make
# make install
Caution: If you use FreeBSD 2.2.2R or later, your nvi is already
extended vi. Don't patch with nvi-1.79.diff.
else we have no patch for it.
4. Extended emacs (OPTIONAL)
The version of Emacs supported by GLOBAL is GNU Emacs 19.28, 19.34 or
Mule 2.3 (= Emacs 19.28). Other emacs version seems to work well,
but I don't confirm it.
You can get it from
Emacs 19.34b:
prep.ai.mit.edu/pub/gnu/emacs-19.34b.tar.gz
Mule 2.3:
ftp://ftp.cs.buffalo.edu/pub/mule/mule-2.3.tar.gz
If you are a FreeBSD user, install it from package.
If you have installed it, to use extended emacs, copy gtags.el
in this package to the emacs lisp library directory or place the file
in a directory (for example "~/lisp") and write $HOME/.emacs like this.
+-----------------------------------------------
|(setq load-path (cons "~/lisp" load-path))
Good luck!

18
contrib/global/MANIFEST Normal file
View File

@ -0,0 +1,18 @@
HISTORY Histroy of GLOBAL.
INSTALL Installation method
MANIFEST This file.
Makefile Makefile for BSD.
Makefile.inc A part of Makefile for BSD.
Makefile.generic Makefile for generic UNIX(including BSD).
README Readme (introduction and usage).
VERSION Version number.
btreeop/ Btreeop command directory.
gctags/ Gctags command directory (extended ctags).
global/ Global command directory.
gtags/ Gtags command directory.
htags/ Htags command directory.
include/ include files for non BSD system.
systags/ Script for kernel.
gtags.el Gtags mode for Emacs
nvi-1.34.diff Patch for nvi 1.34.
nvi-1.79.diff Patch for nvi 1.79.

3
contrib/global/Makefile Normal file
View File

@ -0,0 +1,3 @@
SUBDIR= gctags global gtags btreeop htags systags
.include <bsd.subdir.mk>

View File

@ -0,0 +1,43 @@
# @(#)Makefile 1-Mar-97
SUBDIR= gctags global gtags btreeop htags systags
BINDIR= /usr/bin # EDIT THIS
MANDIR= /usr/share/man # EDIT THIS
# For FreeBSD contrib
CONTRIBDIR= /tmp/global
RMFILES=INSTALL Makefile.generic nvi-1.34.diff nvi-1.79.diff \
*/Makefile.generic */err.c include
all:
@for d in $(SUBDIR); do \
set -e; (cd $$d; echo '===>' $$d; make $(MFLAGS)) \
done
install:
@for d in $(SUBDIR); do \
set -e; (cd $$d; echo '===>' $$d; make $(MFLAGS) BINDIR=$(BINDIR) MANDIR=$(MANDIR) install) \
done
gen:
@if [ ! -f Makefile.generic ]; then \
echo "Error: generic makefile not found."; exit 1; \
fi
mv Makefile Makefile.bsd; mv Makefile.generic Makefile
for d in $(SUBDIR); do \
(cd $$d; mv Makefile Makefile.bsd; mv Makefile.generic Makefile) \
done
bsd:
@if [ ! -f Makefile.bsd ]; then \
echo "Error: BSD style makefile not found."; exit 1; \
fi
mv Makefile Makefile.generic; mv Makefile.bsd Makefile
for d in $(SUBDIR); do \
(cd $$d; mv Makefile Makefile.generic; mv Makefile.bsd Makefile) \
done
bsdcontrib: clean
rm -rf $(CONTRIBDIR)
mkdir $(CONTRIBDIR) && cp -r . $(CONTRIBDIR)
cd $(CONTRIBDIR) && rm -rf $(RMFILES)
clean:
@for d in $(SUBDIR); do \
(cd $$d; echo '===>' $$d; make $(MFLAGS) clean) \
done

View File

@ -0,0 +1 @@
BINDIR?= /usr/bin

695
contrib/global/README Normal file
View File

@ -0,0 +1,695 @@
@@@@@@@=
@= @=
@= @=
@= @= @@@@@= @@@@@@= @@= @=
@= F o r a l l h a c h e r s. version 2.0
@= @@@@@@=@= @= @= @@@@@= @= @= @=
@= @= @= @= @= @= @= @@@@@= @=
@= @= @= @= @= @= @=@= @= @=
@@@@@@@@= @@@@= @@@@@= @@@@@@=@@@= @@@@= @@@@@@=
Shigio Yamaguchi 7-Jul-97
Copyright 1996, 1997 Shigio Yamaguchi All right resereved.
GLOBAL is a browsing system for C and Yacc source code.
It brings benefits to all hackers. Enjoy!
Contents
--------------------------------
0. Introduction
1. Global
1.1. Features
1.2. Preparation
1.3. Basic usage
1.4. Applied usage
2. Extended vi using global
2.1. Features
2.2. Preparation
2.3. Basic usage
2.4. Applied usage
3. Hypertext generator
3.1. Features
3.2. Preparation
3.3. Usage
3.4. To make hypertext of kernel
4. Extended emacs using global
4.1. Features
4.2. Preparation
4.3. Basic usage
4.4. Applied usage
--------------------------------
0. Introduction
GLOBAL is a browsing system for C and Yacc source files.
You can locate the specified function in C source files and move there easily.
It is useful to hack a large project containing many subdirectories,
many '#ifdef' and many main() functions like MH, X or BSD kernel.
It supports following environments.
o shell command line(see '1. Global')
o vi editor(see '2. Extended vi using global')
o web browser(see '3. Hypertext generator')
o emacs editor(see '4. Emacs using global')
GLOBAL is consist of global(1), gtags(1), btreeop(1), gctags(1), htags(1),
extended vi(1) and gtags.el.
* 'extended' means being entended for GLOBAL.
* Btreeop and gctags are used internally, so you need not
understand about them.
The extended vi is completely upper compatible with original one.
All the functions for GLOBAL are enabled only in 'gtagsmode'.
------------------------------------------------------------------------------
1. Global
1.1. Features
o Global can find the locations of a specified function quickly.
o Global can locate not only function definitions but also function references.
o Global allows duplicate entries.
o Global can treat a source tree containing subdirectories and you can
get relative path of objects from anywhere within the tree.
o Global can understand perl's regular expression.
o Global can search in not only a source tree but also library paths.
o Global can treat yacc source file.
I think these features are useful for a large project containing many
subdirectories, many '#ifdef' and many main() functions like MH.
1.2. Preparation
First of all, you must execute gtags(1) at the root of source tree.
For example, if you want to browse vi's source code, please do like this.
% cd /usr/src/usr.bin/vi
% gtags
Gtags traverse subdirectories and makes
two database at the root of source tree.
% ls G*TAGS
GRTAGS GTAGS
GTAGS - database for function definition
GRTAGS - database for function reference
If you cannot find functions that should exist, please try -e option.
% gtags -e
1.3. Basic usage
Please think of following source tree.
ROOT/ <- the root of source tree (GTAGS,GRTAGS)
|
|- DIR1/
| |
| |- fileA.c ..... +---------------+
| | |main(){ |
| | | func1();|
| | | func2();|
| | |} |
| | +---------------+
| |
| |- fileB.c ..... +---------------+
| |func1(){ ... } |
| +---------------+
|- DIR2/
|
|- fileC.c ..... +---------------+
|#ifdef X |
|func2(){ i++; }|
|#else |
|func2(){ i--; }|
|#endif |
|func3(){ |
| func1();|
|} |
+---------------+
You can get the relative path of your object from anywhere within
the source tree.
% cd ROOT
% global func1
DIR1/fileB.c <- func1() is defined in fileB.c
% cd DIR1
% global func1
fileB.c <- relative path from DIR1
% cd ../DIR2
% global func1
../DIR1/fileB.c <- relative path from DIR2
-r option locates function references.
% global -r func2
../DIR1/fileA.c <- func2() is referred from fileA.c
You can use perl's regular expression.
% cd ROOT
% global 'func[1-3]'
DIR1/fileB.c <- func1, func2 and func3 are matched
DIR2/fileC.c
-x option shows the detail. It's similar to ctags's -x option.
% global func2
DIR2/fileC.c
% global -x func2
func2 2 DIR2/fileC.c func2(){ i++; }
func2 4 DIR2/fileC.c func2(){ i--; }
-a option produces the absolute path name.
% global -a func1
/home/user/ROOT/DIR1/fileB.c
You can edit files including specified function directly like this.
% vi `global func1` <- edit fileB.c
1.4. Applied usage
You can make multiple tag files.
For example, you can execute gtags at ROOT/, version1.0/ and version2.0/.
ROOT/ <- the root of source tree (GTAGS,GRTAGS)
|
|- version1.0/ <- the root of version1.0 (GTAGS,GRTAGS)
| |
| |- file.c ..... +---------------+
| |func1(){ i++; }|
| +---------------+
|
|- version2.0/ <- the root of version2.0 (GTAGS,GRTAGS)
|
|- file.c ..... +---------------+
|func1(){ i--; }|
+---------------+
When you are walking in version1.0 directory, global locates functions
only in version1.0.
% cd ROOT/version1.0
% global -x func1
func1 1 file.c func1(){ i++; }
When you are walking in version2.0, global locates functions only in
version2.0.
% cd ROOT/version2.0
% global -x func1
func1 1 file.c func1(){ i--; }
If you are at ROOT/ or you set GTAGSROOT environment variable to ROOT,
global locates functions in both version1.0 and version2.0 directories.
% cd ROOT
% global -x func1
func1 1 version1.0/file.c func1(){ i++; }
func1 1 version2.0/file.c func1(){ i--; }
=-=-=-=
There is another usage of GTAGSROOT.
If your source files are on a read only device like CDROM, you cannot
make database on the root of source tree.
In such case, please do the following.
% mkdir /var/dbpath
% cd /cdrom/src <- the root of source tree
% gtags /var/dbpath <- make tag file in /var/dbpath
% setenv GTAGSROOT `pwd`
% setenv GTAGSDBPATH /var/dbpath
% global func
=-=-=-=
If you want to treat the references to a function that is not defined
in the source tree like a library function or system call, you can specify
library directories with the GTAGSLIBPATH environment variable.
You should execute gtags at each directory of the path.
If GTAGS is not found in a directory, global ignores it.
% pwd
/develop/src/mh <- this is the source tree
% gtags
% ls G*TAGS
GRTAGS GTAGS
% global mhl
uip/mhlsbr.c <- mhl() is found
% global strlen <- strlen() is not found
% (cd /usr/src/lib; gtags) <- library source
% (cd /usr/src/sys; gtags) <- kernel source
% setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys
% global strlen
../../../usr/src/lib/libc/string/strlen.c <- strlen() is found in library
% global access
../../../usr/src/sys/kern/vfs_syscalls.c <- access() is found in kernel
Of course, user program doesn't call kernel function directly, but
at least it is useful.
=-=-=-=
If you forget function name, you can use -c (complete) option.
% global -c kmem <- maybe k..k.. kmem..
kmem_alloc
kmem_alloc_pageable
kmem_alloc_wait
kmem_free
kmem_free_wakeup
kmem_init
kmem_malloc
kmem_suballoc <- This is what I need!
% global kmem_suballoc
../vm/vm_kern.c
You can use -c option with tcsh's complete command.
% set funcs=(`global -c`)
% complete global 'n/*/$funcs/'
% global kmem_<TAB>
kmem_alloc kmem_alloc_wait kmem_free_wakeup kmem_malloc
kmem_alloc_pageable kmem_free kmem_init kmem_suballoc
% global kmem_s<TAB>
% global kmem_suballoc
../vm/vm_kern.c
* <TAB> means tab key or Ctrl-I.
=-=-=-=
If you want to browse many files in order, do the followings.
% global -xr fork | awk '{printf "view +%s %s\n",$2,$3}' | tee /tmp/list
view +650 ../dev/aic7xxx/aic7xxx_asm.c
view +250 ibcs2/ibcs2_misc.c
view +401 linux/linux_misc.c
view +310 ../kern/init_main.c
view +318 ../kern/init_main.c
view +336 ../kern/init_main.c
view +351 ../kern/init_main.c
% sh !$ <- from now on, go to next tag with 'ZZ'.
2. Extended vi using global
2.1. Features
o Tag function of extended vi can locate not only function definitions
but also function references.
o Extended vi allows duplicate tag entries.
o Extended vi can understand perl's regular expression as a tag name
for search.
o Extended vi is completely upper compatible with original one.
Above functions are available only in 'gtags mode'.
2.2. Preparation
First, do the preparation of global. (Please see "1.2. Preparation").
Second, to use global from vi, you need to get into 'gtagsmode'.
There are some ways to do it.
(a) Start vi with -G option
% vi -G file.c
(b) Start vi and execute "set gtagsmode"
% vi file.c
~
~
~
:set gtagsmode
(c) Previously write the set command to .exrc or .nexrc file and start vi
$HOME/.exrc
+----------------------------
|set gtagsmode
You must start vi under the source tree described in "1.2. Preparation".
2.3. Basic usage
o To go to func1, you can say
:tag func1
It seemes same with original vi, but extended vi use GTAGS
instead of tags.
o To go to referenced point of func1, add prefix 'r'
:rtag func1
Extended vi use GRTAGS.
o If a number of functions located, the action of extended vi differs
up to your nvi's version.
[Extended vi based 1.34 nvi]
Vi goes into 'GTAGS SELECT MODE' like this.
+-------------------------------------------------------------
|main 347 i386/isa/ultra14f.c main()
|main 128 kern/init_main.c main(framep)
|main 104 netiso/clnp_debug.c main()
|main 164 netiso/xebec/main.c main(argc, argv)
|~
|~
|~
|~
|~
|[GTAGS SELECT MODE] 4 lines
+-------------------------------------------------------------
You can select a tag line by any vi command and press [RETURN],
and you can go to the tag's point. In ex mode, type "select"
instead of [RETURN]. When you want to go to next or previous tag,
you can return to 'GTAGS SELECT MODE' with <control-T> and reselect.
Suggested .nexrc:
set gtagsmode
set leftright
[Extended vi based 1.79 nvi]
Vi goes to the first tag.
Then you can go to next tag by ':tagnext' or back by ':tagprev'.
Suggested .nexrc:
set gtagsmode
map ^N :tagnext^M
map ^P :tagprev^M
== WHY TWO STYLE EXIST ? ==
1.34 nvi cannot treat duplicate tag entries, so I made 'GTAGS SELECT MODE'
in it. But 1.79 nvi (1.61 and later) can treat them, so I adapted GLOBAL
tags to nvi's tag structure.
o <control-]> command is available.
In gtagsmode, if you are on the first column of line, it is identical to
":rtag <current token>[RETURN]", otherwise ":tag <current token>[RETURN]".
o Other tag commands are available too.
<control-T> - Return to the most recent tag context.
":tagpop" - Pop to the specified tag in the tags stack.
":tagtop" - Pop to the top tag in the tags stack.
":display tags" - Display tags stack.
Please read online manual.
2.4. Applied usage
o In large project which include many main() function like MH,
you can start vi like this.
% vi -G -t main
You can browse all commands sequentially.
o When you want to check functions the name of which start with
"set" or "get",
% vi -G -t '^[sg]et'
Of cause, following command is available too.
:tag ^[sg]et
o If your source files are on a read only device like CDROM, please do
the followings.
% mkdir /var/dbpath <- directory for tag file
% cd /cdrom/src <- the root of source tree
% gtags /var/dbpath <- make tag files in /var/dbpath
% setenv GTAGSROOT `pwd`
% setenv GTAGSDBPATH /var/dbpath
% vi -G -t main
o If you want to treat the references to the function that is not defined
in the source tree like library functions or system calls,
do the followings.
% cd /usr/src/lib
% gtags <- probably as a root
% cd /usr/src/sys
% gtags
% setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys
If you examine vi's source,
% cd /usr/src/usr.bin/vi
% gtags
% vi -G -t main
You can start from vi and trip the whole unix world as if using
hypertext.
3. Hypertext generator
3.1. Features
o Htags makes hypertext from C source files.
o Once the hypertext generated, you need nothing other than WWW browser.
o You can move hypertext to anywhere. It is independent of the source code.
o You can use all of your browser's functions, for example, search,
history, bookmark, save, frame, windows and so on.
3.2. Preparation
At first, you must prepare much disk space. Hypertext needs so much
disk space. For example, the source code of FreeBSD kernel needs the
following disk space.
source code(/usr/src/sys) 14MB
tag database(GTAGS,GRTAGS) 9MB(!)
hypertext(HTML/*) 45MB(!!!)
Please do the followings.
(at your source directory)
% gtags <- make tag database
% htags <- make hypertext
Then you will find 'HTML' directory in the current directory.
3.3. Usage
Please start a web browser like this.
% lynx HTML/index.html
You can use any browsers, for example, Lynx, Chimera, Mosaic,
Netscape Navigator, Internet Explorer and so on. But some browsers
cannot treat framed index. Then select '[no frame version is here]'.
You will understand the usage for the looking.
You can move HTML directory to anywhere. It is independent of
the source code.
3.4. To make hypertext of kernel
If you would like to make hypertext of FreeBSD kernel source,
it is convenient to use systags script in this package.
% cd /usr/src/sys
% systags
then
% netscape HTML/index.html
You can use following functions with systags.
o input form for dynamic index.
(This reqires you to setup httpd server for CGI program.)
o one level nested index.
o browse assembler source file.
Of course, you can use above functions without systags.
Please see gtags(1), htags(1).
4. Extended emacs using global
4.1. Features
Addition to the extended vi,
o More intelligent to recongnize current token and its type.
o Tag completion is available for input tag name.
o Mouse event is supported.
4.2. Preparation
First, do the preparation of global. (Please see "1.2. Preparation").
Second, to use global from emacs, you need to load gtags.el file and
execute gtags-mode function in it. There are some ways to do it.
(a) Start emacs, load gtags.el and execute gtags-mode function.
% emacs
|
|J_:-----Mule: *scratch* (Lisp Interaction)--L16--All----
|M-x load-library[RET]
+------------------------------------------------------
|
|J_:-----Mule: *scratch* (Lisp Interaction)--L16--All----
|Load library: gtags[RET]
+------------------------------------------------------
|
|J_:-----Mule: *scratch* (Lisp Interaction)--L16--All----
|M-x gtags-mode[RET]
+------------------------------------------------------
(b) Previously write autoload function to $HOME/.emacs file,
start emacs and execute gtags-mode function.
$HOME/.emacs
+------------------------------------------------------
|(autoload 'gtags-mode "gtags" "" t)
% emacs
|
|J_:-----Mule: *scratch* (Lisp Interaction)--L16--All----
|M-x gtags-mode[RET]
+------------------------------------------------------
(c) Previously write autoload function to $HOME/.emacs file and
start emacs with -f option
$HOME/.emacs
+------------------------------------------------------
|(autoload 'gtags-mode "gtags" "" t)
% emacs -f gtags-mode
You must start emacs under the source tree described in "1.2. Preparation".
4.3. Basic usage
It is resemble to the extended vi based nvi-1.34.
o To go to func1, press 'ESC-t' and you can see a prompt in mini-buffer.
Then input tag name.
:tag func1 # ':tag ' is a prompt.
~~~~~
o To go to referenced point of func1, press 'ESC-r'.
:rtag func1 # 'rtag ' is a prompt
~~~~~
o Tag name completion is available.
:tag fu<TAB>
:tag func1 # 'nc1' is appended by emacs
o If a number of functions located, emacs goes into 'GTAGS SELECT MODE'
like this.
+-------------------------------------------------------------
|main 347 i386/isa/ultra14f.c main()
|main 128 kern/init_main.c main(framep)
|main 104 netiso/clnp_debug.c main()
|main 164 netiso/xebec/main.c main(argc, argv)
|
|
|
|
|
|J_:--%*-Mule: *scratch* (Gtags Select)--L1--All----
|[GTAGS SELECT MODE] 4 lines
+-------------------------------------------------------------
You can select a tag line by any emacs command and press [RETURN],
and you can go to the tag's point. When you want to go to next or
previous tag, you can return to 'GTAGS SELECT MODE' with <control-T>
and reselect.
o <control-]> command is available.
If current token is a definition, it is identical to
":rtag <current token>[RETURN]", otherwise ":tag <current token>[RETURN]".
(GLOBAL decides this intelligentlly, but may sometimes misunderstand.)
4.4. Applied usage
o You can use perl's regular expression.
:tag ^put_ # locate tags start with 'put_'.
o If your source files are on a read only device like CDROM, please do
the followings.
% mkdir /var/dbpath <- directory for tag file
% cd /cdrom/src <- the root of source tree
% gtags /var/dbpath <- make tag files in /var/dbpath
% setenv GTAGSROOT `pwd`
% setenv GTAGSDBPATH /var/dbpath
% mule -f gtags-mode
o If you want to treat the references to the function that is not defined
in the source tree like library functions or system calls,
do the followings.
% cd /usr/src/lib
% gtags <- probably as a root
% cd /usr/src/sys
% gtags
% setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys
% mule -f gtags-mode
o mouse command is avalable.
If you use X version emacs, try this.
(But xemacs doesn't work well. I don't know why.)
Move mouse cursor to a function name and click center button. And you
will go to function's definition or references depending on the context.
In 'GTAGS SELECT MODE', move mouse cursor to a line and click center
button.
To return to the previous position, click right button.
Thank you for your reading of my poor english.
And of course, I'm grateful to all excellent tools (vi, emacs, perl, C, db,
mozilla ...) and its authors.
----------------------------------------------------------------------------
E-Mail: <shigio@wafu.netgate.net>
WWW: <http://wafu.netgate.net/tama/unix/indexe.html>
(You can find the latest version here.)
----------------------------------------------------------------------------

1
contrib/global/VERSION Normal file
View File

@ -0,0 +1 @@
2.0

View File

@ -0,0 +1,5 @@
# @(#)Makefile 1.0 (Berkeley) 4/21/96
PROG= btreeop
.include <bsd.prog.mk>

View File

@ -0,0 +1,22 @@
# @(#)Makefile 29-Dec-96
PROG = btreeop
CC = gcc
#WARN = -Wall -Wparentheses -Wstrict-prototypes -Wmissing-prototypes
LIBS = -ldb
CFLAGS = -O -I../include
OBJS = btreeop.o err.o
BINDIR = /usr/bin
MANDIR = /usr/share/man
all: $(PROG)
$(PROG): $(OBJS)
$(CC) -o $(PROG) $(OBJS) $(LIBS)
install:
cp $(PROG) $(BINDIR)
chmod 755 $(BINDIR)/$(PROG)
cp $(PROG).1 $(MANDIR)/man1
chmod 644 $(MANDIR)/man1/$(PROG).1
clean:
rm -f $(PROG) $(OBJS) GTAGS GRTAGS

View File

@ -0,0 +1,181 @@
.\"
.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Shigio Yamaguchi.
.\" 4. Neither the name of the author nor the names of any co-contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd July 4, 1997
.Dt BTREEOP 1
.Os BSD 4
.Sh NAME
.Nm btreeop
.Nd btree database maintenance tool
.Sh SYNOPSIS
.Nm btreeop
.Op Fl A
.Op Fl C
.Op Fl D Ar key
.Op Fl K Ar key
.Op Fl L
.Op Fl b
.Op Fl c Ar cashesize
.Op Fl l
.Op Fl p Ar psize
.Op Ar dbname
.Sh DESCRIPTION
.Nm Btreeop
execute simple operations for
.Xr btree 3
database.
.Nm Btreeop
can create database, write record, read record (sequential or index) and
delete record from it.
Duplicate entries are allowed.
.Sh OPTIONS
A capital letter means a command. If no command specified
then it assume sequential read operation.
.Bl -tag -width Ds
.It Fl A
append records. If database doesn't exist, btreeop creates it.
.It Fl C
create database and write records to it.
.It Fl D Ar key
delete records by the key.
.It Fl K Ar key
search records by the key.
.It Fl L
list all keys. It is identical to following command line.
btreeop | awk '{print $1}' | sort | uniq
.It Fl b
assume BIG_ENDIAN byte order. default is LITTLE_ENDIAN.
.It Fl c Ar cashesize
specify cashesize. It's identical to
.Nm info.cachesize
of BTREEINFO. (see btree(3))
.It Fl l
assume LITTLE_ENDIAN byte order. (the default)
.It Fl p Ar psize
specify page size. It's identical to
.Nm info.psize
of BTREEINFO. (see btree(3))
.It Ar dbname
database name. default is 'btree'.
.Sh DATA FORMAT
To creat (or append) database,
.Nm btreeop
read data from stdin.
The format of the data is the following.
Key Data\\n
Key Data\\n
.
.
.
.El
.Bl -enum -offset indent
.It
Key and Data are separated by blank('\\t' or ' ').
.It
Key cannot include blank.
.It
Data can include blank.
.It
Null Data not allowed.
.It
Additionally, META record is available. META record has a key that start with
a blank. You can read this record only by indexed search (with -K option).
Usage is unlimited by btreeop.
.El
.Sh EXAMPLES
Create database.
% btreeop -C
key1 data1
key2 data2
key3 data3
^D
%
Append records.
% btreeop -A
__.VERSION 2
key2 data2-2
^D
%
Sequential read.
% btreeop
key1 data1
key2 data2-2
key2 data2
key3 data3
%
Indexed read.
% btreeop -K key2
key2 data2-2
key2 data2
% btreeop -K ' __.VERSION'
__.VERSION 2
%
List kyes.
% btreeop -L
key1
key2
key3
%
Delete record.
% btreeop -D ' __.VERSION'
% btreeop -K ' __.VERSION'
%
.Sh FILES
.Bl -tag -width tags -compact
.It Pa btree
default database name.
.El
.Sh DIAGNOSTICS
.Nm Btreeop
exits with a value of 1 if an error occurred, 0 otherwise.
.Sh SEE ALSO
.Xr btree 3
.Sh AUTHOR
Shigio Yamaguchi (shigio@wafu.netgate.net)
.Sh HISTORY
The
.Nm
command appeared in FreeBSD 2.2.

View File

@ -0,0 +1,405 @@
/*
* Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Shigio Yamaguchi.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* btreeop.c 6-Jul-97
*
*/
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <ctype.h>
#include <db.h>
#include <fcntl.h>
char *dbdefault = "btree"; /* default database name */
char *dbname;
char buf[BUFSIZ+1];
char out[BUFSIZ+1];
#ifndef __P
#if defined(__STDC__)
#define __P(protos) protos
#else
#define __P(protos) ()
#endif
#endif
void die __P((char *));
static void usage __P((void));
void entab __P((char *));
void detab __P((char *, char *));
void main __P((int, char **));
void dbwrite __P((DB *));
void dbkey __P((DB *, char *));
void dbscan __P((DB *, int));
void dbdel __P((DB *, char *));
DB *db;
char *key;
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif
void
die(s)
char *s;
{
errx(1, "%s", s);
}
static void
usage()
{
fprintf(stderr, "%s\n%s\n",
"usage: btreeop [-A][-C][-D key][-K key][-L][-b][-c cachesize]",
" [-l][-p psize][dbname]");
exit(1);
}
#define TABPOS(i) ((i)%8 == 0)
/*
* entab: convert spaces into tabs
*
* io) buf string buffer
*/
void
entab(buf)
char *buf;
{
int blanks = 0;
int pos, src, dst;
char c;
pos = src = dst = 0;
while ((c = buf[src++]) != 0) {
if (c == ' ') {
if (!TABPOS(++pos)) {
blanks++; /* count blanks */
continue;
}
buf[dst++] = '\t';
} else if (c == '\t') {
while (!TABPOS(++pos))
;
buf[dst++] = '\t';
} else {
++pos;
while (blanks--)
buf[dst++] = ' ';
buf[dst++] = c;
}
blanks = 0;
}
buf[dst] = 0;
}
/*
* detab: convert tabs into spaces
*
* i) buf string including tabs
* o) out output
*/
void
detab(buf, out)
char *buf;
char *out;
{
int src, dst;
char c;
src = dst = 0;
while ((c = buf[src++]) != 0) {
if (c == '\t') {
do {
out[dst++] = ' ';
} while (!TABPOS(dst));
} else {
out[dst++] = c;
}
}
out[dst] = 0;
}
#include <errno.h>
void
main(argc, argv)
int argc;
char *argv[];
{
char command = 'R';
char *key = NULL;
DB *db;
BTREEINFO info;
int c;
int flags = 0;
extern char *optarg;
extern int optind;
info.flags = R_DUP; /* allow duplicate entries */
info.cachesize = 500000;
info.maxkeypage = 0;
info.minkeypage = 0;
info.psize = 0;
info.compare = NULL;
info.prefix = NULL;
info.lorder = LITTLE_ENDIAN;
while ((c = getopt(argc, argv, "ACD:K:Lbc:lp:")) != -1) {
switch (c) {
case 'K':
case 'D':
key = optarg;
case 'A':
case 'C':
case 'L':
if (command != 'R')
usage();
command = c;
break;
case 'b':
info.lorder = BIG_ENDIAN;
break;
case 'c':
info.cachesize = atoi(optarg);
break;
case 'l':
info.lorder = LITTLE_ENDIAN;
break;
case 'p':
info.psize = atoi(optarg);
break;
default:
usage();
}
}
dbname = (optind < argc) ? argv[optind] : dbdefault;
switch (command) {
case 'A':
case 'D':
flags = O_RDWR|O_CREAT;
break;
case 'C':
flags = O_RDWR|O_CREAT|O_TRUNC;
break;
case 'K':
case 'L':
case 'R':
flags = O_RDONLY;
break;
}
db = dbopen(dbname, flags, 0644, DB_BTREE, &info);
if (db == NULL) {
die("dbopen failed.");
}
switch (command) {
case 'A': /* Append records */
case 'C': /* Create database */
dbwrite(db);
break;
case 'D': /* Delete records */
dbdel(db, key);
break;
case 'K': /* Keyed (indexed) read */
dbkey(db, key);
break;
case 'R': /* sequencial Read */
case 'L': /* key's List */
dbscan(db, (command == 'L') ? 1 : 0);
break;
}
if (db->close(db)) {
die("db->close failed.");
}
exit(0);
}
/*
* dbwrite: write to database
*
* i) db
*/
void
dbwrite(db)
DB *db;
{
DBT key, dat;
int status;
#define IDENTLEN 80
char keybuf[IDENTLEN+1];
char *c;
/*
* Input file format:
* +------------------
* |Key Data\n
* |Key Data\n
* .
* .
* - Key and Data are separated by blank('\t' or ' ').
* - Key cannot include blank.
* - Data can include blank.
* - Null Data not allowed.
*
* META record:
* You can write meta record by making key start with a ' '.
* You can read this record only by indexed read ('-K' option).
* +------------------
* | __.VERSION 2
*/
while (fgets(buf, BUFSIZ, stdin)) {
if (buf[strlen(buf)-1] == '\n') /* chop(buf) */
buf[strlen(buf)-1] = 0;
else
while (fgetc(stdin) != '\n')
;
c = buf;
if (*c == ' ') { /* META record */
if (*++c == ' ')
die("illegal format.");
}
for (; *c && !isspace(*c); c++) /* skip key part */
;
if (*c == 0)
die("data part not found.");
if (c - buf > IDENTLEN)
die("key too long.");
strncpy(keybuf, buf, c - buf); /* make key string */
keybuf[c - buf] = 0;
for (; *c && isspace(*c); c++) /* skip blanks */
;
if (*c == 0)
die("data part is null.");
entab(buf);
key.data = keybuf;
key.size = strlen(keybuf)+1;
dat.data = buf;
dat.size = strlen(buf)+1;
status = (db->put)(db, &key, &dat, 0);
switch (status) {
case RET_SUCCESS:
break;
case RET_ERROR:
case RET_SPECIAL:
die("db->put: failed.");
}
}
}
/*
* dbkey: Keyed search
*
* i) db
* i) skey
*/
void
dbkey(db, skey)
DB *db;
char *skey;
{
DBT dat, key;
int status;
key.data = skey;
key.size = strlen(skey)+1;
for (status = (*db->seq)(db, &key, &dat, R_CURSOR);
status == RET_SUCCESS && !strcmp(key.data, skey);
status = (*db->seq)(db, &key, &dat, R_NEXT)) {
detab((char *)dat.data, out);
(void)fprintf(stdout, "%s\n", out);
}
if (status == RET_ERROR)
die("db->seq failed.");
}
/*
* dbscan: Scan all records
*
* i) db
* i) keylist
*/
void
dbscan(db, keylist)
DB *db;
int keylist;
{
DBT dat, key;
int status;
char prev[IDENTLEN+1];
prev[0] = 0;
for (status = (*db->seq)(db, &key, &dat, R_FIRST);
status == RET_SUCCESS;
status = (*db->seq)(db, &key, &dat, R_NEXT)) {
/* skip META record */
if (*(char *)key.data == ' ')
continue;
if (keylist) {
if (!strcmp(prev, (char *)key.data))
continue;
strcpy(prev, (char *)key.data);
(void)fprintf(stdout, "%s\n", (char *)key.data);
continue;
}
detab((char *)dat.data, out);
(void)fprintf(stdout, "%s\n", out);
}
if (status == RET_ERROR)
die("db->seq failed.");
}
/*
* dbdel: Delete records
*
* i) db
* i) skey key
*/
void
dbdel(db, skey)
DB *db;
char *skey;
{
DBT key;
int status;
key.data = skey;
key.size = strlen(skey)+1;
status = (*db->del)(db, &key, 0);
if (status == RET_ERROR)
die("db->del failed.");
}

View File

@ -0,0 +1,217 @@
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
/* extern char *__progname; Program name, from crt0. */
char *progname = "btreeop";
static FILE *err_file; /* file to use for error output */
static void (*err_exit)(int);
void
err_set_file(void *fp)
{
if (fp)
err_file = fp;
else
err_file = stderr;
}
void
err_set_exit(void (*ef)(int))
{
err_exit = ef;
}
void
#ifdef __STDC__
err(int eval, const char *fmt, ...)
#else
err(eval, fmt, va_alist)
int eval;
const char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
verr(eval, fmt, ap);
va_end(ap);
}
void
verr(eval, fmt, ap)
int eval;
const char *fmt;
va_list ap;
{
int sverrno;
sverrno = errno;
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", progname);
if (fmt != NULL) {
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, ": ");
}
(void)fprintf(err_file, "%s\n", strerror(sverrno));
if(err_exit)
err_exit(eval);
exit(eval);
}
void
#if __STDC__
errx(int eval, const char *fmt, ...)
#else
errx(eval, fmt, va_alist)
int eval;
const char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
verrx(eval, fmt, ap);
va_end(ap);
}
void
verrx(eval, fmt, ap)
int eval;
const char *fmt;
va_list ap;
{
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", progname);
if (fmt != NULL)
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, "\n");
if (err_exit)
err_exit(eval);
exit(eval);
}
void
#if __STDC__
warn(const char *fmt, ...)
#else
warn(fmt, va_alist)
const char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vwarn(fmt, ap);
va_end(ap);
}
void
vwarn(fmt, ap)
const char *fmt;
va_list ap;
{
int sverrno;
sverrno = errno;
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", progname);
if (fmt != NULL) {
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, ": ");
}
(void)fprintf(err_file, "%s\n", strerror(sverrno));
}
void
#ifdef __STDC__
warnx(const char *fmt, ...)
#else
warnx(fmt, va_alist)
const char *fmt;
va_dcl
#endif
{
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vwarnx(fmt, ap);
va_end(ap);
}
void
vwarnx(fmt, ap)
const char *fmt;
va_list ap;
{
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", progname);
if (fmt != NULL)
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, "\n");
}

840
contrib/global/gctags/C.c Normal file
View File

@ -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);
}

View File

@ -0,0 +1,7 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= gctags
CFLAGS+=-I${.CURDIR} -DGTAGS -DBUGFIX -DMODIFY -DYACC
SRCS= C.c ctags.c fortran.c lisp.c print.c tree.c yacc.c assembler.c
.include <bsd.prog.mk>

View File

@ -0,0 +1,23 @@
# @(#)Makefile 29-Dec-96
PROG = gctags
DEFS = -DGTAGS -DBUGFIX -DMODIFY -DYACC
CC = gcc
#WARN = -Wall -Wparentheses -Wstrict-prototypes -Wmissing-prototypes
CFLAGS = -O $(DEFS) -I../include
LIBS = -ldb
OBJS = C.o ctags.o fortran.o lisp.o print.o tree.o yacc.o assembler.o err.o
BINDIR = /usr/bin
MANDIR = /usr/share/man
all: $(PROG)
$(PROG): $(OBJS)
$(CC) -o $(PROG) $(OBJS) $(LIBS)
install:
cp $(PROG) $(BINDIR)
chmod 755 $(BINDIR)/$(PROG)
cp $(PROG).1 $(MANDIR)/man1
chmod 644 $(MANDIR)/man1/$(PROG).1
clean:
rm -f $(PROG) $(OBJS) GTAGS GRTAGS

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)assembler.c 8.3 (Berkeley) 6/6/97";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <string.h>
#include "ctags.h"
#ifdef GTAGS
void
asm_entries()
{
char *lbp;
char tok[MAXTOKEN];
char *sp;
for (;;) {
lineftell = ftell(inf);
if (!fgets(lbuf, sizeof(lbuf), inf))
return;
++lineno;
/* extract only ENTRY() and ALTENTRY(). */
if (lbuf[0] != 'E' && lbuf[0] != 'A')
continue;
lbp = lbuf;
if (!strncmp(lbp, "ENTRY(", 6)) {
lbp += 6;
} else if (!strncmp(lbp, "ALTENTRY(", 9)) {
lbp += 9;
} else
continue;
sp = tok;
while (*lbp && intoken(*lbp))
*sp++ = *lbp++;
if (*lbp != ')')
continue;
*sp = EOS;
getline();
pfnote(tok, lineno);
}
/*NOTREACHED*/
}
#endif

View File

@ -0,0 +1,410 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1987, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] =
"$Id: ctags.c,v 1.3 1997/07/10 06:43:40 charnier Exp $";
#endif /* LIBC_SCCS and not lint */
#include <err.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ctags.h"
/*
* ctags: create a tags file
*/
NODE *head; /* head of the sorted binary tree */
/* boolean "func" (see init()) */
bool _wht[256], _etk[256], _itk[256], _btk[256], _gd[256];
FILE *inf; /* ioptr for current input file */
FILE *outf; /* ioptr for tags file */
long lineftell; /* ftell after getc( inf ) == '\n' */
int lineno; /* line number of current line */
int dflag; /* -d: non-macro defines */
#ifdef GTAGS
int eflag; /* -e: '{' at 0 column force function end */
#endif
int tflag; /* -t: create tags for typedefs */
int vflag; /* -v: vgrind style index output */
int wflag; /* -w: suppress warnings */
int xflag; /* -x: cxref style output */
#ifdef GTAGS
int Dflag; /* -D: allow duplicate entrys */
int rflag; /* -r: function reference */
#endif
#ifdef YACC
int yaccfile; /* yacc file */
#endif
char *curfile; /* current input file name */
char searchar = '/'; /* use /.../ searches by default */
char lbuf[LINE_MAX];
void init __P((void));
void find_entries __P((char *));
void main __P((int, char **));
static void usage __P((void));
void
main(argc, argv)
int argc;
char **argv;
{
static char *outfile = "tags"; /* output file */
int aflag; /* -a: append to tags */
int uflag; /* -u: update tags */
int exit_val; /* exit value */
int step; /* step through args */
int ch; /* getopts char */
char cmd[100]; /* too ugly to explain */
extern char *optarg;
extern int optind;
aflag = uflag = NO;
#ifdef GTAGS
while ((ch = getopt(argc, argv, "BDFadef:rtuwvxy")) != -1)
#else
while ((ch = getopt(argc, argv, "BFadf:tuwvx")) != -1)
#endif
switch(ch) {
case 'B':
searchar = '?';
break;
#ifdef GTAGS
case 'D':
Dflag++;
break;
#endif
case 'F':
searchar = '/';
break;
case 'a':
aflag++;
break;
case 'd':
dflag++;
break;
#ifdef GTAGS
case 'e':
eflag++;
break;
#endif
case 'f':
outfile = optarg;
break;
#ifdef GTAGS
case 'r':
rflag++;
break;
#endif
case 't':
tflag++;
break;
case 'u':
uflag++;
break;
case 'w':
wflag++;
break;
case 'v':
vflag++;
case 'x':
xflag++;
break;
case '?':
default:
usage();
}
argv += optind;
argc -= optind;
if (!argc)
usage();
#ifdef GTAGS
if (rflag)
gtagopen();
#endif
init();
for (exit_val = step = 0; step < argc; ++step)
if (!(inf = fopen(argv[step], "r"))) {
warnx("%s cannot open", argv[step]);
exit_val = 1;
}
else {
curfile = argv[step];
find_entries(argv[step]);
(void)fclose(inf);
}
if (head)
if (xflag)
put_entries(head);
else {
if (uflag) {
for (step = 0; step < argc; step++) {
(void)sprintf(cmd,
"mv %s OTAGS; fgrep -v '\t%s\t' OTAGS >%s; rm OTAGS",
outfile, argv[step],
outfile);
system(cmd);
}
++aflag;
}
if (!(outf = fopen(outfile, aflag ? "a" : "w"))) {
warnx("%s cannot open", outfile);
exit(exit_val);
}
put_entries(head);
(void)fclose(outf);
if (uflag) {
(void)sprintf(cmd, "sort -o %s %s",
outfile, outfile);
system(cmd);
}
}
#ifdef GTAGS
if (rflag)
gtagclose();
#endif
exit(exit_val);
}
static void
usage()
{
(void)fprintf(stderr,
#ifdef GTAGS
"usage: gctags [-BDFadrtuwvx] [-f tagsfile] file ...\n");
#else
"usage: gctags [-BFadtuwvx] [-f tagsfile] file ...\n");
#endif
exit(1);
}
/*
* init --
* this routine sets up the boolean psuedo-functions which work by
* setting boolean flags dependent upon the corresponding character.
* Every char which is NOT in that string is false with respect to
* the pseudo-function. Therefore, all of the array "_wht" is NO
* by default and then the elements subscripted by the chars in
* CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in
* the string CWHITE, else NO.
*/
void
init()
{
int i;
unsigned char *sp;
for (i = 0; i < 256; i++) {
_wht[i] = _etk[i] = _itk[i] = _btk[i] = NO;
_gd[i] = YES;
}
#define CWHITE " \f\t\n"
for (sp = (unsigned char *)CWHITE; *sp; sp++) /* white space chars */
_wht[*sp] = YES;
#define CTOKEN " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?"
for (sp = (unsigned char *)CTOKEN; *sp; sp++) /* token ending chars */
_etk[*sp] = YES;
#define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789"
for (sp = (unsigned char *)CINTOK; *sp; sp++) /* valid in-token chars */
_itk[*sp] = YES;
#define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
for (sp = (unsigned char *)CBEGIN; *sp; sp++) /* token starting chars */
_btk[*sp] = YES;
#define CNOTGD ",;"
for (sp = (unsigned char *)CNOTGD; *sp; sp++) /* invalid after-function chars */
_gd[*sp] = NO;
}
/*
* find_entries --
* this routine opens the specified file and calls the function
* which searches the file.
*/
void
find_entries(file)
char *file;
{
char *cp;
lineno = 0; /* should be 1 ?? KB */
if ((cp = strrchr(file, '.')) != NULL) {
if (cp[1] == 'l' && !cp[2]) {
int c;
#ifdef GTAGS
if (rflag)
fprintf(stderr, "-r option is ignored in lisp file (Warning only)\n");
#endif
for (;;) {
if (GETC(==, EOF))
return;
if (!iswhite(c)) {
rewind(inf);
break;
}
}
#define LISPCHR ";(["
/* lisp */ if (strchr(LISPCHR, c)) {
l_entries();
return;
}
/* lex */ else {
/*
* we search all 3 parts of a lex file
* for C references. This may be wrong.
*/
toss_yysec();
(void)strcpy(lbuf, "%%$");
pfnote("yylex", lineno);
rewind(inf);
}
}
/* yacc */ else if (cp[1] == 'y' && !cp[2]) {
#ifdef YACC
/*
* we search all part of a yacc file for C references.
* but ignore yacc rule tags.
*/
yaccfile = YES;
c_entries();
return;
#endif
/*
* we search only the 3rd part of a yacc file
* for C references. This may be wrong.
*/
toss_yysec();
(void)strcpy(lbuf, "%%$");
pfnote("yyparse", lineno);
y_entries();
}
#ifdef GTAGS
/* assembler */ else if ((cp[1] == 's' || cp[1] == 'S') && !cp[2]) {
asm_entries();
return;
}
#endif
/* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) {
#ifdef GTAGS
if (rflag)
fprintf(stderr, "-r option is ignored in fortran file (Warning only)\n");
#endif
if (PF_funcs())
return;
rewind(inf);
}
}
#ifdef YACC
yaccfile = NO;
#endif
/* C */ c_entries();
}
#ifdef GTAGS
#include <db.h>
DB *db;
void
gtagopen()
{
BTREEINFO info;
char *env;
char dbname[200];
strcpy(dbname, ".");
if ((env = getenv("GTAGDBPATH"))) {
strcpy(dbname, env);
}
strcat(dbname, "/GTAGS");
info.flags = 0;
info.cachesize = 500000;
info.maxkeypage = 0;
info.minkeypage = 0;
info.psize = 0;
info.compare = 0;
info.prefix = 0;
info.lorder = 0;
#define O_RDONLY 0x0000 /* open for reading only */
db = dbopen(dbname, O_RDONLY, 0, DB_BTREE, &info);
if (db == 0)
errx(1, "GTAGS file needed");
}
int
isdefined(skey)
char *skey;
{
DBT dat, key;
int status;
key.data = skey;
key.size = strlen(skey)+1;
status = (*db->get)(db, &key, &dat, 0);
switch (status) {
case RET_SUCCESS:
return(1); /* exist */
case RET_ERROR:
errx(1, "db->get failed");
case RET_SPECIAL: /* not exist */
break;
}
return 0;
}
void
gtagclose()
{
if (db->close(db))
errx(1, "GTAGS cannot close.(dbclose)");
}
#endif

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ctags.h 8.3 (Berkeley) 4/2/94
*/
#define bool char
#define YES 1
#define NO 0
#define EOS '\0'
#define ENDLINE 50 /* max length of pattern */
#define MAXTOKEN 250 /* max size of single token */
#ifndef LINE_MAX
#define LINE_MAX 2048
#endif
#define SETLINE {++lineno;lineftell = ftell(inf);}
#define GETC(op,exp) ((c = getc(inf)) op (int)exp)
#define iswhite(arg) (_wht[(unsigned)arg]) /* T if char is white */
#define begtoken(arg) (_btk[(unsigned)arg]) /* T if char can start token */
#define intoken(arg) (_itk[(unsigned)arg]) /* T if char can be in token */
#define endtoken(arg) (_etk[(unsigned)arg]) /* T if char ends tokens */
#define isgood(arg) (_gd[(unsigned)arg]) /* T if char can be after ')' */
typedef struct nd_st { /* sorting structure */
struct nd_st *left,
*right; /* left and right sons */
char *entry, /* function or type name */
*file, /* file name */
*pat; /* search pattern */
int lno; /* for -x option */
bool been_warned; /* set if noticed dup */
} NODE;
extern char *curfile; /* current input file name */
extern NODE *head; /* head of the sorted binary tree */
extern FILE *inf; /* ioptr for current input file */
extern FILE *outf; /* ioptr for current output file */
extern long lineftell; /* ftell after getc( inf ) == '\n' */
extern int lineno; /* line number of current line */
#ifdef GTAGS
extern int eflag; /* -e: '{' at 0 column force function end */
extern int Dflag; /* -D: allow duplicate entrys */
extern int rflag; /* -r: function reference */
#endif /* GTAGS */
extern int dflag; /* -d: non-macro defines */
extern int tflag; /* -t: create tags for typedefs */
extern int vflag; /* -v: vgrind style index output */
extern int wflag; /* -w: suppress warnings */
extern int xflag; /* -x: cxref style output */
extern bool _wht[], _etk[], _itk[], _btk[], _gd[];
extern char lbuf[LINE_MAX];
extern char *lbp;
extern char searchar; /* ex search character */
#ifndef __P
#ifdef __STDC__
#define __P(protos) protos
#else
#define __P(protos) ()
#endif
#endif
int cicmp __P((char *));
void getline __P((void));
void pfnote __P((char *, int));
int skip_key __P((int));
void put_entries __P((NODE *));
void toss_yysec __P((void));
void l_entries __P((void));
void y_entries __P((void));
int PF_funcs __P((void));
void c_entries __P((void));
void skip_comment __P((void));
#ifdef GTAGS
void asm_entries __P((void));
void gtagopen __P((void));
int isdefined __P((char *));
void gtagclose __P((void));
#endif

217
contrib/global/gctags/err.c Normal file
View File

@ -0,0 +1,217 @@
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
/* extern char *__progname; Program name, from crt0. */
char *progname = "gctags";
static FILE *err_file; /* file to use for error output */
static void (*err_exit)(int);
void
err_set_file(void *fp)
{
if (fp)
err_file = fp;
else
err_file = stderr;
}
void
err_set_exit(void (*ef)(int))
{
err_exit = ef;
}
void
#ifdef __STDC__
err(int eval, const char *fmt, ...)
#else
err(eval, fmt, va_alist)
int eval;
const char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
verr(eval, fmt, ap);
va_end(ap);
}
void
verr(eval, fmt, ap)
int eval;
const char *fmt;
va_list ap;
{
int sverrno;
sverrno = errno;
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", progname);
if (fmt != NULL) {
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, ": ");
}
(void)fprintf(err_file, "%s\n", strerror(sverrno));
if(err_exit)
err_exit(eval);
exit(eval);
}
void
#if __STDC__
errx(int eval, const char *fmt, ...)
#else
errx(eval, fmt, va_alist)
int eval;
const char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
verrx(eval, fmt, ap);
va_end(ap);
}
void
verrx(eval, fmt, ap)
int eval;
const char *fmt;
va_list ap;
{
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", progname);
if (fmt != NULL)
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, "\n");
if (err_exit)
err_exit(eval);
exit(eval);
}
void
#if __STDC__
warn(const char *fmt, ...)
#else
warn(fmt, va_alist)
const char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vwarn(fmt, ap);
va_end(ap);
}
void
vwarn(fmt, ap)
const char *fmt;
va_list ap;
{
int sverrno;
sverrno = errno;
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", progname);
if (fmt != NULL) {
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, ": ");
}
(void)fprintf(err_file, "%s\n", strerror(sverrno));
}
void
#ifdef __STDC__
warnx(const char *fmt, ...)
#else
warnx(fmt, va_alist)
const char *fmt;
va_dcl
#endif
{
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vwarnx(fmt, ap);
va_end(ap);
}
void
vwarnx(fmt, ap)
const char *fmt;
va_list ap;
{
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", progname);
if (fmt != NULL)
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, "\n");
}

View File

@ -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;
}
}

View File

@ -0,0 +1,237 @@
.\" Copyright (c) 1987, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)gctags.1 8.1 (Berkeley) 6/6/93
.\"
.Dd April 21, 1997
.Dt GCTAGS 1
.Os BSD 4
.Sh NAME
.Nm gctags
.Nd create a tags file (special command for GLOBAL)
.Sh SYNOPSIS
.Nm gctags
.Op Fl BDFadertuwvx
.Op Fl f Ar tagsfile
.Ar name ...
.Sh DESCRIPTION
.Nm Gctags
makes a tags file for
.Xr ex 1
from the specified C,
Pascal, Fortran,
.Tn YACC ,
lex, lisp and assembler sources.
A tags file gives the locations of specified objects in a group of files.
Each line of the tags file contains the object name, the file in which it
is defined, and a search pattern for the object definition, separated by
white-space.
Using the
.Ar tags
file,
.Xr ex 1
can quickly locate these object definitions.
Depending upon the options provided to
.Nm gctags ,
objects will consist of subroutines, typedefs, defines, structs,
enums and unions.
.Bl -tag -width Ds
.It Fl B
use backward searching patterns
.Pq Li ?...? .
.It Fl D
allow duplicate object names.
.It Fl F
use forward searching patterns
.Pq Li /.../
(the default).
.It Fl a
append to
.Ar tags
file.
.It Fl d
create tags for
.Li #defines
that don't take arguments;
.Li #defines
that take arguments are tagged automatically.
.It Fl e
force a function to end when reach a '}' at the first column. (C source only)
.It Fl f
place the tag descriptions in a file called
.Ar tagsfile .
The default behavior is to place them in a file called
.Ar tags .
.It Fl r
locate function references instead of function definitions. GTAGS file is
needed at the current directory. (C source only)
.It Fl t
create tags for typedefs, structs, unions, and enums.
.It Fl u
update the specified files in the
.Ar tags
file, that is, all
references to them are deleted, and the new values are appended to the
file. (Beware: this option is implemented in a way which is rather
slow; it is usually faster to simply rebuild the
.Ar tags
file.)
.It Fl v
An index of the form expected by
.Xr vgrind 1
is produced on the standard output. This listing
contains the object name, file name, and page number (assuming 64
line pages). Since the output will be sorted into lexicographic order,
it may be desired to run the output through
.Xr sort 1 .
Sample use:
.Bd -literal -offset indent
gctags \-v files \&| sort \-f > index
vgrind \-x index
.Ed
.It Fl w
suppress warning diagnostics.
.It Fl x
.Nm gctags
produces a list of object
names, the line number and file name on which each is defined, as well
as the text of that line and prints this on the standard output. This
is a simple index which can be printed out as an off-line readable
function index.
.El
.Pp
Files whose names end in
.Nm \&.c
or
.Nm \&.h
are assumed to be C
source files and are searched for C style routine and macro definitions.
Files whose names end in
.Nm \&.y
are assumed to be
.Tn YACC
source files.
Files whose names end in
.Nm \&.l
are assumed to be lisp files if their
first non-blank character is `;', `(', or `[',
otherwise, they are
treated as lex files.
Files whose names end in
.Nm \&.s
or
.Nm \&.S
are assumed to be Assembler
source files. Other files are first examined to see if they
contain any Pascal or Fortran routine definitions, and, if not, are
searched for C style definitions.
.Pp
The tag
.Li main
is treated specially in C programs. The tag formed
is created by prepending
.Ar M
to the name of the file, with the
trailing
.Nm \&.c
and any leading pathname components removed. This
makes use of
.Nm gctags
practical in directories with more than one
program.
.Pp
Yacc and lex files each have a special tag.
.Ar Yyparse
is the start
of the second section of the yacc file, and
.Ar yylex
is the start of
the second section of the lex file.
.Sh FILES
.Bl -tag -width tags -compact
.It Pa tags
default output tags file
.It Pa GTAGS
tags file for GLOBAL
.El
.Sh DIAGNOSTICS
.Nm Gctags
exits with a value of 1 if an error occurred, 0 otherwise.
Duplicate objects are not considered errors.
.Sh SEE ALSO
.Xr btreeop 1 ,
.Xr ex 1 ,
.Xr global 1 ,
.Xr gtags 1 ,
.Xr htags 1 ,
.Xr vi 1 .
.Sh BUGS
.Pp
Recognition of
.Nm functions ,
.Nm subroutines
and
.Nm procedures
for
.Tn FORTRAN
and Pascal is done is a very simpleminded way. No attempt
is made to deal with block structure; if you have two Pascal procedures
in different blocks with the same name you lose.
.Nm Gctags
doesn't
understand about Pascal types.
.Pp
The method of deciding whether to look for C, Pascal or
.Tn FORTRAN
functions is a hack.
.Pp
.Nm Gctags
relies on the input being well formed, and any syntactical
errors will completely confuse it. It also finds some legal syntax
confusing; for example, since it doesn't understand
.Li #ifdef Ns 's
(incidentally, that's a feature, not a bug), any code with unbalanced
braces inside
.Li #ifdef Ns 's
will cause it to become somewhat disoriented.
In a similar fashion, multiple line changes within a definition will
cause it to enter the last line of the object, rather than the first, as
the searching pattern. The last line of multiple line
.Li typedef Ns 's
will similarly be noted.
.Pp
Assembler support is far from completeness. It extracts only ENTRY()
and ALTENTRY() from source file. Probably valid only for FreeBSD and Linux
kernel source.
.Sh HISTORY
The
.Nm
command appeared in FreeBSD 2.2.

View File

@ -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*/
}

View File

@ -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);
}

View File

@ -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 */
{
}

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)tree.c 8.3 (Berkeley) 4/2/94";
#endif /* LIBC_SCCS and not lint */
#include <err.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ctags.h"
static void add_node __P((NODE *, NODE *));
static void free_tree __P((NODE *));
/*
* pfnote --
* enter a new node in the tree
*/
void
pfnote(name, ln)
char *name;
int ln;
{
NODE *np;
char *fp;
char nbuf[MAXTOKEN];
/*NOSTRICT*/
if (!(np = (NODE *)malloc(sizeof(NODE)))) {
warnx("too many entries to sort");
put_entries(head);
free_tree(head);
/*NOSTRICT*/
if (!(head = np = (NODE *)malloc(sizeof(NODE))))
errx(1, "out of space");
}
if (!xflag && !strcmp(name, "main")) {
if (!(fp = strrchr(curfile, '/')))
fp = curfile;
else
++fp;
(void)sprintf(nbuf, "M%s", fp);
fp = strrchr(nbuf, '.');
if (fp && !fp[2])
*fp = EOS;
name = nbuf;
}
if (!(np->entry = strdup(name)))
errx(1, "out of space");
np->file = curfile;
np->lno = ln;
np->left = np->right = 0;
if (!(np->pat = strdup(lbuf)))
errx(1, "out of space");
if (!head)
head = np;
else
add_node(np, head);
}
static void
add_node(node, cur_node)
NODE *node,
*cur_node;
{
int dif;
dif = strcmp(node->entry, cur_node->entry);
#ifdef GTAGS
if (!Dflag && !dif) /* -D option allows duplicate entries. */
#else
if (!dif)
#endif
{
if (node->file == cur_node->file) {
if (!wflag)
fprintf(stderr, "Duplicate entry in file %s, line %d: %s\nSecond entry ignored\n", node->file, lineno, node->entry);
return;
}
if (!cur_node->been_warned)
if (!wflag)
fprintf(stderr, "Duplicate entry in files %s and %s: %s (Warning only)\n", node->file, cur_node->file, node->entry);
cur_node->been_warned = YES;
}
else if (dif < 0)
if (cur_node->left)
add_node(node, cur_node->left);
else
cur_node->left = node;
else if (cur_node->right)
add_node(node, cur_node->right);
else
cur_node->right = node;
}
static void
free_tree(node)
NODE *node;
{
while (node) {
if (node->right)
free_tree(node->right);
free(node);
node = node->left;
}
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -0,0 +1,13 @@
# @(#)Makefile 29-Dec-96
PROG = global
BINDIR = /usr/bin
MANDIR = /usr/share/man
all:
install:
cp $(PROG).pl $(BINDIR)/$(PROG)
chmod 755 $(BINDIR)/$(PROG)
cp $(PROG).1 $(MANDIR)/man1
chmod 644 $(MANDIR)/man1/$(PROG).1
clean:

View File

@ -0,0 +1,149 @@
.\"
.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Shigio Yamaguchi.
.\" 4. Neither the name of the author nor the names of any co-contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd April 21, 1997
.Dt GLOBAL 1
.Os BSD 4
.Sh NAME
.Nm global
.Nd print the locations of specified function.
.Sh SYNOPSIS
.Nm global
.Op Fl arx
.Ar name
.Nm global -c
.Op Ar name
.Nm global
.Op Fl a
.Fl f
.Ar file
.Sh DESCRIPTION
.Nm Global
find the locations of specified function in C and Yacc source files.
.Nm Global
can treat a source tree, that is, a directory that has subdirectories and
source files.
You can get the relative path of objects from anywhere within the tree.
.Nm Global
can locate not only function definitions but also function references and
allow duplicate entries too.
.Pp
In advance of using this command, you must execute
.Xr gtags 1
at the root directory of the source tree.
.Pp
The following options are available:
.Bl -tag -width Ds
.It Fl a
print absolute path name. By default, print relative path name.
.It Fl c Op Ar name
print candidate function names which start with specified
.Ar name .
If
.Ar name
is not specified, print all function names.
.It Fl f Ar file
print all function definitions in the
.Ar file .
This option implies -x option.
.It Fl r
print the locations of function references. By default, print function
definitions.
.It Fl x
In addition to the default output, produce the line number and
the line contents.
.It Ar name
function name. It can include perl's regular expression.
.Sh FILES
.Bl -tag -width tags -compact
.It Pa GTAGS
tags file for function definitions.
.It Pa GRTAGS
tags file for function references.
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of global.
.Pp
.Bl -tag -width indent
.It Ev GTAGSROOT
The directory which is the root of source tree.
.It Ev GTAGSDBPATH
The directory on which gtags database exist. This value is ignored
when GTAGSROOT is not defined.
.It Ev GTAGSLIBPATH
If this variable is set, its value is used as the path to search for library
functions. If specified function is not found in a source tree,
global search in these path too.
.Sh EXAMPLES
% ls -F
Makefile src/ lib/
% gtags
% global main
src/main.c
% global -x main
main 10 src/main.c main (argc, argv) {
% global -x '^[sg]et'
set_num 20 lib/util.c set_num(values)
get_num 30 lib/util.c get_num() {
% global -rx '^[sg]et'
set_num 113 src/op.c set_num(32);
set_num 225 src/opop.c if (set_num(0) > 0) {
get_num 90 src/op.c while (get_num() > 0) {
% cd lib
% global -rx '^[sg]et'
set_num 113 ../src/op.c set_num(32);
set_num 225 ../src/opop.c if (set_num(0) > 0) {
get_num 90 ../src/op.c while (get_num() > 0) {
% global strlen
% (cd /usr/src/sys; gtags)
% setenv GTAGSLIBPATH /usr/src/sys
% global strlen
../../../usr/src/sys/libkern/strlen.c
% (cd /usr/src/lib; gtags)
% setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys
% global strlen
../../../usr/src/lib/libc/string/strlen.c
.Sh DIAGNOSTICS
.Nm Global
exits with a non 0 value if an error occurred, 0 otherwise.
.Sh SEE ALSO
.Xr btreeop 1 ,
.Xr gctags 1 ,
.Xr gtags 1 ,
.Xr htags 1 .
.Sh AUTHORS
Shigio Yamaguchi (shigio@wafu.netgate.net)
.Sh HISTORY
The
.Nm
command appeared in FreeBSD 2.2.

View File

@ -0,0 +1,302 @@
#!/usr/bin/perl
#
# Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Shigio Yamaguchi.
# 4. Neither the name of the author nor the names of any co-contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# global.pl 7-Jul-97
#
sub getcwd {
local($dir);
chop($dir = `/bin/pwd`);
$dir;
}
sub regexp {
$_[0] =~ /[][.*\^\$+?|(){}\\]/; # include regular expression ?
}
$com = $0;
$com =~ s/.*\///;
$usage = "usage:\t$com [-a][-r][-x] pattern\n\t$com -c [name]\n\t$com [-a] -f file\n";
$ENV{'PATH'} = '/bin:/usr/bin';
#
# options check
#
while ($ARGV[0] =~ /^-/) {
$opt = shift;
if ($opt =~ /a/) { $aflag = 1; }
if ($opt =~ /c/) { $cflag = 1; }
if ($opt =~ /f/) { $fflag = 1; }
if ($opt =~ /r/) { $rflag = 1; }
if ($opt =~ /x/) { $xflag = 1; }
}
# -f option is valid when it is only one except for -a and -x option
if ($fflag && ($cflag || $rflag)) {
$fflag = 0;
}
# -c option is valid when it is only one
if ($cflag && ($aflag || $fflag || $rflag || $xflag)) {
$cflag = 0;
}
if (@ARGV == 0) {
die($usage) if (! $cflag);
}
if ($cflag && &regexp($ARGV[0])) {
die "$com: regular expression not allowed with -c option.\n";
}
$ARGV[0] =~ s/^[ \t]+//; # remove leading blanks
#
# get $dbpath and $root
#
local($dbpath, $root) = &getdbpath();
#
# recognize format version of GTAGS. 'format version record' is saved as a
# META record in GTAGS and GRTAGS. if 'format version record' is not found,
# it's assumed version 1.
$support_version = 1; # accept this format version
#
open(GTAGS, "btreeop -K ' __.VERSION' $dbpath/GTAGS |") || die "$com: GTAGS not found.\n";
$rec = <GTAGS>;
close(GTAGS);
if ($rec =~ /^ __\.VERSION[ \t]+([0-9]+)$/) {
$format_version = $1;
} else {
$format_version = 1;
}
if ($format_version > $support_version) {
die "$com: GTAGS seems new format. Please install the latest GLOBAL.\n";
}
#
# complete function name
#
if ($cflag) {
open(PIPEIN, "btreeop -L $dbpath/GTAGS |") || die "$com: btreeop cannot exec.\n";
while (<PIPEIN>) {
print if (@ARGV == 0 || $_ =~ /^$ARGV[0]/o);
}
close(PIPEIN);
exit(0);
}
#
# make path filter.
#
if ($aflag) {
@com = ("-e 's!\\.!$root!'"); # absolute
} else {
@com = &relative_filter($root); # relative
}
#
# print function definitions.
#
if ($fflag) {
if (! -f $ARGV[0]) { die "$com: file '$ARGV[0]' not exist.\n"; }
$path = &realpath($ARGV[0]);
$path =~ s/^$root/./;
chdir($root) || die "$com: cannot move to directory '$root'.\n";
system("gctags -Dex '$path' | sort +1n -2 | sed @com");
exit(0);
}
#
# search in current source tree.
#
$cnt = &search($ARGV[0], $dbpath, @com);
#
# search in library path.
#
if ($cnt == 0 && ! &regexp($ARGV[0]) && ! $rflag && defined($ENV{'GTAGSLIBPATH'})) {
local($cwd) = &getcwd;
foreach $lib (split(':', $ENV{'GTAGSLIBPATH'})) {
next unless (-f "$lib/GTAGS");
next if ($dbpath eq $lib);
chdir($lib) || die "$com: cannot chdir to $lib.\n";
$root = $dbpath = &getcwd;
if ($aflag) {
@com = ("-e 's!\\.!$root!'");
} else {
$common = &common($root, $cwd);
$up = $root;
$up =~ s/$common//;
$down = $cwd;
$down =~ s/$common//;
$down =~ s![^/]+!..!g;
next if ($down eq '' || $up eq '');
@com = ("-e 's!\\./!$down/$up/!'");
}
$cnt = &search($ARGV[0], $dbpath, @com);
last if ($cnt > 0);
}
chdir($cwd) || die "$com: cannot return current directory.\n";
}
exit(0);
#
# realpath: get absolute path name
#
# r) absolute path
#
sub realpath {
local($path) = @_;
local($dirname, $basename);
if ($path =~ m!^(.*)/([^/]*)$!) {
$dirname = $1;
$basename = $2;
} else {
$dirname = '.';
$basename = $path;
}
local($cwd) = &getcwd;
chdir($dirname) || die "$com: cannot move to '$dirname'.\n";
$path = &getcwd . '/' . $basename;
chdir($cwd) || die "$com: cannot return to '$cwd'.\n";
$path;
}
#
# getdbpath: get dbpath and root directory
#
# r) ($dbpath, $root)
#
sub getdbpath {
local($dbpath, $root);
local($cwd) = &getcwd;
if (defined($ENV{'GTAGSROOT'})) {
$dbpath = $root = $ENV{'GTAGSROOT'};
if (defined($ENV{'GTAGSDBPATH'})) {
$dbpath = $ENV{'GTAGSDBPATH'};
}
$root =~ /^\// || die "$com: GTAGSROOT must be an absolute path.\n";
$dbpath =~ /^\// || die "$com: GTAGSDBPATH must be an absolute path.\n";
chdir($root) || die "$com: directory $root not found.\n";
$root = &getcwd;
chdir($cwd);
chdir($dbpath) || die "$com: directory $dbpath not found.\n";
$dbpath = &getcwd;
if ($cwd !~ /^$root/) {
die "$com: you must be under GTAGSROOT.\n";
}
}
if (!$root) {
local($gtags) = 'GTAGS';
while (! -r $gtags && ! -r "obj/$gtags") {
if (&getcwd =~ m!^/$!) { die "$com: $gtags not found.\n"; }
chdir('..');
}
$dbpath = $root = &getcwd;
$dbpath = "$dbpath/obj" if (! -r $gtags);
}
chdir($cwd) || die "$com: cannot return current directory.\n";
($dbpath, $root);
}
#
# relative_filter: make relative path filter
#
# i) $root the root directory of source tree
# r) @com sed command list
#
sub relative_filter {
local($root) = @_;
local($cwd) = &getcwd;
local($cur) = $cwd;
$cur =~ s!$root!!;
$cur =~ s!^/!!;
local(@step) = split('/', $cur);
local($downpath) = '\\.\\./' x @step;
local(@com);
push(@com, "-e 's!\\./!$downpath!'");
foreach $step (@step) {
push(@com, "-e 's!\\.\\./$step/!!'");
}
chdir($cwd) || die "$com: cannot return current directory.\n";
@com;
}
#
# common: extract a common part of two paths.
#
# i) $p1, $p2 paths
# r) common part
#
sub common {
local($p1, $p2) = @_;
local(@p1, @p2, @common, $common);
@p1 = split('/', $p1);
@p2 = split('/', $p2);
while (@p1 && @p2 && $p1[0] eq $p2[0]) {
push(@common, shift @p1);
shift @p2;
}
$common = join('/', @common);
$common .= '/';
$common;
}
#
# search: search specified function
#
# i) $pattern search pattern
# i) $dbpath where GTAGS exist
# i) @com sed's command
# gi) $xflag -x option
# gi) $rflag -r option
# r) count of output lines
#
sub search {
local($pattern, $dbpath, @com) = @_;
local($regex, $gtags, $outfilter, $infilter);
#
# make input filter
#
$gtags = ($rflag) ? 'GRTAGS' : 'GTAGS';
if ($regex = &regexp($pattern)) { # regular expression
$infilter = "btreeop $dbpath/$gtags |";
} else {
$infilter = "btreeop -K '$pattern' $dbpath/$gtags |";
}
#
# make output filter
# gtags fields is same to ctags -x format.
# 0:tag, 1:lineno, 2:filename, 3: pattern.
#
if ($xflag) {
$outfilter = "| sort +0 -1 +2 -3 +1n -2";
} else {
$outfilter = "| awk '{print \$3}' | sort | uniq";
}
$outfilter .= "| sed @com";
open(PIPEIN, $infilter) || die "$com: database not found.\n";
open(PIPEOUT, $outfilter) || die "$com: pipe cannot open.\n";
local($cnt) = 0;
while (<PIPEIN>) {
local($tag) = split;
if (! $regex || $tag =~ /$pattern/o) {
$cnt++;
print PIPEOUT $_;
}
}
close(PIPEIN);
close(PIPEOUT);
$cnt;
}

298
contrib/global/gtags.el Normal file
View File

@ -0,0 +1,298 @@
;;; gtags.el --- gtags facility for Emacs
;;
;; Copyright (c) 1997 Shigio Yamaguchi. All rights reserved.
;;
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions
;; are met:
;; 1. Redistributions of source code must retain the above copyright
;; notice, this list of conditions and the following disclaimer.
;; 2. Redistributions in binary form must reproduce the above copyright
;; notice, this list of conditions and the following disclaimer in the
;; documentation and/or other materials provided with the distribution.
;; 3. All advertising materials mentioning features or use of this software
;; must display the following acknowledgement:
;; This product includes software developed by Shigio Yamaguchi.
;; 4. Neither the name of the author nor the names of any co-contributors
;; may be used to endorse or promote products derived from this software
;; without specific prior written permission.
;;
;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
;; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
;; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
;; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
;; SUCH DAMAGE.
;;
;; gtags.el 6-Jul-97
;;
;; This file is part of GLOBAL.
;; Author: Shigio Yamaguchi <shigio@wafu.netgate.net>
;; Version: 1.0
;; Keywords: tools
;;; Code
(defvar gtags-buffer-stack nil
"Stack for tag browsing.")
(defvar gtags-point-stack nil
"Stack for tag browsing.")
(defvar gtags-complete-list nil
"Gtags complete list.")
(defconst symbol-regexp "[A-Za-z_][A-Za-z_0-9]*"
"Regexp matching tag name.")
(defconst definition-regexp "#[ \t]*define[ \t]+\\|ENTRY(\\|ALTENTRY("
"Regexp matching tag definition name.")
(defvar gtags-read-only nil
"Gtags read only mode")
(defvar gtags-mode-map (make-sparse-keymap)
"Keymap used in gtags mode.")
(define-key gtags-mode-map "\et" 'gtags-find-tag)
(define-key gtags-mode-map "\er" 'gtags-find-rtag)
(define-key gtags-mode-map "\C-]" 'gtags-find-tag-from-here)
(define-key gtags-mode-map "\C-t" 'gtags-pop-stack)
(define-key gtags-mode-map "\e." 'etags-style-find-tag)
(define-key gtags-mode-map [mouse-2] 'gtags-find-tag-by-event)
(define-key gtags-mode-map [mouse-3] 'gtags-pop-stack)
(defvar gtags-select-mode-map (make-sparse-keymap)
"Keymap used in gtags select mode.")
(define-key gtags-select-mode-map "q" 'gtags-pop-stack)
(define-key gtags-select-mode-map "\C-t" 'gtags-pop-stack)
(define-key gtags-select-mode-map "\C-m" 'gtags-select-tag)
(define-key gtags-select-mode-map " " 'scroll-up)
(define-key gtags-select-mode-map "\^?" 'scroll-down)
(define-key gtags-select-mode-map "n" 'next-line)
(define-key gtags-select-mode-map "p" 'previous-line)
(define-key gtags-select-mode-map [mouse-2] 'gtags-select-tag-by-event)
(define-key gtags-select-mode-map [mouse-3] 'gtags-pop-stack)
;;
;; utirity
;;
(defun match-string (n)
(buffer-substring (match-beginning n) (match-end n)))
;; Return a default tag to search for, based on the text at point.
(defun gtags-current-token ()
(cond
((looking-at "[0-9A-Za-z_]")
(while (looking-at "[0-9A-Za-z_]")
(forward-char -1))
(forward-char 1))
(t
(while (looking-at "[ \t]")
(forward-char 1))))
(if (and (bolp) (looking-at definition-regexp))
(goto-char (match-end 0)))
(if (looking-at symbol-regexp)
(match-string 0) nil))
;; push current context to stack
(defun push-context ()
(setq gtags-buffer-stack (cons (current-buffer) gtags-buffer-stack))
(setq gtags-point-stack (cons (point) gtags-point-stack)))
;; pop context from stack
(defun pop-context ()
(if (not gtags-buffer-stack) nil
(let (buffer point)
(setq buffer (car gtags-buffer-stack))
(setq gtags-buffer-stack (cdr gtags-buffer-stack))
(setq point (car gtags-point-stack))
(setq gtags-point-stack (cdr gtags-point-stack))
(list buffer point))))
;; if the buffer exist in the stack
(defun exist-in-stack (buffer)
(memq buffer gtags-buffer-stack))
;; is it a definition?
(defun is-definition ()
(save-excursion
(if (bolp)
t
(forward-word -1)
(cond
((looking-at "define")
(forward-char -1)
(while (and (not (bolp)) (looking-at "[ \t]"))
(forward-char -1))
(if (and (bolp) (looking-at "#"))
t nil))
((looking-at "ENTRY\\|ALTENTRY")
(if (bolp) t nil))))))
;;
;; interactive command
;;
(defun gtags-find-tag ()
"Input tag name and move to the definition."
(interactive)
(let (tagname)
(setq tagname (completing-read ":tag " gtags-complete-list))
(push-context)
(gtags-goto-tag tagname t)))
(defun etags-style-find-tag ()
"Input tag name and move to the definition.(etags style)"
(interactive)
(let (tagname prompt input)
(setq tagname (gtags-current-token))
(if tagname
(setq prompt (concat "Find tag: (default " tagname ") "))
(setq prompt "Find tag: "))
(setq input (completing-read prompt gtags-complete-list))
(if (not (equal "" input)) (setq tagname input))
(push-context)
(gtags-goto-tag tagname t)))
(defun gtags-find-rtag ()
"Input tag name and move to the referenced point."
(interactive)
(let (tagname)
(setq tagname (completing-read ":rtag " gtags-complete-list))
(push-context)
(gtags-goto-tag tagname nil)))
(defun gtags-find-tag-from-here ()
"Get the expression as a tagname around here and move there."
(interactive)
(let (tagname)
(setq tagname (gtags-current-token))
(if (not tagname)
nil
(push-context)
(gtags-goto-tag tagname (not (is-definition))))))
(defun gtags-find-tag-by-event (event)
"Get the expression as a tagname around here and move there."
(interactive "e")
(select-window (posn-window (event-end event)))
(set-buffer (window-buffer (posn-window (event-end event))))
(goto-char (posn-point (event-end event)))
(let (tagname definition)
(setq definition nil)
(if (= 0 (count-lines (point-min) (point-max)))
(setq tagname "main")
(setq tagname (gtags-current-token))
(setq definition (is-definition)))
(if (not tagname)
nil
(push-context)
(gtags-goto-tag tagname (not definition)))))
(defun gtags-select-tag ()
"Select a tagname in [GTAGS SELECT MODE] and move there."
(interactive)
(push-context)
(gtags-select-it nil))
(defun gtags-select-tag-by-event (event)
"Select a tagname in [GTAGS SELECT MODE] and move there."
(interactive "e")
(select-window (posn-window (event-end event)))
(set-buffer (window-buffer (posn-window (event-end event))))
(goto-char (posn-point (event-end event)))
(push-context)
(gtags-select-it nil))
(defun gtags-pop-stack ()
"Move to previous point on the stack."
(interactive)
(let (delete context buffer)
(if (not (exist-in-stack (current-buffer)))
(setq delete t))
(setq context (pop-context))
(if (not context)
(message "The tags stack is empty.")
(if delete
(kill-buffer (current-buffer)))
(switch-to-buffer (nth 0 context))
(goto-char (nth 1 context)))))
;;
;; common function
;;
;; goto tag's point
(defun gtags-goto-tag (tagname definition)
(let (save flags buffer lines)
(setq save (current-buffer))
(if definition
(setq flags "") (setq flags "-r"))
;; load tag
(setq buffer (generate-new-buffer (generate-new-buffer-name (concat (if (equal flags "") "(D)" "(R)") tagname))))
(set-buffer buffer)
(if (not (= 0 (call-process "global" nil t nil (concat "-ax" flags) tagname)))
(progn (message "cannot execute global.")
(pop-context))
(goto-char (point-min))
(setq lines (count-lines (point-min) (point-max)))
(cond
((= 0 lines)
(message "%s: tag not found" tagname)
(pop-context)
(kill-buffer buffer)
(set-buffer save))
((= 1 lines)
(gtags-select-it t))
(t
(switch-to-buffer buffer)
(gtags-select-mode))))))
;; select a tag line from lines
(defun gtags-select-it (delete)
(let (line file)
;; get context from current tag line
(beginning-of-line)
(if (not (looking-at "[A-Za-z_][A-Za-z_0-9]*[ \t]+\\([0-9]+\\)[ \t]\\([^ \t]+\\)[ \t]"))
(pop-context)
(setq line (string-to-number (match-string 1)))
(setq file (match-string 2))
(if delete (kill-buffer (current-buffer)))
;; move to the context
(if gtags-read-only (find-file-read-only file) (find-file file))
(goto-line line)
(use-local-map gtags-mode-map))))
;; make complete list
(defun make-gtags-complete-list ()
(save-excursion
(setq gtags-complete-list (make-vector 63 0))
(set-buffer (generate-new-buffer "*Completions*"))
(call-process "global" nil t nil "-c")
(goto-char (point-min))
(while (looking-at symbol-regexp)
(intern (match-string 0) gtags-complete-list)
(forward-line))
(kill-buffer (current-buffer))))
;;;###autoload
(defun gtags-mode ()
"Minor mode for browsing C source using GLOBAL."
(interactive)
(make-gtags-complete-list)
(use-local-map gtags-mode-map)
(run-hooks 'gtags-mode-hook))
;; make gtags select mode
(defun gtags-select-mode ()
"Major mode for choosing a tag from tags list."
(setq buffer-read-only t
major-mode 'gtags-select-mode
mode-name "Gtags Select")
(use-local-map gtags-select-mode-map)
(setq truncate-lines t)
(goto-char (point-min))
(message "[GTAGS SELECT MODE] %d lines" (count-lines (point-min) (point-max)))
(run-hooks 'gtags-select-mode-hook))
;;; gtags.el ends here

View File

@ -0,0 +1,9 @@
# @(#)Makefile 1.0 (Berkeley) 4/21/96
MAN1= gtags.1
beforeinstall:
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
${.CURDIR}/gtags.pl ${DESTDIR}/usr/bin/gtags
.include <bsd.prog.mk>

View File

@ -0,0 +1,13 @@
# @(#)Makefile 29-Dec-96
PROG = gtags
BINDIR = /usr/bin
MANDIR = /usr/share/man
all:
install:
cp $(PROG).pl $(BINDIR)/$(PROG)
chmod 755 $(BINDIR)/$(PROG)
cp $(PROG).1 $(MANDIR)/man1
chmod 644 $(MANDIR)/man1/$(PROG).1
clean:

View File

@ -0,0 +1,86 @@
.\"
.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Shigio Yamaguchi.
.\" 4. Neither the name of the author nor the names of any co-contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd April 21, 1997
.Dt GTAGS 1
.Os BSD 4
.Sh NAME
.Nm gtags
.Nd create GTAGS, GRTAGS file
.Sh SYNOPSIS
.Nm gtags
.Op Fl e
.Op Fl s
.Op Ar dbpath
.Sh DESCRIPTION
.Nm Gtags
makes GTAGS, GRTAGS files for global(1).
.Nm Gtags
trace subdirectories, read source files,
locate the functions and save the information into tag files.
C, yacc and assembler source files are supported.
You should execute this command at the root of the source tree.
.Pp
If your source directory is on a read only device like CDROM, specify
.Ar dbpath
of the directory on which make tags files.
.Pp
.Bl -tag -width Ds
.It Fl e
force a function to end when reach a '}' at the first column in C source file.
.It Fl s
treat assembler source file (*.s, *.S).
.Sh FILES
.Bl -tag -width tags -compact
.It Pa GTAGS
tags file for function definitions.
.It Pa GRTAGS
tags file for function references.
.El
.Sh DIAGNOSTICS
.Nm Gtags
exits with a value of 1 if an error occurred, 0 otherwise.
.Sh SEE ALSO
.Xr btreeop 1 ,
.Xr gctags 1 ,
.Xr global 1 ,
.Xr htags 1 .
.Sh BUG
GTAGS, GRTAGS are very large. In advance, check the space of your disk.
Assembler support is far from completeness. It extracts only ENTRY()
and ALTENTRY() from source file. Probably valid only for FreeBSD and Linux
kernel source.
.Sh AUTHORS
Shigio Yamaguchi (shigio@wafu.netgate.net)
.Sh HISTORY
The
.Nm
command appeared in FreeBSD 2.2.

View File

@ -0,0 +1,84 @@
#!/usr/bin/perl
#
# Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Shigio Yamaguchi.
# 4. Neither the name of the author nor the names of any co-contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# gtags.pl 5-Jul-97
#
$com = $0;
$com =~ s/.*\///;
$usage = "usage: $com [-e][-s][dbpath]";
$ENV{'PATH'} = '/bin:/usr/bin';
#
# ctags flag
#
$eflag = $sflag = '';
while ($ARGV[0] =~ /^-/) {
$opt = shift;
if ($opt =~ /[^-es]/) { die "$usage\n"; }
if ($opt =~ /e/) { $eflag = 'e'; }
if ($opt =~ /s/) { $sflag = 's'; }
}
$dbpath = '.';
$dbpath = $ARGV[0] if ($ARGV[0]);
if (-f "$dbpath/GTAGS" && -f "$dbpath/GRTAGS") {
if (! -w "$dbpath/GTAGS") {
die "$com: cannot write to GTAGS.\n";
} elsif (! -w "$dbpath/GRTAGS") {
die "$com: cannot write to GRTAGS.\n";
}
} elsif (! -w "$dbpath") {
die "$com: cannot write to the directory '$dbpath'.\n"
}
#
# make global database
#
foreach $db ('GTAGS', 'GRTAGS') {
# currently only *.c *.h *.y are supported.
# *.s *.S is valid only when -s option specified.
open(FIND, "find . -type f -name '*.[chysS]' -print |") || die "$com: cannot exec find.\n";
open(DB, "|btreeop -C $dbpath/$db") || die "$com: cannot create db file '$dbpath/$db'.\n";
while (<FIND>) {
chop;
next if /(y\.tab\.c|y\.tab\.h)$/;
next if /(\/SCCS\/|\/RCS\/)/;
next if (/\.[sS]$/ && (!$sflag || $db eq 'GRTAGS'));
$flag = ($db eq 'GRTAGS') ? "${eflag}Dxr" : "${eflag}Dx";
$ENV{'GTAGDBPATH'} = $dbpath;
open(TAGS, "gctags -$flag $_ |") || die "$com: cannot read '$_'.\n";
while (<TAGS>) {
print DB;
}
close(TAGS);
}
close(DB);
close(FIND);
}
exit 0;

View File

@ -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>

View File

@ -0,0 +1,13 @@
# @(#)Makefile 29-Dec-96
PROG = htags
BINDIR = /usr/bin
MANDIR = /usr/share/man
all:
install:
cp $(PROG).pl $(BINDIR)/$(PROG)
chmod 755 $(BINDIR)/$(PROG)
cp $(PROG).1 $(MANDIR)/man1
chmod 644 $(MANDIR)/man1/$(PROG).1
clean:

View File

@ -0,0 +1,124 @@
.\"
.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Shigio Yamaguchi.
.\" 4. Neither the name of the author nor the names of any co-contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd June 28, 1997
.Dt HTAGS 1
.Os BSD 4
.Sh NAME
.Nm htags
.Nd generate hypertext from C and Yacc source code
.Sh SYNOPSIS
.Nm htags
.Op Fl a
.Op Fl f
.Op Fl l
.Op Fl n
.Op Fl v
.Op Fl w
.Op Fl d Ar tagdir
.Op Fl t Ar title
.Op Ar dir
.Sh DESCRIPTION
.Nm Htags
makes hypertext from C and Yacc source code using GLOBAL database (GTAGS, GRTAGS).
.Pp
In advance of using this command, you must execute
.Xr gtags 1
at the root directory of the source tree.
Then you can execute
.Nm htags
at the same place.
.Nm Htags
makes HTML directory and generate hypertext in it.
.Pp
You can start browsing from 'HTML/index.html'.
Once hypertext generated, you can move it anywhere and browse it
by any browsers.
.Pp
.br
.Bl -tag -width Ds
.It Fl a
make an alphabetical function index. It's suitable for large project.
.It Fl f
support input form and dynamic index by CGI program.
You need to setup HTTP server for it.
.It Fl l
make name tag(<A NAME=line number>) for each line so that outer hypertext
can point any line of this hypertext.
By default, make it only for lines which have referred object.
.It Fl n
print line number. By default, doesn't print it.
.It Fl v
verbose mode.
.It Fl w
print warning message.
.It Fl d Ar tagdir
the directory in which GTAGS and GRTAGS exist. Default is current directory.
.It Fl t Ar title
Tile of this hypertext. Default is the last conponent of current path.
.It Ar dir
the directory in which hypertext generated. Default is current directory.
.Sh EXAMPLES
% cd /usr/src/sys
# gtags -se
# htags -fnvat 'Welcom to FreeBSD kernel source tour!'
% lynx HTML/index.html
.Sh FILES
.Bl -tag -width tags -compact
.It Pa HTML/index.html
Index file.
.It Pa GTAGS
tags file for function definitions.
.It Pa GRTAGS
tags file for function references.
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of htags.
.Pp
.Bl -tag -width indent
.It Ev TMPDIR
If this variable is set, its value is used as the directory to make temporary file.
Default is /tmp.
.Sh DIAGNOSTICS
.Nm Htags
exits with a value of 1 if an error occurred, 0 otherwise.
.Sh SEE ALSO
.Xr btreeop 1 ,
.Xr gctags 1 ,
.Xr global 1 ,
.Xr gtags 1 .
.Sh BUG
Generated hypertext is VERY LARGE. In advance, check the space of your disk.
.Sh AUTHORS
Shigio Yamaguchi (shigio@wafu.netgate.net)
.Sh HISTORY
The
.Nm
command appeared in FreeBSD 2.2.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ansi.h 8.2 (Berkeley) 1/4/94
* $Id: ansi.h,v 1.10 1996/05/01 00:47:05 bde Exp $
*/
#ifndef _MACHINE_ANSI_H_
#define _MACHINE_ANSI_H_
/*
* Types which are fundamental to the implementation and must be declared
* in more than one standard header are defined here. Standard headers
* then use:
* #ifdef _BSD_SIZE_T_
* typedef _BSD_SIZE_T_ size_t;
* #undef _BSD_SIZE_T_
* #endif
*/
#define _BSD_CLOCK_T_ unsigned long /* clock() */
#define _BSD_PTRDIFF_T_ int /* ptr1 - ptr2 */
#define _BSD_RUNE_T_ _BSD_CT_RUNE_T_ /* rune_t (see below) */
#define _BSD_SIZE_T_ unsigned int /* sizeof() */
#define _BSD_SSIZE_T_ int /* byte count or error */
#define _BSD_TIME_T_ long /* time() */
#define _BSD_WCHAR_T_ _BSD_CT_RUNE_T_ /* wchar_t (see below) */
/*
* Types which are fundamental to the implementation and must be used
* in more than one standard header although they are only declared in
* one (perhaps nonstandard) header are defined here. Standard headers
* use _BSD_XXX_T_ without undef'ing it.
*/
#define _BSD_CT_RUNE_T_ int /* arg type for ctype funcs */
#define _BSD_OFF_T_ long long /* file offset */
#define _BSD_PID_T_ int /* process [group] */
#define _BSD_VA_LIST_ char * /* va_list */
/*
* The rune type is declared to be an ``int'' instead of the more natural
* ``unsigned long'' or ``long''. Two things are happening here. It is not
* unsigned so that EOF (-1) can be naturally assigned to it and used. Also,
* it looks like 10646 will be a 31 bit standard. This means that if your
* ints cannot hold 32 bits, you will be in trouble. The reason an int was
* chosen over a long is that the is*() and to*() routines take ints (says
* ANSI C), but they use _BSD_CT_RUNE_T_ instead of int. By changing it
* here, you lose a bit of ANSI conformance, but your programs will still
* work.
*/
/*
* Frequencies of the clock ticks reported by clock() and times(). They
* are the same as stathz for bogus historical reasons. They should be
* 1e6 because clock() and times() are implemented using getrusage() and
* there is no good reason why they should be less accurate. There is
* the bad reason that (broken) programs might not like clock_t or
* CLOCKS_PER_SEC being ``double'' (``unsigned long'' is not large enough
* to hold the required 24 hours worth of ticks if the frequency is
* 1000000ul, and ``unsigned long long'' would be nonstandard).
*/
#define _BSD_CLK_TCK_ 128
#define _BSD_CLOCKS_PER_SEC_ 128
#endif /* !_MACHINE_ANSI_H_ */

View File

@ -0,0 +1,158 @@
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Berkeley Software Design, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cdefs.h 8.8 (Berkeley) 1/9/95
* $Id: cdefs.h,v 1.11 1996/08/18 16:14:03 peter Exp $
*/
#ifndef _SYS_CDEFS_H_
#define _SYS_CDEFS_H_
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS };
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
/*
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
* with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
* The __CONCAT macro is a bit tricky -- make sure you don't put spaces
* in between its arguments. __CONCAT can also concatenate double-quoted
* strings produced by the __STRING macro, but this only works with ANSI C.
*/
#if defined(__STDC__) || defined(__cplusplus)
#define __P(protos) protos /* full-blown ANSI C */
#define __CONCAT1(x,y) x ## y
#define __CONCAT(x,y) __CONCAT1(x,y)
#define __STRING(x) #x
#define __const const /* define reserved names to standard */
#define __signed signed
#define __volatile volatile
#if defined(__cplusplus)
#define __inline inline /* convert to C++ keyword */
#else
#ifndef __GNUC__
#define __inline /* delete GCC keyword */
#endif /* !__GNUC__ */
#endif /* !__cplusplus */
#else /* !(__STDC__ || __cplusplus) */
#define __P(protos) () /* traditional C preprocessor */
#define __CONCAT(x,y) x/**/y
#define __STRING(x) "x"
#ifndef __GNUC__
#define __const /* delete pseudo-ANSI C keywords */
#define __inline
#define __signed
#define __volatile
/*
* In non-ANSI C environments, new programs will want ANSI-only C keywords
* deleted from the program and old programs will want them left alone.
* When using a compiler other than gcc, programs using the ANSI C keywords
* const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
* When using "gcc -traditional", we assume that this is the intent; if
* __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
*/
#ifndef NO_ANSI_KEYWORDS
#define const /* delete ANSI C keywords */
#define inline
#define signed
#define volatile
#endif /* !NO_ANSI_KEYWORDS */
#endif /* !__GNUC__ */
#endif /* !(__STDC__ || __cplusplus) */
/*
* GCC1 and some versions of GCC2 declare dead (non-returning) and
* pure (no side effects) functions using "volatile" and "const";
* unfortunately, these then cause warnings under "-ansi -pedantic".
* GCC2.5 uses a new, peculiar __attribute__((attrs)) style. All of
* these work for GNU C++ (modulo a slight glitch in the C++ grammar
* in the distribution version of 2.5.5).
*/
#if __GNUC__ < 2
#define __dead
#define __dead2
#define __pure
#define __pure2
#define __unused
#define __attribute__(x)
#endif
#if __GNUC__ == 2 && __GNUC_MINOR__ < 5
#define __dead __volatile
#define __dead2
#define __pure __const
#define __pure2
#define __unused
#endif
#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7
#define __dead
#define __dead2 __attribute__((__noreturn__))
#define __pure
#define __pure2 __attribute__((__const__))
#define __unused
#endif
#if __GNUC__ == 2 && __GNUC_MINOR__ >= 7 || __GNUC__ >= 3
#define __dead
#define __dead2 __attribute__((__noreturn__))
#define __pure
#define __pure2 __attribute__((__const__))
#define __unused __attribute__((__unused__))
#endif
#ifdef __GNUC__
#ifdef __STDC__
#define __weak_reference(sym,alias) \
__asm__(".stabs \"_" #alias "\",11,0,0,0"); \
__asm__(".stabs \"_" #sym "\",1,0,0,0")
#define __warn_references(sym,msg) \
__asm__(".stabs \"" msg "\",30,0,0,0"); \
__asm__(".stabs \"_" #sym "\",1,0,0,0")
#else
#define __weak_reference(sym,alias) \
__asm__(".stabs \"_/**/alias\",11,0,0,0"); \
__asm__(".stabs \"_/**/sym\",1,0,0,0")
#define __warn_references(sym,msg) \
__asm__(".stabs msg,30,0,0,0"); \
__asm__(".stabs \"_/**/sym\",1,0,0,0")
#endif
#endif
#endif /* !_SYS_CDEFS_H_ */

View File

@ -0,0 +1,62 @@
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)err.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _ERR_H_
#define _ERR_H_
/*
* Don't use va_list in the err/warn prototypes. Va_list is typedef'd in two
* places (<machine/varargs.h> and <machine/stdarg.h>), so if we include one
* of them here we may collide with the utility's includes. It's unreasonable
* for utilities to have to include one of them to include err.h, so we get
* _BSD_VA_LIST_ from <machine/ansi.h> and use it.
*/
#include <ansi.h>
#include <cdefs.h>
__BEGIN_DECLS
void err __P((int, const char *, ...)) __dead2;
void verr __P((int, const char *, _BSD_VA_LIST_)) __dead2;
void errx __P((int, const char *, ...)) __dead2;
void verrx __P((int, const char *, _BSD_VA_LIST_)) __dead2;
void warn __P((const char *, ...));
void vwarn __P((const char *, _BSD_VA_LIST_));
void warnx __P((const char *, ...));
void vwarnx __P((const char *, _BSD_VA_LIST_));
void err_set_file __P((void *));
void err_set_exit __P((void (*)(int)));
__END_DECLS
#endif /* !_ERR_H_ */

View File

@ -0,0 +1,900 @@
diff -c -r -N /usr/src/usr.bin/vi/USD.doc/vi.man/vi.1 ./USD.doc/vi.man/vi.1
*** /usr/src/usr.bin/vi/USD.doc/vi.man/vi.1 Wed Aug 17 08:36:39 1994
--- ./USD.doc/vi.man/vi.1 Sat Dec 14 11:54:14 1996
***************
*** 39,59 ****
.Nd text editors
.Sh SYNOPSIS
.Nm \&ex
! .Op Fl eFRrsv
.Op Fl c Ar cmd
.Op Fl t Ar tag
.Op Fl w Ar size
.\".Op Fl X Ar \&aw
.Op Ar "file ..."
.Nm \&vi
! .Op Fl eFRrv
.Op Fl c Ar cmd
.Op Fl t Ar tag
.Op Fl w Ar size
.\".Op Fl X Ar \&aw
.Op Ar "file ..."
.Nm view
! .Op Fl eFRrv
.Op Fl c Ar cmd
.Op Fl t Ar tag
.Op Fl w Ar size
--- 39,59 ----
.Nd text editors
.Sh SYNOPSIS
.Nm \&ex
! .Op Fl eFGRrsv
.Op Fl c Ar cmd
.Op Fl t Ar tag
.Op Fl w Ar size
.\".Op Fl X Ar \&aw
.Op Ar "file ..."
.Nm \&vi
! .Op Fl eFGRrv
.Op Fl c Ar cmd
.Op Fl t Ar tag
.Op Fl w Ar size
.\".Op Fl X Ar \&aw
.Op Ar "file ..."
.Nm view
! .Op Fl eFGRrv
.Op Fl c Ar cmd
.Op Fl t Ar tag
.Op Fl w Ar size
***************
*** 124,129 ****
--- 124,131 ----
Don't copy the entire file when first starting to edit.
(The default is to make a copy in case someone else modifies
the file during your edit session.)
+ .It Fl G
+ Start editing in gtags mode, as if the gtagsmode option was set.
.It Fl R
Start editing in read-only mode, as if the command name was
.Nm view ,
***************
*** 377,382 ****
--- 379,385 ----
Move the cursor down
.Li count
lines to the first nonblank character of that line.
+ In gtags select mode, <control-M> select current line as a tag.
.It Sy "[count] <control-P>"
.It Sy "[count] k"
Move the cursor up
***************
*** 402,408 ****
.Nm \&ex
commands or cancel partial commands.
.It Sy "<control-]>"
! Push a tag reference onto the tag stack.
.It Sy "<control-^>"
Switch to the most recently edited file.
.It Sy "[count] <space>"
--- 405,412 ----
.Nm \&ex
commands or cancel partial commands.
.It Sy "<control-]>"
! Push a tag reference onto the tag stack. In gtagsmode, if at the first column
! of line, locate function references otherwise function definitions.
.It Sy "<control-^>"
Switch to the most recently edited file.
.It Sy "[count] <space>"
***************
*** 780,785 ****
--- 784,793 ----
Grow or shrink the current screen.
.It Sy "rew[ind][!]"
Rewind the argument list.
+ .It Sy "rta[g][!] tagstring"
+ Edit the file refering the specified tag. (Only in gtagsmode)
+ .It Sy "se[lect]"
+ Select a tag from gtags list.
.It Sy "se[t] [option[=[value]] ...] [nooption ...] [option? ...] [all]"
Display or set editor options.
.It Sy "sh[ell]"
***************
*** 901,906 ****
--- 909,916 ----
style) expressions.
.It Sy "flash [on]"
Flash the screen instead of beeping the keyboard on error.
+ .It Sy "gtagsmode, gt [off]"
+ Use GTAGS and GRTAGS instead of tags.
.It Sy "hardtabs, ht [8]"
Set the spacing between hardware tab settings.
.It Sy "ignorecase, ic [off]"
diff -c -r -N /usr/src/usr.bin/vi/common/Makefile ./common/Makefile
*** /usr/src/usr.bin/vi/common/Makefile Mon Sep 12 07:01:45 1994
--- ./common/Makefile Sat Dec 14 11:55:27 1996
***************
*** 9,15 ****
LINKS+= ${BINDIR}/${VI} ${BINDIR}/view
MAN1= ${.CURDIR}/../USD.doc/vi.man/vi.1
! CFLAGS+=-I. -I${.CURDIR}
DPADD+= ${LIBCURSES} ${LIBTERMCAP} ${LIBUTIL}
LDADD+= -lcurses -ltermcap -lutil
--- 9,15 ----
LINKS+= ${BINDIR}/${VI} ${BINDIR}/view
MAN1= ${.CURDIR}/../USD.doc/vi.man/vi.1
! CFLAGS+=-I. -I${.CURDIR} -DGTAGS
DPADD+= ${LIBCURSES} ${LIBTERMCAP} ${LIBUTIL}
LDADD+= -lcurses -ltermcap -lutil
diff -c -r -N /usr/src/usr.bin/vi/common/exf.c ./common/exf.c
*** /usr/src/usr.bin/vi/common/exf.c Tue May 30 15:35:44 1995
--- ./common/exf.c Sat Dec 14 11:54:15 1996
***************
*** 156,162 ****
--- 156,169 ----
* Required FRP initialization; the only flag we keep is the
* cursor information.
*/
+ #ifdef GTAGS
+ /*
+ * we must keep gtagstmp information too.
+ */
+ F_CLR(frp, ~(FR_CURSORSET|FR_GTAGSTMP));
+ #else
F_CLR(frp, ~FR_CURSORSET);
+ #endif
/*
* Required EXF initialization:
***************
*** 290,295 ****
--- 297,305 ----
* an error.
*/
if (rcv_name == NULL)
+ #ifdef GTAGS
+ if (!F_ISSET(frp, FR_GTAGSTMP))
+ #endif
switch (file_lock(oname,
&ep->fcntl_fd, ep->db->fd(ep->db), 0)) {
case LOCK_FAILED:
diff -c -r -N /usr/src/usr.bin/vi/common/gs.h ./common/gs.h
*** /usr/src/usr.bin/vi/common/gs.h Wed Aug 17 08:36:42 1994
--- ./common/gs.h Sat Dec 14 11:54:15 1996
***************
*** 48,53 ****
--- 48,56 ----
sigset_t blockset; /* Signal mask. */
+ #ifdef GTAGS
+ char *gtagstmp; /* gtagstmp made by -t option */
+ #endif
#ifdef DEBUG
FILE *tracefp; /* Trace file pointer. */
#endif
diff -c -r -N /usr/src/usr.bin/vi/common/main.c ./common/main.c
*** /usr/src/usr.bin/vi/common/main.c Tue May 30 15:35:45 1995
--- ./common/main.c Sat Dec 14 11:54:15 1996
***************
*** 98,103 ****
--- 98,106 ----
SCR *sp;
u_int flags, saved_vi_mode;
int ch, eval, flagchk, readonly, silent, snapshot;
+ #ifdef GTAGS
+ int gtags = 0;
+ #endif
char *excmdarg, *myname, *p, *tag_f, *trace_f, *wsizearg;
char path[MAXPATHLEN];
***************
*** 134,140 ****
--- 137,147 ----
excmdarg = tag_f = trace_f = wsizearg = NULL;
silent = 0;
snapshot = 1;
+ #ifdef GTAGS
+ while ((ch = getopt(argc, argv, "c:eFGRrsT:t:vw:X:")) != EOF)
+ #else
while ((ch = getopt(argc, argv, "c:eFRrsT:t:vw:X:")) != EOF)
+ #endif
switch (ch) {
case 'c': /* Run the command. */
excmdarg = optarg;
***************
*** 146,151 ****
--- 153,163 ----
case 'F': /* No snapshot. */
snapshot = 0;
break;
+ #ifdef GTAGS
+ case 'G': /* gtags mode. */
+ gtags = 1;
+ break;
+ #endif
case 'R': /* Readonly. */
readonly = 1;
break;
***************
*** 245,250 ****
--- 257,266 ----
goto err;
if (readonly) /* Global read-only bit. */
O_SET(sp, O_READONLY);
+ #ifdef GTAGS
+ if (gtags) /* Global gtags bit. */
+ O_SET(sp, O_GTAGSMODE);
+ #endif
if (silent) { /* Ex batch mode. */
O_CLR(sp, O_AUTOPRINT);
O_CLR(sp, O_PROMPT);
***************
*** 515,520 ****
--- 531,539 ----
LIST_INIT(&gp->cutq);
LIST_INIT(&gp->seqq);
+ #ifdef GTAGS
+ gp->gtagstmp = NULL;
+ #endif
/* Set a flag if we're reading from the tty. */
if (isatty(STDIN_FILENO))
F_SET(gp, G_STDIN_TTY);
***************
*** 554,559 ****
--- 573,584 ----
SCR *sp;
char *tty;
+ #ifdef GTAGS
+ if (gp->gtagstmp) {
+ if (!strncmp(gp->gtagstmp, _PATH_GTAGSTMP, strlen(_PATH_GTAGSTMP)))
+ (void)unlink(gp->gtagstmp);
+ }
+ #endif
/* Default buffer storage. */
(void)text_lfree(&gp->dcb_store.textq);
diff -c -r -N /usr/src/usr.bin/vi/common/msg.c ./common/msg.c
*** /usr/src/usr.bin/vi/common/msg.c Thu Aug 18 10:10:54 1994
--- ./common/msg.c Sat Dec 14 11:54:15 1996
***************
*** 338,343 ****
--- 338,352 ----
#else
pid = "";
#endif
+ #ifdef GTAGS
+ if (F_ISSET(sp->frp, FR_GTAGSTMP)) {
+ if (file_lline(sp, ep, &last)) {
+ return (1);
+ }
+ msgq(sp, M_INFO, "[GTAGS SELECT MODE] %d lines", last);
+ return (0);
+ }
+ #endif
/*
* See nvi/exf.c:file_init() for a description of how and
* when the read-only bit is set.
diff -c -r -N /usr/src/usr.bin/vi/common/options.c ./common/options.c
*** /usr/src/usr.bin/vi/common/options.c Tue May 30 15:35:46 1995
--- ./common/options.c Sat Dec 14 11:54:15 1996
***************
*** 103,108 ****
--- 103,112 ----
{"extended", NULL, OPT_0BOOL, 0},
/* O_FLASH HPUX */
{"flash", NULL, OPT_1BOOL, 0},
+ #ifdef GTAGS
+ /* O_GTAGSMODE SPECIAL */
+ {"gtagsmode", NULL, OPT_0BOOL, 0},
+ #endif
/* O_HARDTABS 4BSD */
{"hardtabs", NULL, OPT_NUM, 0},
/* O_IGNORECASE 4BSD */
***************
*** 228,233 ****
--- 232,240 ----
{"eb", O_ERRORBELLS}, /* 4BSD */
{"ed", O_EDCOMPATIBLE}, /* 4BSD */
{"ex", O_EXRC}, /* System V (undocumented) */
+ #ifdef GTAGS
+ {"gt", O_GTAGSMODE}, /* Special */
+ #endif
{"ht", O_HARDTABS}, /* 4BSD */
{"ic", O_IGNORECASE}, /* 4BSD */
{"li", O_LINES}, /* 4.4BSD */
diff -c -r -N /usr/src/usr.bin/vi/common/pathnames.h ./common/pathnames.h
*** /usr/src/usr.bin/vi/common/pathnames.h Wed Aug 17 08:36:43 1994
--- ./common/pathnames.h Sat Dec 14 11:54:15 1996
***************
*** 43,45 ****
--- 43,48 ----
#define _PATH_TAGS "tags"
#define _PATH_TMP "/tmp"
#define _PATH_TTY "/dev/tty"
+ #ifdef GTAGS
+ #define _PATH_GTAGSTMP "/var/tmp/gtags"
+ #endif
diff -c -r -N /usr/src/usr.bin/vi/common/screen.h ./common/screen.h
*** /usr/src/usr.bin/vi/common/screen.h Wed Aug 17 08:36:43 1994
--- ./common/screen.h Sat Dec 14 11:54:15 1996
***************
*** 87,92 ****
--- 87,95 ----
#define FR_TMPEXIT 0x100 /* Modified temporary file, no exit. */
#define FR_TMPFILE 0x200 /* If file has no name. */
#define FR_UNLOCKED 0x400 /* File couldn't be locked. */
+ #ifdef GTAGS
+ #define FR_GTAGSTMP 0x800 /* File is gtags temporary file. */
+ #endif
u_int16_t flags;
};
diff -c -r -N /usr/src/usr.bin/vi/ex/ex_tag.c ./ex/ex_tag.c
*** /usr/src/usr.bin/vi/ex/ex_tag.c Thu Aug 18 10:13:20 1994
--- ./ex/ex_tag.c Sat Dec 14 11:54:15 1996
***************
*** 64,69 ****
--- 64,72 ----
#include "vi.h"
#include "excmd.h"
#include "tag.h"
+ #ifdef GTAGS
+ #include "pathnames.h"
+ #endif
static char *binary_search __P((char *, char *, char *));
static int compare __P((char *, char *, char *));
***************
*** 71,76 ****
--- 74,288 ----
static int search __P((SCR *, char *, char *, char **));
static int tag_get __P((SCR *, char *, char **, char **, char **));
+ #ifdef DEBUG
+ void
+ trace(fp)
+ FILE *fp;
+ {
+ SCR *sp;
+ TAG *tp;
+ FREF *frp;
+ int scr, fref, tag;
+
+ fprintf(fp, "------------------------------------\n");
+ scr = 0;
+ for (sp = __global_list->dq.cqh_first; sp != (void *)&__global_list->dq; sp = sp->q.cqe_next) {
+ fprintf(fp, "screen %d {\n", ++scr);
+ fref = 0;
+ for (frp = sp->frefq.cqh_first;
+ frp != (FREF *)&sp->frefq; frp = frp->q.cqe_next) {
+ fprintf(fp, " FREF %d ", ++fref);
+ if (F_ISSET(frp, FR_GTAGSTMP))
+ fprintf(fp, "<%s>\n", frp->name);
+ else
+ fprintf(fp, "%s\n", frp->name);
+ }
+ tag = 0;
+ if (!EXP(sp))
+ continue;
+ fprintf(fp, " ................................\n");
+ for (tp = EXP(sp)->tagq.tqh_first; tp != NULL; tp = tp->q.tqe_next) {
+ fprintf(fp, " TAG %d ", ++tag);
+ if (F_ISSET(tp->frp, FR_GTAGSTMP))
+ fprintf(fp, "<%s>\n", tp->frp->name);
+ else
+ fprintf(fp, "%s\n", tp->frp->name);
+ }
+ fprintf(fp, "}\n");
+ }
+ fprintf(fp, "------------------------------------\n");
+ }
+ #endif
+ #ifdef GTAGS
+ /*
+ * getentry --
+ * get tag information from current line.
+ *
+ * gtags temporary file format.
+ * <tag> <lineno> <file> <image>
+ *
+ * sample.
+ * +------------------------------------------------
+ * |main 30 main.c main(argc, argv)
+ * |func 21 subr.c func(arg)
+ */
+ static int
+ getentry(buf, tag, file, line)
+ char *buf, *tag, *file, *line;
+ {
+ char *p;
+
+ p = tag;
+ while (*buf && !isspace(*buf)) /* tag name */
+ *p++ = *buf++;
+ *p = 0;
+ while (*buf && isspace(*buf)) /* skip blanks */
+ buf++;
+ p = line;
+ while (*buf && !isspace(*buf)) /* line no */
+ *p++ = *buf++;
+ *p = 0;
+ while (*buf && isspace(*buf)) /* skip blanks */
+ buf++;
+ p = file;
+ while (*buf && !isspace(*buf)) /* file name */
+ *p++ = *buf++;
+ *p = 0;
+
+ /* value check */
+ if (strlen(tag) && strlen(line) && strlen(file) && atoi(line) > 0)
+ return 1; /* OK */
+ return 0; /* ERROR */
+ }
+
+ /*
+ * gtag_get --
+ * Get a gtag from the GTAGS files.
+ */
+ static int
+ gtag_get(sp, ref, gtagselect, tag, tagp, filep, searchp)
+ SCR *sp;
+ int ref;
+ int *gtagselect;
+ char *tag, **tagp, **filep, **searchp;
+ {
+ static char name[80], file[200], line[10], gtagstmp[80];
+ char command[200];
+ char buf[BUFSIZ+1];
+ FILE *fp;
+
+ sprintf(gtagstmp, "%s.XXXXXXXX", _PATH_GTAGSTMP);
+ if (mktemp(gtagstmp) == 0) {
+ msgq(sp, M_ERR, "cannot generate temporary file name");
+ return (1);
+ }
+ sprintf(command, "global -%s '%s' > %s; chmod 600 %s",
+ ref ? "rx" : "x", tag, gtagstmp, gtagstmp);
+ if (system(command)) {
+ msgq(sp, M_ERR, "cannot exec global");
+ goto err;
+ }
+ if (!(fp = fopen(gtagstmp, "r"))) {
+ msgq(sp, M_ERR, "tag file cannot open.");
+ goto err;
+ }
+ if (!(fgets(buf, BUFSIZ, fp))) {
+ msgq(sp, M_ERR, "%s: tag not found", tag);
+ fclose(fp);
+ goto err;
+ }
+
+ if (getentry(buf, name, file, line) == 0) {
+ msgq(sp, M_ERR, "%s: illegal tag entry", tag);
+ fclose(fp);
+ goto err;
+ }
+
+ if (!(fgets(buf, BUFSIZ, fp))) { /* just one line */
+ fclose(fp);
+ (void)unlink(gtagstmp);
+ *gtagselect = 0; /* go to user's file immediately */
+ *tagp = strdup(name);
+ *filep = file;
+ *searchp = line;
+ if (*tagp == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+ return (0);
+ }
+ fclose(fp);
+ *gtagselect = 1; /* go to gtags select mode */
+ *tagp = strdup(name);
+ *filep = gtagstmp;
+ *searchp = "1";
+ if (*tagp == NULL) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+ return (0);
+ err:
+ (void)unlink(gtagstmp);
+ return (1);
+ }
+
+ /*
+ * ex_gtagselect --
+ * The tag code can be entered from gtag select mode.
+ */
+ int
+ ex_gtagselect(sp, ep, cmdp)
+ SCR *sp;
+ EXF *ep;
+ EXCMDARG *cmdp;
+ {
+ if (!F_ISSET(sp->frp, FR_GTAGSTMP)) {
+ msgq(sp, M_ERR, "illegal tag entry");
+ return (1);
+ }
+ cmdp->cmd = &cmds[C_TAG];
+ cmdp->flags |= (E_GTAGSELECT|E_FORCE);
+ return ex_tagpush(sp, ep, cmdp);
+ }
+
+ /*
+ * should_delete --
+ * 1: should delete, 0: should not delete
+ */
+ int
+ should_delete(gtagstmp)
+ char *gtagstmp;
+ {
+ SCR *sp;
+ TAG *tp;
+ int tagcnt = 0;
+
+ /* make sure */
+ if (strncmp(gtagstmp, _PATH_GTAGSTMP, strlen(_PATH_GTAGSTMP)))
+ return 0;
+ /* this gtag is generated by -t option. don't delete here */
+ if (__global_list->gtagstmp && !strcmp(gtagstmp, __global_list->gtagstmp))
+ return 0;
+
+ for (sp = __global_list->dq.cqh_first; sp != (void *)&__global_list->dq; sp = sp->q.cqe_next) {
+ if (!EXP(sp))
+ continue;
+ for (tp = EXP(sp)->tagq.tqh_first; tp != NULL; tp = tp->q.tqe_next) {
+ if (!tp->frp || !F_ISSET(tp->frp, FR_GTAGSTMP))
+ continue;
+ if (!strcmp(tp->frp->name, gtagstmp))
+ ++tagcnt;
+ }
+ }
+ if (tagcnt == 1)
+ return 1;
+ if (tagcnt > 1)
+ return 0;
+ /* IMPOSSIBLE */
+ return 0;
+ }
+ #endif
+
/*
* ex_tagfirst --
* The tag code can be entered from main, i.e. "vi -t tag".
***************
*** 86,96 ****
--- 298,317 ----
u_int flags;
int sval;
char *p, *tag, *name, *search;
+ #ifdef GTAGS
+ int gtagselect = 0;
+ #endif
/* Taglength may limit the number of characters. */
if ((tl = O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(tagarg) > tl)
tagarg[tl] = '\0';
+ #ifdef GTAGS
+ if (O_ISSET(sp, O_GTAGSMODE)) {
+ if (gtag_get(sp, 0, &gtagselect, tagarg, &tag, &name, &search))
+ return (1);
+ } else
+ #endif
/* Get the tag information. */
if (tag_get(sp, tagarg, &tag, &name, &search))
return (1);
***************
*** 106,111 ****
--- 327,336 ----
* The historic tags file format (from a long, long time ago...)
* used a line number, not a search string. I got complaints, so
* people are still using the format.
+ #ifdef GTAGS
+ * Yes, gtags use the old format. Search string is very flexible
+ * but is not suitable to treat duplicate entries.
+ #endif
*/
if (isdigit(search[0])) {
m.lno = atoi(search);
***************
*** 132,137 ****
--- 357,371 ----
frp->lno = m.lno;
frp->cno = m.cno;
F_SET(frp, FR_CURSORSET);
+ #ifdef GTAGS
+ if (gtagselect) {
+ F_SET(frp, FR_GTAGSTMP);
+ if (!(sp->gp->gtagstmp = strdup(name))) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+ }
+ #endif
/* Might as well make this the default tag. */
if ((EXP(sp)->tlast = strdup(tagarg)) == NULL) {
***************
*** 142,153 ****
--- 376,399 ----
}
/* Free a tag or tagf structure from a queue. */
+ #ifdef GTAGS
#define FREETAG(tp) { \
+ if (F_ISSET(tp->frp, FR_GTAGSTMP)) \
+ if (should_delete(tp->frp->name)) \
+ unlink(tp->frp->name); \
TAILQ_REMOVE(&exp->tagq, (tp), q); \
if ((tp)->search != NULL) \
free((tp)->search); \
FREE((tp), sizeof(TAGF)); \
}
+ #else
+ #define FREETAG(tp) { \
+ TAILQ_REMOVE(&exp->tagq, (tp), q); \
+ if ((tp)->search != NULL) \
+ free((tp)->search); \
+ FREE((tp), sizeof(TAGF)); \
+ }
+ #endif
#define FREETAGF(tfp) { \
TAILQ_REMOVE(&exp->tagfq, (tfp), q); \
free((tfp)->name); \
***************
*** 182,189 ****
--- 428,464 ----
int sval;
long tl;
char *name, *p, *search, *tag;
+ #ifdef GTAGS
+ int gtagselect = 0;
+ char *line;
+ size_t len;
+ char tagbuf[80], namebuf[200], linebuf[10];
+ #endif
exp = EXP(sp);
+ #ifdef GTAGS
+ /*
+ * Enter from gtag select mode.
+ * get tag information from current line.
+ */
+ if (F_ISSET(cmdp, E_GTAGSELECT)) {
+ if ((line = file_gline(sp, ep, sp->lno, &len)) == NULL) {
+ GETLINE_ERR(sp, sp->lno);
+ return (1);
+ }
+ if (getentry(line, tagbuf, namebuf, linebuf) == 0) {
+ msgq(sp, M_ERR, "illegal tag entry");
+ return (1);
+ }
+ if (!(tag = strdup(tagbuf))) {
+ msgq(sp, M_SYSERR, NULL);
+ return (1);
+ }
+ name = namebuf;
+ search = linebuf;
+ goto getfref;
+ }
+ #endif
switch (cmdp->argc) {
case 1:
if (exp->tlast != NULL)
***************
*** 207,216 ****
--- 482,504 ----
if ((tl = O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(exp->tlast) > tl)
exp->tlast[tl] = '\0';
+ #ifdef GTAGS
+ if (O_ISSET(sp, O_GTAGSMODE)) {
+ if (gtag_get(sp, F_ISSET(cmdp->cmd, E_REFERENCE), &gtagselect,
+ exp->tlast, &tag, &name, &search))
+ return (1);
+ } else if (F_ISSET(cmdp->cmd, E_REFERENCE)) {
+ msgq(sp, M_ERR, "Please set gtagsmode");
+ return (1);
+ } else
+ #endif
/* Get the tag information. */
if (tag_get(sp, exp->tlast, &tag, &name, &search))
return (1);
+ #ifdef GTAGS
+ getfref:
+ #endif
/* Get the (possibly new) FREF structure. */
if ((frp = file_add(sp, name)) == NULL)
goto err;
***************
*** 305,310 ****
--- 593,603 ----
sp->cno = m.cno;
break;
}
+ #ifdef GTAGS
+ if (gtagselect) {
+ F_SET(frp, FR_GTAGSTMP);
+ }
+ #endif
return (0);
}
***************
*** 490,495 ****
--- 783,793 ----
for (cnt = 1, tp = exp->tagq.tqh_first; tp != NULL;
++cnt, tp = tp->q.tqe_next) {
len = strlen(name = tp->frp->name); /* The original name. */
+ #ifdef GTAGS
+ if (F_ISSET(tp->frp, FR_GTAGSTMP)) {
+ (void)ex_printf(EXCOOKIE, "%2d [GTAGS]\n", cnt);
+ } else
+ #endif
if (len > maxlen || len + tp->slen > sp->cols)
if (tp == NULL || tp->search == NULL)
(void)ex_printf(EXCOOKIE,
diff -c -r -N /usr/src/usr.bin/vi/ex/excmd.c ./ex/excmd.c
*** /usr/src/usr.bin/vi/ex/excmd.c Thu Aug 18 10:13:29 1994
--- ./ex/excmd.c Sat Dec 14 11:54:15 1996
***************
*** 319,324 ****
--- 319,331 ----
"!",
"rew[ind][!]",
"re-edit all the files in the file argument list"},
+ #ifdef GTAGS
+ /* C_RTAG */
+ {"rtag", ex_tagpush, E_NOGLOBAL|E_REFERENCE,
+ "!w1o",
+ "rta[g][!] [string]",
+ "edit the file containing the tag"},
+ #endif
/* C_SUBSTITUTE */
{"substitute", ex_substitute, E_ADDR2|E_NORC,
"s",
***************
*** 329,334 ****
--- 336,348 ----
"!f1o",
"sc[ript][!] [file]",
"run a shell in a screen"},
+ #ifdef GTAGS
+ /* C_GTAGSELECT */
+ {"select", ex_gtagselect, E_NOGLOBAL,
+ "",
+ "sel[ect]",
+ "edit the file containing the tag"},
+ #endif
/* C_SET */
{"set", ex_set, E_NOGLOBAL,
"wN",
diff -c -r -N /usr/src/usr.bin/vi/ex/excmd.h.stub ./ex/excmd.h.stub
*** /usr/src/usr.bin/vi/ex/excmd.h.stub Wed Aug 17 08:36:28 1994
--- ./ex/excmd.h.stub Sat Dec 14 11:54:15 1996
***************
*** 69,74 ****
--- 69,79 ----
#define E_NORC 0x0800000 /* Not from a .exrc or EXINIT. */
#define E_ZERO 0x1000000 /* 0 is a legal addr1. */
#define E_ZERODEF 0x2000000 /* 0 is default addr1 of empty files. */
+
+ #ifdef GTAGS
+ #define E_REFERENCE 0x4000000 /* locate function references */
+ #define E_GTAGSELECT 0x8000000 /* current line is gtags entry */
+ #endif
u_int32_t flags;
char *syntax; /* Syntax script. */
char *usage; /* Usage line. */
***************
*** 234,239 ****
--- 239,245 ----
EXPROTO(ex_fg);
EXPROTO(ex_file);
EXPROTO(ex_global);
+ EXPROTO(ex_gtagselect);
EXPROTO(ex_help);
EXPROTO(ex_insert);
EXPROTO(ex_join);
diff -c -r -N /usr/src/usr.bin/vi/svi/svi_refresh.c ./svi/svi_refresh.c
*** /usr/src/usr.bin/vi/svi/svi_refresh.c Tue May 30 15:35:56 1995
--- ./svi/svi_refresh.c Sat Dec 14 11:54:16 1996
***************
*** 725,731 ****
--- 725,736 ----
EXF *ep;
{
size_t cols, curlen, endpoint, len, midpoint;
+ #ifdef GTAGS
+ char *p, buf[30];
+ recno_t last;
+ #else
char *p, buf[20];
+ #endif
/* Clear the mode line. */
MOVE(sp, INFOLINE(sp), 0);
***************
*** 746,751 ****
--- 751,765 ----
curlen = 0;
if (sp->q.cqe_next != (void *)&sp->gp->dq) {
+ #ifdef GTAGS
+ if (F_ISSET(sp->frp, FR_GTAGSTMP)) {
+ if (file_lline(sp, ep, &last)) {
+ return (1);
+ }
+ sprintf(buf, "[GTAGS SELECT MODE] %d lines", last);
+ p = buf;
+ } else {
+ #endif
for (p = sp->frp->name; *p != '\0'; ++p);
while (--p > sp->frp->name) {
if (*p == '/') {
***************
*** 758,764 ****
break;
}
}
!
MOVE(sp, INFOLINE(sp), 0);
standout();
for (; *p != '\0'; ++p)
--- 772,780 ----
break;
}
}
! #ifdef GTAGS
! }
! #endif
MOVE(sp, INFOLINE(sp), 0);
standout();
for (; *p != '\0'; ++p)
diff -c -r -N /usr/src/usr.bin/vi/vi/v_ex.c ./vi/v_ex.c
*** /usr/src/usr.bin/vi/vi/v_ex.c Thu Aug 18 10:15:03 1994
--- ./vi/v_ex.c Sat Dec 14 11:54:16 1996
***************
*** 298,303 ****
--- 298,308 ----
ARGS *ap[2], a;
EXCMDARG cmd;
+ #ifdef GTAGS
+ if (O_ISSET(sp, O_GTAGSMODE) && vp->m_start.cno == 0)
+ excmd(&cmd, C_RTAG, 0, OOBLNO, 0, 0, ap, &a, vp->keyword);
+ else
+ #endif
excmd(&cmd, C_TAG, 0, OOBLNO, 0, 0, ap, &a, vp->keyword);
return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
}
diff -c -r -N /usr/src/usr.bin/vi/vi/v_scroll.c ./vi/v_scroll.c
*** /usr/src/usr.bin/vi/vi/v_scroll.c Thu Aug 18 10:15:15 1994
--- ./vi/v_scroll.c Sat Dec 14 11:54:16 1996
***************
*** 255,260 ****
--- 255,269 ----
EXF *ep;
VICMDARG *vp;
{
+ #ifdef GTAGS
+ EXCMDARG cmd;
+
+ if (F_ISSET(sp->frp, FR_GTAGSTMP)) {
+ memset(&cmd, 0, sizeof(EXCMDARG));
+ cmd.cmd = &cmds[C_GTAGSELECT];
+ return (sp->s_ex_cmd(sp, ep, &cmd, &vp->m_final));
+ }
+ #endif
/*
* If it's a script window, exec the line,
* otherwise it's the same as v_down().

View File

@ -0,0 +1,664 @@
diff -c -r -N /usr/local/src/nvi-1.79/build/Makefile.in ./build/Makefile.in
*** /usr/local/src/nvi-1.79/build/Makefile.in Wed Oct 23 22:43:38 1996
--- ./build/Makefile.in Wed Apr 16 21:20:09 1997
***************
*** 3,9 ****
srcdir= @srcdir@/..
CC= @CC@
OPTFLAG=@OPTFLAG@
! CFLAGS= -c $(OPTFLAG) @CFLAGS@ -I. -I$(srcdir)/include @CPPFLAGS@
LDFLAGS=@LDFLAGS@
PERL= @vi_cv_path_perl@
PERLLIB=@vi_cv_perllib@
--- 3,9 ----
srcdir= @srcdir@/..
CC= @CC@
OPTFLAG=@OPTFLAG@
! CFLAGS= -c $(OPTFLAG) @CFLAGS@ -I. -I$(srcdir)/include @CPPFLAGS@ -DGTAGS
LDFLAGS=@LDFLAGS@
PERL= @vi_cv_path_perl@
PERLLIB=@vi_cv_perllib@
diff -c -r -N /usr/local/src/nvi-1.79/common/main.c ./common/main.c
*** /usr/local/src/nvi-1.79/common/main.c Sat Oct 12 07:28:28 1996
--- ./common/main.c Wed Apr 16 21:20:09 1997
***************
*** 64,69 ****
--- 64,72 ----
size_t len;
u_int flags;
int ch, flagchk, lflag, secure, startup, readonly, rval, silent;
+ #ifdef GTAGS
+ int gtags = 0;
+ #endif
char *tag_f, *wsizearg, path[256];
/* Initialize the busy routine, if not defined by the screen. */
***************
*** 113,123 ****
--- 116,134 ----
/* Set the file snapshot flag. */
F_SET(gp, G_SNAPSHOT);
+ #ifdef GTAGS
+ #ifdef DEBUG
+ while ((ch = getopt(argc, argv, "c:D:eFGlRrSsT:t:vw:")) != EOF)
+ #else
+ while ((ch = getopt(argc, argv, "c:eFGlRrSst:vw:")) != EOF)
+ #endif
+ #else
#ifdef DEBUG
while ((ch = getopt(argc, argv, "c:D:eFlRrSsT:t:vw:")) != EOF)
#else
while ((ch = getopt(argc, argv, "c:eFlRrSst:vw:")) != EOF)
#endif
+ #endif
switch (ch) {
case 'c': /* Run the command. */
/*
***************
*** 154,159 ****
--- 165,175 ----
case 'F': /* No snapshot. */
F_CLR(gp, G_SNAPSHOT);
break;
+ #ifdef GTAGS
+ case 'G': /* gtags mode. */
+ gtags = 1;
+ break;
+ #endif
case 'l': /* Set lisp, showmatch options. */
lflag = 1;
break;
***************
*** 252,257 ****
--- 268,277 ----
}
if (readonly)
*oargp++ = O_READONLY;
+ #ifdef GTAGS
+ if (gtags)
+ *oargp++ = O_GTAGSMODE;
+ #endif
if (secure)
*oargp++ = O_SECURE;
*oargp = -1; /* Options initialization. */
diff -c -r -N /usr/local/src/nvi-1.79/common/options.c ./common/options.c
*** /usr/local/src/nvi-1.79/common/options.c Tue Oct 15 03:56:29 1996
--- ./common/options.c Wed Apr 16 21:20:09 1997
***************
*** 80,85 ****
--- 80,89 ----
{"filec", NULL, OPT_STR, 0},
/* O_FLASH HPUX */
{"flash", NULL, OPT_1BOOL, 0},
+ #ifdef GTAGS
+ /* O_GTAGSMODE FreeBSD2.2 */
+ {"gtagsmode", NULL, OPT_0BOOL, 0},
+ #endif
/* O_HARDTABS 4BSD */
{"hardtabs", NULL, OPT_NUM, 0},
/* O_ICLOWER 4.4BSD */
***************
*** 244,249 ****
--- 248,256 ----
{"eb", O_ERRORBELLS}, /* 4BSD */
{"ed", O_EDCOMPATIBLE}, /* 4BSD */
{"ex", O_EXRC}, /* System V (undocumented) */
+ #ifdef GTAGS
+ {"gt", O_GTAGSMODE}, /* FreeBSD2.2 */
+ #endif
{"ht", O_HARDTABS}, /* 4BSD */
{"ic", O_IGNORECASE}, /* 4BSD */
{"li", O_LINES}, /* 4.4BSD */
diff -c -r -N /usr/local/src/nvi-1.79/docs/USD.doc/vi.man/vi.1 ./docs/USD.doc/vi.man/vi.1
*** /usr/local/src/nvi-1.79/docs/USD.doc/vi.man/vi.1 Fri Oct 11 10:34:05 1996
--- ./docs/USD.doc/vi.man/vi.1 Wed Apr 16 21:20:09 1997
***************
*** 17,23 ****
.SH SYNOPSIS
.B ex
[\c
! .B -eFRrSsv\c
] [\c
.BI -c " cmd"\c
] [\c
--- 17,23 ----
.SH SYNOPSIS
.B ex
[\c
! .B -eFGRrSsv\c
] [\c
.BI -c " cmd"\c
] [\c
***************
*** 28,34 ****
.br
.B vi
[\c
! .B -eFlRrSv\c
] [\c
.BI -c " cmd"\c
] [\c
--- 28,34 ----
.br
.B vi
[\c
! .B -eFGlRrSv\c
] [\c
.BI -c " cmd"\c
] [\c
***************
*** 39,45 ****
.br
.B view
[\c
! .B -eFRrSv\c
] [\c
.BI -c " cmd"\c
] [\c
--- 39,45 ----
.br
.B view
[\c
! .B -eFGRrSv\c
] [\c
.BI -c " cmd"\c
] [\c
***************
*** 121,126 ****
--- 121,129 ----
.B \-l
Start editing with the lisp and showmatch options set.
.TP
+ .B \-G
+ Start editing in gtags mode, as if the gtagsmode option was set.
+ .TP
.B \-R
Start editing in read-only mode, as if the command name was
.IR view ,
***************
*** 429,434 ****
--- 432,439 ----
.TP
.B "<control-]>"
Push a tag reference onto the tag stack.
+ In gtagsmode, if at the first column of line,
+ locate function references otherwise function definitions.
.TP
.B "<control-^>"
Switch to the most recently edited file.
***************
*** 940,945 ****
--- 945,953 ----
.B "rew[ind][!]"
Rewind the argument list.
.TP
+ .B "rta[g][!] tagstring"
+ Edit the file refering the specified tag. (Only in gtagsmode)
+ .TP
.B "se[t] [option[=[value]] ...] [nooption ...] [option? ...] [all]"
Display or set editor options.
.TP
***************
*** 1109,1114 ****
--- 1117,1125 ----
.TP
.B "flash [on]"
Flash the screen instead of beeping the keyboard on error.
+ .TP
+ .B "gtagsmode, gt [off]"
+ Use GTAGS and GRTAGS instead of tags.
.TP
.B "hardtabs, ht [8]"
Set the spacing between hardware tab settings.
diff -c -r -N /usr/local/src/nvi-1.79/ex/ex.h ./ex/ex.h
*** /usr/local/src/nvi-1.79/ex/ex.h Tue Aug 13 09:24:00 1996
--- ./ex/ex.h Wed Apr 16 21:20:09 1997
***************
*** 152,157 ****
--- 152,160 ----
#define E_SEARCH_WMSG 0x01000000 /* Display search-wrapped message. */
#define E_USELASTCMD 0x02000000 /* Use the last command. */
#define E_VISEARCH 0x04000000 /* It's really a vi search command. */
+ #ifdef GTAGS
+ #define E_REFERENCE 0x08000000 /* locate function references */
+ #endif
u_int32_t flags; /* Current flags. */
};
diff -c -r -N /usr/local/src/nvi-1.79/ex/ex_cmd.c ./ex/ex_cmd.c
*** /usr/local/src/nvi-1.79/ex/ex_cmd.c Wed Oct 23 22:31:01 1996
--- ./ex/ex_cmd.c Wed Apr 16 21:20:09 1997
***************
*** 302,307 ****
--- 302,314 ----
"!",
"rew[ind][!]",
"re-edit all the files in the file argument list"},
+ #ifdef GTAGS
+ /* C_RTAG */
+ {"rtag", ex_rtag_push, E_NEWSCREEN,
+ "!w1o",
+ "[Rr]ta[g][!] [string]",
+ "edit the file containing the tag"},
+ #endif
/*
* !!!
* Adding new commands starting with 's' may break the substitute command code
diff -c -r -N /usr/local/src/nvi-1.79/ex/ex_tag.c ./ex/ex_tag.c
*** /usr/local/src/nvi-1.79/ex/ex_tag.c Mon Sep 16 05:02:43 1996
--- ./ex/ex_tag.c Wed Apr 16 21:20:09 1997
***************
*** 46,51 ****
--- 46,55 ----
static int compare __P((char *, char *, char *));
static void ctag_file __P((SCR *, TAGF *, char *, char **, size_t *));
static int ctag_search __P((SCR *, char *, size_t, char *));
+ #ifdef GTAGS
+ static int getentry __P((char *, char *, char *, char *));
+ static TAGQ *gtag_slist __P((SCR *, char *, int));
+ #endif
static int ctag_sfile __P((SCR *, TAGF *, TAGQ *, char *));
static TAGQ *ctag_slist __P((SCR *, char *));
static char *linear_search __P((char *, char *, char *));
***************
*** 89,94 ****
--- 93,117 ----
return (0);
}
+ #ifdef GTAGS
+ /*
+ * ex_rtag_push -- ^]
+ * :rtag[!] [string]
+ *
+ * Enter a new TAGQ context based on a ctag string.
+ *
+ * PUBLIC: int ex_rtag_push __P((SCR *, EXCMD *));
+ */
+ int
+ ex_rtag_push(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+ {
+ F_SET(cmdp, E_REFERENCE);
+ return ex_tag_push(sp, cmdp);
+ }
+ #endif
+
/*
* ex_tag_push -- ^]
* :tag[!] [string]
***************
*** 138,143 ****
--- 161,172 ----
}
/* Get the tag information. */
+ #ifdef GTAGS
+ if (O_ISSET(sp, O_GTAGSMODE)) {
+ if ((tqp = gtag_slist(sp, exp->tag_last, F_ISSET(cmdp, E_REFERENCE))) == NULL)
+ return (1);
+ } else
+ #endif
if ((tqp = ctag_slist(sp, exp->tag_last)) == NULL)
return (1);
***************
*** 969,974 ****
--- 998,1116 ----
return (0);
}
+ #ifdef GTAGS
+ /*
+ * getentry --
+ * get tag information from current line.
+ *
+ * gtags temporary file format.
+ * <tag> <lineno> <file> <image>
+ *
+ * sample.
+ * +------------------------------------------------
+ * |main 30 main.c main(argc, argv)
+ * |func 21 subr.c func(arg)
+ */
+ static int
+ getentry(buf, tag, file, line)
+ char *buf, *tag, *file, *line;
+ {
+ char *p;
+
+ p = tag;
+ while (*buf && !isspace(*buf)) /* tag name */
+ *p++ = *buf++;
+ *p = 0;
+ while (*buf && isspace(*buf)) /* skip blanks */
+ buf++;
+ p = line;
+ while (*buf && !isspace(*buf)) /* line no */
+ *p++ = *buf++;
+ *p = 0;
+ while (*buf && isspace(*buf)) /* skip blanks */
+ buf++;
+ p = file;
+ while (*buf && !isspace(*buf)) /* file name */
+ *p++ = *buf++;
+ *p = 0;
+
+ /* value check */
+ if (strlen(tag) && strlen(line) && strlen(file) && atoi(line) > 0)
+ return 1; /* OK */
+ return 0; /* ERROR */
+ }
+
+ /*
+ * gtag_slist --
+ * Search the list of tags files for a tag, and return tag queue.
+ */
+ static TAGQ *
+ gtag_slist(sp, tag, ref)
+ SCR *sp;
+ char *tag;
+ int ref;
+ {
+ EX_PRIVATE *exp;
+ TAGF *tfp;
+ TAGQ *tqp;
+ size_t len;
+ int echk;
+ TAG *tp;
+ static char name[80], file[200], line[10];
+ char command[200];
+ char buf[BUFSIZ+1];
+ FILE *fp;
+
+ /* Allocate and initialize the tag queue structure. */
+ len = strlen(tag);
+ CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
+ CIRCLEQ_INIT(&tqp->tagq);
+ tqp->tag = tqp->buf;
+ memcpy(tqp->tag, tag, (tqp->tlen = len) + 1);
+
+ /*
+ * Find the tag, only display missing file messages once, and
+ * then only if we didn't find the tag.
+ */
+ sprintf(command, "global -%s '%s'", ref ? "rx" : "x", tag);
+ if (fp = popen(command, "r")) {
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (buf[strlen(buf)-1] == '\n') /* chop(buf) */
+ buf[strlen(buf)-1] = 0;
+ else
+ while (fgetc(fp) != '\n')
+ ;
+ if (getentry(buf, name, file, line) == 0) {
+ echk = 1;
+ F_SET(tfp, TAGF_ERR);
+ break;
+ }
+ CALLOC_GOTO(sp, tp,
+ TAG *, 1, sizeof(TAG) + strlen(file) + 1 + strlen(line) + 1);
+ tp->fname = tp->buf;
+ strcpy(tp->fname, file);
+ tp->fnlen = strlen(file);
+ tp->search = tp->fname + tp->fnlen + 1;
+ strcpy(tp->search, line);
+ CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
+ }
+ pclose(fp);
+ }
+
+ /* Check to see if we found anything. */
+ if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
+ msgq_str(sp, M_ERR, tag, "162|%s: tag not found");
+ free(tqp);
+ return (NULL);
+ }
+
+ tqp->current = tqp->tagq.cqh_first;
+ return (tqp);
+
+ alloc_err:
+ return (NULL);
+ }
+ #endif
/*
* ctag_slist --
* Search the list of tags files for a tag, and return tag queue.
diff -c -r -N /usr/local/src/nvi-1.79/include/ex_def.h ./include/ex_def.h
*** /usr/local/src/nvi-1.79/include/ex_def.h Wed Oct 23 22:53:09 1996
--- ./include/ex_def.h Wed Apr 16 21:20:09 1997
***************
*** 47,78 ****
#define C_RECOVER 46
#define C_RESIZE 47
#define C_REWIND 48
! #define C_SUBSTITUTE 49
! #define C_SCRIPT 50
! #define C_SET 51
! #define C_SHELL 52
! #define C_SOURCE 53
! #define C_STOP 54
! #define C_SUSPEND 55
! #define C_T 56
! #define C_TAG 57
! #define C_TAGNEXT 58
! #define C_TAGPOP 59
! #define C_TAGPREV 60
! #define C_TAGTOP 61
! #define C_TCLCMD 62
! #define C_UNDO 63
! #define C_UNABBREVIATE 64
! #define C_UNMAP 65
! #define C_V 66
! #define C_VERSION 67
! #define C_VISUAL_EX 68
! #define C_VISUAL_VI 69
! #define C_VIUSAGE 70
! #define C_WRITE 71
! #define C_WN 72
! #define C_WQ 73
! #define C_XIT 74
! #define C_YANK 75
! #define C_Z 76
! #define C_SUBTILDE 77
--- 47,79 ----
#define C_RECOVER 46
#define C_RESIZE 47
#define C_REWIND 48
! #define C_RTAG 49
! #define C_SUBSTITUTE 50
! #define C_SCRIPT 51
! #define C_SET 52
! #define C_SHELL 53
! #define C_SOURCE 54
! #define C_STOP 55
! #define C_SUSPEND 56
! #define C_T 57
! #define C_TAG 58
! #define C_TAGNEXT 59
! #define C_TAGPOP 60
! #define C_TAGPREV 61
! #define C_TAGTOP 62
! #define C_TCLCMD 63
! #define C_UNDO 64
! #define C_UNABBREVIATE 65
! #define C_UNMAP 66
! #define C_V 67
! #define C_VERSION 68
! #define C_VISUAL_EX 69
! #define C_VISUAL_VI 70
! #define C_VIUSAGE 71
! #define C_WRITE 72
! #define C_WN 73
! #define C_WQ 74
! #define C_XIT 75
! #define C_YANK 76
! #define C_Z 77
! #define C_SUBTILDE 78
diff -c -r -N /usr/local/src/nvi-1.79/include/ex_extern.h ./include/ex_extern.h
*** /usr/local/src/nvi-1.79/include/ex_extern.h Wed Oct 23 22:53:10 1996
--- ./include/ex_extern.h Wed Apr 16 21:20:09 1997
***************
*** 89,94 ****
--- 89,95 ----
char *, size_t, char **, size_t *, regex_t *, u_int));
void re_error __P((SCR *, int, regex_t *));
int ex_tag_first __P((SCR *, char *));
+ int ex_rtag_push __P((SCR *, EXCMD *));
int ex_tag_push __P((SCR *, EXCMD *));
int ex_tag_next __P((SCR *, EXCMD *));
int ex_tag_prev __P((SCR *, EXCMD *));
diff -c -r -N /usr/local/src/nvi-1.79/include/options_def.h ./include/options_def.h
*** /usr/local/src/nvi-1.79/include/options_def.h Wed Oct 23 22:53:10 1996
--- ./include/options_def.h Wed Apr 16 21:20:09 1997
***************
*** 16,79 ****
#define O_EXTENDED 15
#define O_FILEC 16
#define O_FLASH 17
! #define O_HARDTABS 18
! #define O_ICLOWER 19
! #define O_IGNORECASE 20
! #define O_KEYTIME 21
! #define O_LEFTRIGHT 22
! #define O_LINES 23
! #define O_LISP 24
! #define O_LIST 25
! #define O_LOCKFILES 26
! #define O_MAGIC 27
! #define O_MATCHTIME 28
! #define O_MESG 29
! #define O_MODELINE 30
! #define O_MSGCAT 31
! #define O_NOPRINT 32
! #define O_NUMBER 33
! #define O_OCTAL 34
! #define O_OPEN 35
! #define O_OPTIMIZE 36
! #define O_PARAGRAPHS 37
! #define O_PATH 38
! #define O_PRINT 39
! #define O_PROMPT 40
! #define O_READONLY 41
! #define O_RECDIR 42
! #define O_REDRAW 43
! #define O_REMAP 44
! #define O_REPORT 45
! #define O_RULER 46
! #define O_SCROLL 47
! #define O_SEARCHINCR 48
! #define O_SECTIONS 49
! #define O_SECURE 50
! #define O_SHELL 51
! #define O_SHELLMETA 52
! #define O_SHIFTWIDTH 53
! #define O_SHOWMATCH 54
! #define O_SHOWMODE 55
! #define O_SIDESCROLL 56
! #define O_SLOWOPEN 57
! #define O_SOURCEANY 58
! #define O_TABSTOP 59
! #define O_TAGLENGTH 60
! #define O_TAGS 61
! #define O_TERM 62
! #define O_TERSE 63
! #define O_TILDEOP 64
! #define O_TIMEOUT 65
! #define O_TTYWERASE 66
! #define O_VERBOSE 67
! #define O_W1200 68
! #define O_W300 69
! #define O_W9600 70
! #define O_WARN 71
! #define O_WINDOW 72
! #define O_WINDOWNAME 73
! #define O_WRAPLEN 74
! #define O_WRAPMARGIN 75
! #define O_WRAPSCAN 76
! #define O_WRITEANY 77
! #define O_OPTIONCOUNT 78
--- 16,80 ----
#define O_EXTENDED 15
#define O_FILEC 16
#define O_FLASH 17
! #define O_GTAGSMODE 18
! #define O_HARDTABS 19
! #define O_ICLOWER 20
! #define O_IGNORECASE 21
! #define O_KEYTIME 22
! #define O_LEFTRIGHT 23
! #define O_LINES 24
! #define O_LISP 25
! #define O_LIST 26
! #define O_LOCKFILES 27
! #define O_MAGIC 28
! #define O_MATCHTIME 29
! #define O_MESG 30
! #define O_MODELINE 31
! #define O_MSGCAT 32
! #define O_NOPRINT 33
! #define O_NUMBER 34
! #define O_OCTAL 35
! #define O_OPEN 36
! #define O_OPTIMIZE 37
! #define O_PARAGRAPHS 38
! #define O_PATH 39
! #define O_PRINT 40
! #define O_PROMPT 41
! #define O_READONLY 42
! #define O_RECDIR 43
! #define O_REDRAW 44
! #define O_REMAP 45
! #define O_REPORT 46
! #define O_RULER 47
! #define O_SCROLL 48
! #define O_SEARCHINCR 49
! #define O_SECTIONS 50
! #define O_SECURE 51
! #define O_SHELL 52
! #define O_SHELLMETA 53
! #define O_SHIFTWIDTH 54
! #define O_SHOWMATCH 55
! #define O_SHOWMODE 56
! #define O_SIDESCROLL 57
! #define O_SLOWOPEN 58
! #define O_SOURCEANY 59
! #define O_TABSTOP 60
! #define O_TAGLENGTH 61
! #define O_TAGS 62
! #define O_TERM 63
! #define O_TERSE 64
! #define O_TILDEOP 65
! #define O_TIMEOUT 66
! #define O_TTYWERASE 67
! #define O_VERBOSE 68
! #define O_W1200 69
! #define O_W300 70
! #define O_W9600 71
! #define O_WARN 72
! #define O_WINDOW 73
! #define O_WINDOWNAME 74
! #define O_WRAPLEN 75
! #define O_WRAPMARGIN 76
! #define O_WRAPSCAN 77
! #define O_WRITEANY 78
! #define O_OPTIONCOUNT 79
diff -c -r -N /usr/local/src/nvi-1.79/vi/v_ex.c ./vi/v_ex.c
*** /usr/local/src/nvi-1.79/vi/v_ex.c Mon Sep 16 05:03:02 1996
--- ./vi/v_ex.c Wed Apr 16 21:20:09 1997
***************
*** 226,231 ****
--- 226,236 ----
ARGS *ap[2], a;
EXCMD cmd;
+ #ifdef GTAGS
+ if (O_ISSET(sp, O_GTAGSMODE) && vp->m_start.cno == 0)
+ ex_cinit(&cmd, C_RTAG, 0, OOBLNO, 0, 0, ap);
+ else
+ #endif
ex_cinit(&cmd, C_TAG, 0, OOBLNO, 0, 0, ap);
ex_cadd(&cmd, &a, VIP(sp)->keyw, strlen(VIP(sp)->keyw));
return (v_exec_ex(sp, vp, &cmd));

View File

@ -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>

View File

@ -0,0 +1,10 @@
# @(#)Makefile 29-Dec-96
PROG = systags
BINDIR = /usr/bin
all:
install:
cp $(PROG).sh $(BINDIR)/$(PROG)
chmod 755 $(BINDIR)/$(PROG)
clean:

View File

@ -0,0 +1,87 @@
#!/bin/sh
#
# Copyright (c) 1997 Shigio Yamaguchi. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Shigio Yamaguchi.
# 4. Neither the name of the author nor the names of any co-contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# systags.sh 7-Jul-97
#
# script to make hypertext of kernel source.
# supporting FreeBSD and Linux.
#
case $1 in
-n) nflag=1; shift;;
esac
case $1 in
"") dir=.;;
*) dir=$1;;
esac
#
# get release number from source tree.
#
if [ -f conf/newvers.sh ]; then
os=FreeBSD
release=`awk -F= '/^RELEASE=/ {print $2}' < conf/newvers.sh`
elif [ -f Makefile ] && grep '^vmlinux:' Makefile >/dev/null; then
os=Linux
version=`awk -F= '/^VERSION *=/ {print $2}' < Makefile`
patchlevel=`awk -F= '/^PATCHLEVEL *=/ {print $2}' < Makefile`
sublevel=`awk -F= '/^SUBLEVEL *=/ {print $2}' < Makefile`
release=`echo "$version.$patchlevel.$sublevel" | tr -d ' '`
fi
#
# remove old files
#
case $nflag in
1) echo "rm -rf $dir/htags.log $dir/GTAGS $dir/GRTAGS $dir/HTML";;
*) rm -rf $dir/htags.log $dir/GTAGS $dir/GRTAGS $dir/HTML;;
esac
#
# make global database(GTAGS, GRTAGS).
#
case $nflag in
1) echo "gtags -se $dir";;
*) gtags -se $dir;;
esac
case $? in
0) ;;
*) exit 1;;
esac
#
# make hypertext.
# (please replace this title with a suitable one.)
#
case $os$release in
"") program=`/bin/pwd | sed 's/.*\///'`
title="Welcome to $program source tour!";;
*) title="Welcome to $os $release kernel source tour!";;
esac
case $nflag in
1) echo "htags -fnvat '$title' -d $dir $dir > $dir/htags.log 2>&1";;
*) htags -fnvat "$title" -d $dir $dir> $dir/htags.log 2>&1;;
esac