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