diff options
author | jkh <jkh@FreeBSD.org> | 1997-04-15 12:30:38 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1997-04-15 12:30:38 +0000 |
commit | 29e9ef05d0c260d4547756e194224176c57611ec (patch) | |
tree | fec9d4361eb5f7d1b15c25c7d963be41051af145 /usr.bin/global | |
download | FreeBSD-src-29e9ef05d0c260d4547756e194224176c57611ec.zip FreeBSD-src-29e9ef05d0c260d4547756e194224176c57611ec.tar.gz |
Shigio Yamaguchi's global tags package. The infrastructure support
for this is already in place, so "make tags" (or "make tags HTML=yes")
should work after your next make world.
Submitted by: Shigio Yamaguchi <shigio@wafu.netgate.net>
Diffstat (limited to 'usr.bin/global')
31 files changed, 5260 insertions, 0 deletions
diff --git a/usr.bin/global/HISTORY b/usr.bin/global/HISTORY new file mode 100644 index 0000000..e591c74 --- /dev/null +++ b/usr.bin/global/HISTORY @@ -0,0 +1,131 @@ +GLOBAL history +-------------- + +version 1.0 initial version [21-Apr-96] + +version 1.1 only bugfix [2-May-96] + + [fixed bug] + global - makes corrupted path name by conversion error. + - description of exit code in online manual is mistaken. + btreeop - cannot treat a long line over BUFSIZ. With the result + that gtags fails. + extended ctags - when using -r option, considers a reserved word + to be a function name. With the result that GRTAGS becomes + too large. + +version 1.2 mainly unification of files [7-Jun-96] + + [changed] + extended ctags + - change to use bsearch(3) for searching reserved words. + - change to consider '__P' as a reserved word. + - unify the original patch (included in version1.0) and + the bugfix patch (included in version1.1). + extended vi + - unify the VI entended patch. + +version 1.3 support of GTAGSLIBPATH [28-Jul-96] + + [changed] + global - search in not only a source tree but also library paths + specified by environment variable GTAGSLIBPATH. + extended ctags + - change print format a little when -x option + +version 1.4 support of yacc source file [26-Oct-96] + + [changed] + extended ctags + - support of yacc source file. + - this version of ctags is NOT COMPATIBLE with original one. + * search all part of a yacc file for C functions. + (original only 3rd part) + * no longer considers a yacc rule to be an object. + +version 1.5 hypertext generator [12-Dec-96] + + [fixed bug] + gtags - doesn't skip 'y.tab.c'.(we should treat only *.y) + extended vi + - free stack memory. free(3) in FreeBSD 2.1.5R seems to + show a warning message when receive stack address. + So it spoils the screen. + [added] + htags - new command (hypertext generator of C source file) + gtags - error check code added. + +version 1.6 support of 1.76 nvi and reconstruction for other OS [21-Jan-97] + + [changed] + htags - cease using <BLOCKQUOTE> because lynx doesn't understand it. + global,htags + - replace 'sort -u' with 'sort | uniq' for compatibility reason. + [fixed bug] + global - makes illegal path name when using GTAGSLIBPATH. + gtags - error message mistaken. + [added] + nvi-1.76.diff + - patch for nvi 1.76 to make extended vi. + gctags - this is the same with extended ctags in older version. + now GLOBAL includes BSD ctags in it. so no longer has + patch file (ctags.diff). + (I brought original ctags from FreeBSD 2.1.5R) + global - -a option added. + +version 1.7 make suitable for large project (mainly FreeBSD kernel) [17-Feb-97] + + [changed] + htags - htags no longer makes frame.html. Index.html offers frame + function too. + - works MUCH faster than previous version. + [fixed bug] + htags - string 'param' follows '&' means specific charactor in hypertext. + So, changed internal separator from '&' to '|'. + [added] + gtags - -s option added. If specified, gtags extract ENTRY() and + ALTENTRY() from *.[sS] files. + htags - supports one level nested index. It's always valid for file + index when directories found, and valid for function index + only when -a option specified. + - -v and -t option added. + systags.sh + - script to make all tags (GTAGS,GRTAGS,HTML) for kernel source. + (it is only for FreeBSD and Linux) + +version 1.8 fix some bugs, add options and make more portable [5-Apr-97] + + [changed] + gctags, btreeop, Makefile + - modify for generic UNIX (Linux, Solaris) + - modify to quiet compiler. + + Many thanks to + A.E. Brouwer + Oleg Checkulaev + Emile Heyns + + gctags - modify to treat '\r' at the end of line. + htags - changed internal separator from '|' to ' '. + because some OS cannot treat '|' in a path. + [fixed bug] + htags - regard a part of path in #include as a reserved word. + - generate illegal links when same tags exist in a line. + - insufficient comment detection. + gctags - regard function name as a definition in extern statement. + - skip macro(no argment) body when -r specified. + gctags, htags + - regard 'entry' as a reserved word. + [added] + global - -c (complete) option added. + htags - -d tagdir option added. + - -w option added. + +version 1.81 make global to understand 'obj' directory and bug fix. [14-Apr-97] + + [fixed bug] + extended vi + - doesn't hand '\' in a pattern to global. + [changed] + global + - can find tag file in obj directory. diff --git a/usr.bin/global/MANIFEST b/usr.bin/global/MANIFEST new file mode 100644 index 0000000..a03c42e --- /dev/null +++ b/usr.bin/global/MANIFEST @@ -0,0 +1,16 @@ +HISTORY Histroy of GLOBAL. +INSTALL Installation method +MANIFEST This file. +Makefile Makefile for generic UNIX(including BSD). +Makefile.bsd Makefile for BSD. +Makefile.inc A part of Makefile for BSD. +README Readme (introduction and usage). +VERSION Version number. +btreeop/ Btreeop command directory. +gctags/ Gctags command directory (extended ctags). +global/ Global command directory. +gtags/ Gtags command directory. +htags/ Htags command directory. +systags/ Script for kernel. +nvi-1.34.diff Patch for nvi 1.34. +nvi-1.76.diff Patch for nvi 1.76. diff --git a/usr.bin/global/Makefile b/usr.bin/global/Makefile new file mode 100644 index 0000000..2eb181e --- /dev/null +++ b/usr.bin/global/Makefile @@ -0,0 +1,3 @@ +SUBDIR= gctags global gtags btreeop htags systags + +.include <bsd.subdir.mk> diff --git a/usr.bin/global/Makefile.inc b/usr.bin/global/Makefile.inc new file mode 100644 index 0000000..c24c4b1 --- /dev/null +++ b/usr.bin/global/Makefile.inc @@ -0,0 +1 @@ +BINDIR?= /usr/bin diff --git a/usr.bin/global/README b/usr.bin/global/README new file mode 100644 index 0000000..4259637 --- /dev/null +++ b/usr.bin/global/README @@ -0,0 +1,527 @@ + + @@@@@@@- + @- @- + @- @- + @- @- @@@@@- @@@@@@- @@- @- + @- F o r a l l h a c h e r s. version 1.8 + @- @@@@@@-@- @- @- @@@@@- @- @- @- + @- @- @- @- @- @- @- @@@@@- @- + @- @- @- @- @- @- @-@- @- @- + @@@@@@@@- @@@@- @@@@@- @@@@@@-@@@- @@@@- @@@@@@- + + Shigio Yamaguchi 5-Apr-97 + + Copyright 1996, 1997 Shigio Yamaguchi All right resereved. + +GLOBAL is a browsing system for C and Yacc source code. +It brings benefits to all hackers. Enjoy! + + Contents + -------------------------------- + 0. Introduction + + 1. Global + + 1.1. Features + 1.2. Preparation + 1.3. Basic usage + 1.4. Applied usage + + 2. Extended vi using global + + 2.1. Features + 2.2. Preparation + 2.3. Basic usage + 2.4. Applied usage + + 3. Hypertext generator + + 3.1. Features + 3.2. Preparation + 3.3. Usage + 3.4. To make hypertext of kernel + -------------------------------- + +0. Introduction + +GLOBAL is a browsing system for C and Yacc source files. +You can locate the specified function in C source files and move there easily. +It is useful to hack a large project containing many subdirectories, +many '#ifdef' and many main() functions like MH, X or BSD kernel. + +It supports following environments. + + o shell command line(see '1. Global') + o vi editor(see '2. Extended vi using global') + o web browser(see '3. Hypertext generator') + +GLOBAL is consist of global(1), gtags(1), btreeop(1), gctags(1), htags(1) +and extended vi(1). + + * 'extended' means being entended for GLOBAL. + + * Btreeop and gctags are used internally, so you need not + understand about them. + +The extended vi is completely upper compatible with original one. +All the functions for GLOBAL are enabled only in 'gtagsmode'. + +------------------------------------------------------------------------------ + +1. Global + +1.1. Features + + o Global can find the locations of a specified function quickly. + o Global can locate not only function definitions but also function references. + o Global allows duplicate entries. + o Global can treat a source tree containing subdirectories and you can + get relative path of objects from anywhere within the tree. + o Global can understand perl's regular expression. + o Global can search in not only a source tree but also library paths. + o Global can treat yacc source file. + + I think these features are useful for a large project containing many + subdirectories, many '#ifdef' and many main() functions like MH. + +1.2. Preparation + + First of all, you must execute gtags(1) at the root of source tree. + For example, if you want to browse vi's source code, please do like this. + + % cd /usr/src/usr.bin/vi + % gtags + + Gtags traverse subdirectories and makes + two database at the root of source tree. + + % ls G*TAGS + GRTAGS GTAGS + + GTAGS - database for function definition + GRTAGS - database for function reference + + If you cannot find functions that should exist, please try -e option. + + % gtags -e + +1.3. Basic usage + + Please think of following source tree. + + ROOT/ <- the root of source tree (GTAGS,GRTAGS) + | + |- DIR1/ + | | + | |- fileA.c ..... +---------------+ + | | |main(){ | + | | | func1();| + | | | func2();| + | | |} | + | | +---------------+ + | | + | |- fileB.c ..... +---------------+ + | |func1(){ ... } | + | +---------------+ + |- DIR2/ + | + |- fileC.c ..... +---------------+ + |#ifdef X | + |func2(){ i++; }| + |#else | + |func2(){ i--; }| + |#endif | + |func3(){ | + | func1();| + |} | + +---------------+ + + You can get the relative path of your object from anywhere within + the source tree. + + % cd ROOT + % global func1 + DIR1/fileB.c <- func1() is defined in fileB.c + % cd DIR1 + % global func1 + fileB.c <- relative path from DIR1 + % cd ../DIR2 + % global func1 + ../DIR1/fileB.c <- relative path from DIR2 + + -r option locates function references. + + % global -r func2 + ../DIR1/fileA.c <- func2() is referred from fileA.c + + You can use perl's regular expression. + + % cd ROOT + % global 'func[1-3]' + DIR1/fileB.c <- func1, func2 and func3 are matched + DIR2/fileC.c + + -x option shows the detail. It's similar to ctags's -x option. + + % global func2 + DIR2/fileC.c + % global -x func2 + func2 2 DIR2/fileC.c func2(){ i++; } + func2 4 DIR2/fileC.c func2(){ i--; } + + -a option produces the absolute path name. + + % global -a func1 + /home/user/ROOT/DIR1/fileB.c + + You can edit files including specified function directly like this. + + % vi `global func1` <- edit fileB.c + + +1.4. Applied usage + + You can make multiple tag files. + For example, you can execute gtags at ROOT/, version1.0/ and version2.0/. + + ROOT/ <- the root of source tree (GTAGS,GRTAGS) + | + |- version1.0/ <- the root of version1.0 (GTAGS,GRTAGS) + | | + | |- file.c ..... +---------------+ + | |func1(){ i++; }| + | +---------------+ + | + |- version2.0/ <- the root of version2.0 (GTAGS,GRTAGS) + | + |- file.c ..... +---------------+ + |func1(){ i--; }| + +---------------+ + + When you are walking in version1.0 directory, global locates functions + only in version1.0. + + % cd ROOT/version1.0 + % global -x func1 + func1 1 file.c func1(){ i++; } + + When you are walking in version2.0, global locates functions only in + version2.0. + + % cd ROOT/version2.0 + % global -x func1 + func1 1 file.c func1(){ i--; } + + If you are at ROOT/ or you set GTAGSROOT environment variable to ROOT, + global locates functions in both version1.0 and version2.0 directories. + + % cd ROOT + % global -x func1 + func1 1 version1.0/file.c func1(){ i++; } + func1 1 version2.0/file.c func1(){ i--; } + + =-=-=-= + + There is another usage of GTAGSROOT. + If your source files are on a read only device like CDROM, you cannot + make database on the root of source tree. + In such case, please do the following. + + % mkdir /var/dbpath + % cd /cdrom/src <- the root of source tree + % gtags /var/dbpath <- make tag file in /var/dbpath + % setenv GTAGSROOT `pwd` + % setenv GTAGSDBPATH /var/dbpath + % global func + + =-=-=-= + + If you want to treat the references to a function that is not defined + in the source tree like a library function or system call, you can specify + library directories with the GTAGSLIBPATH environment variable. + You should execute gtags at each directory of the path. + If GTAGS is not found in a directory, global ignores it. + + % pwd + /develop/src/mh <- this is the source tree + % gtags + % ls G*TAGS + GRTAGS GTAGS + % global mhl + uip/mhlsbr.c <- mhl() is found + % global strlen <- strlen() is not found + % (cd /usr/src/lib; gtags) <- library source + % (cd /usr/src/sys; gtags) <- kernel source + % setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys + % global strlen + ../../../usr/src/lib/libc/string/strlen.c <- strlen() is found in library + % global access + ../../../usr/src/sys/kern/vfs_syscalls.c <- access() is found in kernel + + Of course, user program doesn't call kernel function directly, but + at least it is useful. + + =-=-=-= + + If you forget function name, you can use -c (complete) option. + + % global -c kmem <- maybe k..k.. kmem.. + kmem_alloc + kmem_alloc_pageable + kmem_alloc_wait + kmem_free + kmem_free_wakeup + kmem_init + kmem_malloc + kmem_suballoc <- This is what I need! + % global kmem_suballoc + ../vm/vm_kern.c + + You can use -c option with tcsh's complete command. + + % set funcs=(`global -c`) + % complete global 'n/*/$funcs/' + % global kmem_<TAB> + kmem_alloc kmem_alloc_wait kmem_free_wakeup kmem_malloc + kmem_alloc_pageable kmem_free kmem_init kmem_suballoc + % global kmem_s<TAB> + % global kmem_suballoc + ../vm/vm_kern.c + + * <TAB> means tab key or Ctrl-I. + + =-=-=-= + + If you want to browse many files in order, do the followings. + + % global -xr fork | awk '{printf "view +%s %s\n",$2,$3}' | tee /tmp/list + view +650 ../dev/aic7xxx/aic7xxx_asm.c + view +250 ibcs2/ibcs2_misc.c + view +401 linux/linux_misc.c + view +310 ../kern/init_main.c + view +318 ../kern/init_main.c + view +336 ../kern/init_main.c + view +351 ../kern/init_main.c + % sh !$ <- from now on, go to next tag with 'ZZ'. + +2. Extended vi using global + +2.1. Features + + o Tag function of extended vi can locate not only function definitions + but also function references. + o Extended vi allows duplicate tag entries. + o Extended vi can understand perl's regular expression as a tag name + for search. + o Extended vi is completely upper compatible with original one. + Above functions are available only in 'gtags mode'. + +2.2. Preparation + + First do the preparation of global. (Please see "1.2. Preparation"). + + Second, to use global from vi, you need to get into 'gtagsmode'. + There are some ways to do it. + + (a) Start vi with -G option + + % vi -G file.c + + (b) Start vi and execute "set gtagsmode" + + % vi file.c + ~ + ~ + ~ + :set gtagsmode + + (c) Previously write the set command to .exrc or .nexrc file and start vi + + $HOME/.exrc + +---------------------------- + |set gtagsmode + + You must start vi under the source tree described in "1.2. Preparation". + +2.3. Basic usage + + o To go to func1, you can say + + :tag func1 + + It seemes same with original vi, but extended vi use GTAGS + instead of tags. + + o To go to referenced point of func1, add prefix 'r' + + :rtag func1 + + Extended vi use GRTAGS. + + o If a number of functions located, the action of extended vi differs + up to your nvi's version. + + [Extended vi based 1.34 nvi] + + Vi goes into 'GTAGS SELECT MODE' like this. + + +------------------------------------------------------------- + |main 347 i386/isa/ultra14f.c main() + |main 128 kern/init_main.c main(framep) + |main 104 netiso/clnp_debug.c main() + |main 164 netiso/xebec/main.c main(argc, argv) + |~ + |~ + |~ + |~ + |~ + |[GTAGS SELECT MODE] 4 lines + +------------------------------------------------------------- + + You can select a tag line by any vi command and press [RETURN], + and you can go to the tag's point. In ex mode, type "select" + instead of [RETURN]. When you want to go to next or previous tag, + you can return to 'GTAGS SELECT MODE' with <control-T> and reselect. + + Suggested .nexrc: + set gtagsmode + set leftright + + [Extended vi based 1.76 nvi] + + Vi goes to the first tag. + Then you can go to next tag by ':tagnext' or back by ':tagprev'. + + Suggested .nexrc: + set gtagsmode + map ^N :tagnext^M + map ^P :tagprev^M + + == WHY TWO STYLE EXIST ? == + 1.34 nvi cannot treat duplicate tag entries, so I made 'GTAGS SELECT MODE' + in it. But 1.76 nvi (1.61 and later) can treat them, so I adapted GLOBAL + tags to nvi's tag structure. + + o <control-]> command is available. + + In gtagsmode, if you are on the first column of line, it is identical to + ":rtag <current token>[RETURN]", otherwise ":tag <current token>[RETURN]". + + o Other tag commands are available too. + + <control-T> + ":tagpop" + ":tagtop" + ":display tags" + + Please read online manual. + +2.4. Applied usage + + o In large project which include many main() function like MH, + you can start vi like this. + + % vi -G -t main + + You can browse all commands sequentially. + + o When you want to check functions the name of which start with + "set" or "get", + + % vi -G -t '^[sg]et' + + Of cause, following command is available too. + + :tag ^[sg]et + + o If your source files are on a read only device like CDROM, please do + the followings. + + % mkdir /var/dbpath <- directory for tag file + % cd /cdrom/src <- the root of source tree + % gtags /var/dbpath <- make tag files in /var/dbpath + % setenv GTAGSROOT `pwd` + % setenv GTAGSDBPATH /var/dbpath + % vi -G -t main + + o If you want to treat the references to the function that is not defined + in the source tree like library functions or system calls, + do the followings. + + % cd /usr/src/lib + % gtags <- probably as a root + % cd /usr/src/sys + % gtags + % setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys + + If you examine vi's source, + + % cd /usr/src/usr.bin/vi + % gtags + % vi -G -t main + + You can start from vi and trip the whole unix world as if using + hypertext. + + +3. Hypertext generator + +3.1. Features + + o Htags makes hypertext from C source files. + o Once the hypertext generated, you need nothing other than WWW browser. + o You can use all of your browser's functions, for example, search, + history, bookmark, save, frame, windows and so on. + +3.2. Preparation + + At first, you must prepare much disk space. Hypertext needs so much + disk space. For example, the source code of FreeBSD kernel needs the + following disk space. + + source code(/usr/src/sys) 14MB + tag database(GTAGS,GRTAGS) 9MB(!) + hypertext(HTML/*) 42MB(!!!) + + Please do the followings. + + (at your source directory) + % gtags <- make tag database + % htags <- make hypertext + + Then you will find 'HTML' directory in the current directory. + +3.3. Usage + + Please start a web browser like this. + + % lynx HTML/index.html + + You can use any browsers, for example, Lynx, Chimera, Mosaic, + Netscape Navigator, Internet Explorer and so on. + (But IE3.0 doesn't work well about index.) + + You will understand the usage for the looking. + You can move HTML directory to anywhere. It is independent of + the source code. + +3.4. To make hypertext of kernel + + If you would like to make hypertext of FreeBSD or Linux kernel source, + it is convenient to use systags script in this package. + + % cd /usr/src/sys + % systags + then + + % netscape HTML/index.html + + You can use one level nested index and browse assembler source file too. + +Thank you for your reading of my poor english. +And of course, thank you Keith Bostic (the author of nvi(1) and db(3)). +---------------------------------------------------------------------------- +E-Mail: <shigio@wafu.netgate.net> +WWW: <http://wafu.netgate.net/tama/unix/indexe.html> + (You can find the latest version here.) +---------------------------------------------------------------------------- diff --git a/usr.bin/global/VERSION b/usr.bin/global/VERSION new file mode 100644 index 0000000..ea3769f --- /dev/null +++ b/usr.bin/global/VERSION @@ -0,0 +1 @@ +1.81 diff --git a/usr.bin/global/btreeop/Makefile b/usr.bin/global/btreeop/Makefile new file mode 100644 index 0000000..c9e0409 --- /dev/null +++ b/usr.bin/global/btreeop/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 1.0 (Berkeley) 4/21/96 + +PROG= btreeop + +.include <bsd.prog.mk> diff --git a/usr.bin/global/btreeop/btreeop.1 b/usr.bin/global/btreeop/btreeop.1 new file mode 100644 index 0000000..b6baa6d --- /dev/null +++ b/usr.bin/global/btreeop/btreeop.1 @@ -0,0 +1,142 @@ +.\" +.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Shigio Yamaguchi. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 21, 1996 +.Dt BTREEOP 1 +.Os BSD 4 +.Sh NAME +.Nm btreeop +.Nd btree database maintenance tool +.Sh SYNOPSIS +.Nm btreeop +.Op Fl C +.Op Fl K Ar key +.Op Fl b +.Op Fl c Ar cashesize +.Op Fl l +.Op Fl p Ar psize +.Op Ar dbname +.Sh DESCRIPTION +.Nm Btreeop +execute simple operations for +.Xr btree 3 +database. +.Nm Btreeop +can create database and read (sequential or index) from it . +Duplicate entries are allowed. +.Sh OPTIONS +A capital letter means a command. If no command specified +then it assume sequential read operation. +.Bl -tag -width Ds +.It Fl C +create database. +.It Fl K Ar key +search data by the key. +.It Fl b +assume BIG_ENDIAN byte order. default is LITTLE_ENDIAN. +.It Fl c Ar cashesize +specify cashesize. It's identical to +.Nm info.cachesize +of BTREEINFO. (see btree(3)) +.It Fl l +assume LITTLE_ENDIAN byte order. (the default) +.It Fl p Ar psize +specify page size. It's identical to +.Nm info.psize +of BTREEINFO. (see btree(3)) +.It Ar dbname +database name. default is 'btree'. +.Sh DATA FORMAT +To creat database, +.Nm btreeop +read data from stdin. +The format of the data is the following. + + Key Data\\n + Key Data\\n + . + . + . + +.El + +.Bl -enum -offset indent +.It +Key and Data are separated by blank('\\t' or ' '). +.It +Key cannot include blank. +.It +Data can include blank. +.It +Null Data not allowed. +.El +.Sh EXAMPLES +Create database. + + % btreeop -C + key1 data1 + key2 data2 + key2 data2-2 + key3 data3 + ^D + % + +Sequential read. + + % btreeop + key2 data2 + key3 data3 + key2 data2-2 + key1 data1 + % + +Indexed read. + + % btreeop -K key2 + key2 data2-2 + key2 data2 + % + +.Sh FILES +.Bl -tag -width tags -compact +.It Pa btree +default database name. +.El +.Sh DIAGNOSTICS +.Nm Btreeop +exits with a value of 1 if an error occurred, 0 otherwise. +.Sh SEE ALSO +.Xr btree 3 , +.Sh BUGS +.Nm btreeop +cannot utilize all features of +.Xr btree 3 +.Sh AUTHOR +Shigio Yamaguchi (shigio@wafu.netgate.net) diff --git a/usr.bin/global/btreeop/btreeop.c b/usr.bin/global/btreeop/btreeop.c new file mode 100644 index 0000000..1d2faeb --- /dev/null +++ b/usr.bin/global/btreeop/btreeop.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Shigio Yamaguchi. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * btreeop.c 5-Apr-97 + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <ctype.h> +#include <db.h> +#include <fcntl.h> + +char *dbdefault = "btree"; /* default database name */ +char *progname = "btreeop"; /* command name */ +char *dbname; +char buf[BUFSIZ+1]; + +#ifndef __P +#if defined(__STDC__) +#define __P(protos) protos +#else +#define __P(protos) () +#endif +#endif +void die __P((char *)); +void usage __P((void)); +void entab __P((char *)); +void main __P((int, char **)); +int dbcreate __P((DB *)); +int dbkey __P((DB *, char *)); +int dbscan __P((DB *)); + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +void +die(s) +char *s; +{ + fprintf(stderr, "%s: %s\n", progname, s); + exit(1); +} + +void +usage() { + fprintf(stderr, + "usage: %s [-C][-K key][-b][-c cachesize][-l][-p psize][dbname]\n", + progname); + exit(1); +} + +#define TABPOS(i) ((i)%8 == 0) +/* + * entab: convert spaces into tabs + * + * io) buf string buffer + */ +void +entab(buf) +char *buf; +{ + int blanks = 0; + int pos, src, dst; + char c; + + pos = src = dst = 0; + while ((c = buf[src++]) != 0) { + if (c == ' ') { + if (!TABPOS(++pos)) { + blanks++; /* count blanks */ + continue; + } + buf[dst++] = '\t'; + } else if (c == '\t') { + while (!TABPOS(++pos)) + ; + buf[dst++] = '\t'; + } else { + ++pos; + while (blanks--) + buf[dst++] = ' '; + buf[dst++] = c; + } + blanks = 0; + } + buf[dst] = 0; +} + +#include <errno.h> +void +main(argc, argv) +int argc; +char *argv[]; +{ + char command = 0; + char *key = NULL; + DB *db; + BTREEINFO info; + int c; + + info.flags = R_DUP; /* allow duplicate entries */ + info.cachesize = 500000; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = NULL; + info.prefix = NULL; + info.lorder = LITTLE_ENDIAN; + + while ((c = getopt(argc, argv, "CK:bc:lp:")) != EOF) { + switch (c) { + case 'K': + key = optarg; + case 'C': + command = c; + break; + case 'b': + info.lorder = BIG_ENDIAN; + break; + case 'c': + info.cachesize = atoi(optarg); + break; + case 'l': + info.lorder = LITTLE_ENDIAN; + break; + case 'p': + info.psize = atoi(optarg); + break; + default: + usage(); + } + } + + dbname = (optind < argc) ? argv[optind] : dbdefault; + db = dbopen(dbname, command == 'C' ? + O_RDWR|O_CREAT|O_TRUNC : O_RDONLY, + 0644, DB_BTREE, &info); + + if (db == NULL) { + die("dbopen failed."); + } + switch (command) { + case 'C': /* Create database */ + dbcreate(db); + break; + case 'K': /* Keyed search */ + dbkey(db, key); + break; + default: /* Scan all data */ + dbscan(db); + break; + } + if (db->close(db)) { + die("db->close failed."); + } + exit(0); +} +/* + * dbcreate: create database + * + * i) db + * r) 0: normal + */ +int +dbcreate(db) +DB *db; +{ + DBT key, dat; + int status; +#define IDENTLEN 80 + char keybuf[IDENTLEN+1]; + char *c; + + /* + * Input file format: + * +------------------ + * |Key Data\n + * |Key Data\n + * . + * . + * - Key and Data are separated by blank('\t' or ' '). + * - Key cannot include blank. + * - Data can include blank. + * - Null Data not allowed. + */ + while (fgets(buf, BUFSIZ, stdin)) { + if (buf[strlen(buf)-1] == '\n') /* chop(buf) */ + buf[strlen(buf)-1] = 0; + else + while (fgetc(stdin) != '\n') + ; + for (c = buf; *c && !isspace(*c); c++) /* skip key part */ + ; + if (*c == 0) + die("data part not found."); + if (c - buf > IDENTLEN) + die("key too long."); + strncpy(keybuf, buf, c - buf); /* make key string */ + keybuf[c - buf] = 0; + for (; *c && isspace(*c); c++) /* skip blanks */ + ; + if (*c == 0) + die("data part is null."); + entab(buf); + key.data = keybuf; + key.size = strlen(keybuf)+1; + dat.data = buf; + dat.size = strlen(buf)+1; + + status = (db->put)(db, &key, &dat, 0); + switch (status) { + case RET_SUCCESS: + break; + case RET_ERROR: + case RET_SPECIAL: + die("db->put: failed."); + } + } + return(0); +} + +/* + * dbkey: Keyed search + * + * i) db + * i) skey + * r) 0: normal + * 1: not found + */ +int +dbkey(db, skey) +DB *db; +char *skey; +{ + DBT dat, key; + int status; + + key.data = skey; + key.size = strlen(skey)+1; + + for (status = (*db->seq)(db, &key, &dat, R_CURSOR); + status == RET_SUCCESS && !strcmp(key.data, skey); + status = (*db->seq)(db, &key, &dat, R_NEXT)) { + (void)fprintf(stdout, "%s\n", (char *)dat.data); + } + + if (status == RET_ERROR) + die("db->seq failed."); + return (0); +} + +/* + * dbscan: Scan all data + * + * i) db + * r) 0: normal + * 1: not found + */ +int +dbscan(db) +DB *db; +{ + DBT dat, key; + int status; + + for (status = (*db->seq)(db, &key, &dat, R_FIRST); + status == RET_SUCCESS; + status = (*db->seq)(db, &key, &dat, R_NEXT)) { + (void)fprintf(stdout, "%s\n", (char *)dat.data); + } + if (status == RET_ERROR) + die("db->seq failed."); + return (0); +} diff --git a/usr.bin/global/gctags/C.c b/usr.bin/global/gctags/C.c new file mode 100644 index 0000000..87652b5 --- /dev/null +++ b/usr.bin/global/gctags/C.c @@ -0,0 +1,840 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)C.c 8.4 (Berkeley) 4/2/94"; +#endif /* LIBC_SCCS and not lint */ + +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ctags.h" + +static int func_entry __P((void)); +static void hash_entry __P((void)); +static void skip_string __P((int)); +static int str_entry __P((int)); +#ifdef GTAGS +static int cmp __P((const void *, const void *)); +static int isstatement __P((char *)); +static void define_line __P((void)); +#endif + +#ifdef YACC +extern int yaccfile; /* true when *.y file */ +#endif +/* + * c_entries -- + * read .c and .h files and call appropriate routines + */ +void +c_entries() +{ + int c; /* current character */ + int level; /* brace level */ + int token; /* if reading a token */ + int t_def; /* if reading a typedef */ + int t_level; /* typedef's brace level */ + char *sp; /* buffer pointer */ + char tok[MAXTOKEN]; /* token buffer */ +#ifdef YACC + /* + * yacc file format is like the following. + * + * declarations + * %% + * rules + * %% + * programs + * + */ +#define DECLARATIONS 0 +#define RULES 1 +#define PROGRAMS 2 + int yaccstatus = (yaccfile) ? DECLARATIONS : PROGRAMS; + int inyacc = (yaccfile) ? YES : NO; /* NO while C source */ +#endif + + lineftell = ftell(inf); + sp = tok; token = t_def = NO; t_level = -1; level = 0; lineno = 1; + while (GETC(!=, EOF)) { + switch (c) { + /* + * Here's where it DOESN'T handle: { + * foo(a) + * { + * #ifdef notdef + * } + * #endif + * if (a) + * puts("hello, world"); + * } + */ + case '{': +#ifdef YACC + if (yaccstatus == RULES && level == 0) + inyacc = NO; +#endif + ++level; + goto endtok; + case '}': + /* + * if level goes below zero, try and fix + * it, even though we've already messed up + */ + if (--level < 0) + level = 0; +#ifdef GTAGS + /* + * -e flag force a function to end when a '}' appear + * at column 0. If -e flag not specified, all functions + * after funcA() would be lost. + * + * funcA() { + * #ifdef A + * if (a) { + * ... + * #else + * if (nota) { + * ... + * #endif + * } + * } + */ + if (eflag && ftell(inf) == lineftell+1) { + level = 0; + } +#endif +#if YACC + if (yaccstatus == RULES && level == 0) + inyacc = YES; +#endif + goto endtok; + + case '\n': + SETLINE; + /* + * the above 3 cases are similar in that they + * are special characters that also end tokens. + */ + endtok: if (sp > tok) { + *sp = EOS; + token = YES; + sp = tok; + } + else + token = NO; + continue; + + /* + * We ignore quoted strings and character constants + * completely. + */ + case '"': + case '\'': + (void)skip_string(c); + break; + + /* + * comments can be fun; note the state is unchanged after + * return, in case we found: + * "foo() XX comment XX { int bar; }" + */ + case '/': + if (GETC(==, '*')) { + skip_comment(); + continue; + } + (void)ungetc(c, inf); + c = '/'; + goto storec; + + /* hash marks flag #define's. */ + case '#': + if (sp == tok) { + hash_entry(); + break; + } + goto storec; + + /* + * if we have a current token, parenthesis on + * level zero indicates a function. +#ifdef GTAGS + * in the case of rflag == 1, if we have a current token, + * parenthesis on level > zero indicates a function reference. +#endif +#ifdef YACC + * inyacc == NO while C source. +#endif + */ + case '(': +#ifdef YACC + if (inyacc == NO) +#endif +#ifdef GTAGS + if (!rflag && !level && token) +#else + if (!level && token) +#endif + { + int curline; + + if (sp != tok) + *sp = EOS; + /* + * grab the line immediately, we may + * already be wrong, for example, + * foo\n + * (arg1, + */ + getline(); + curline = lineno; +#ifdef GTAGS + /* to make sure. */ + if (!isstatement(tok)) +#endif + if (func_entry()) { + ++level; + pfnote(tok, curline); + } + break; + } +#ifdef GTAGS + else if (rflag && level && token) { + if (sp != tok) + *sp = EOS; + getline(); + if (!isstatement(tok) && isdefined(tok)) + pfnote(tok, lineno); + break; + } +#endif + goto storec; + + /* + * semi-colons indicate the end of a typedef; if we find a + * typedef we search for the next semi-colon of the same + * level as the typedef. Ignoring "structs", they are + * tricky, since you can find: + * + * "typedef long time_t;" + * "typedef unsigned int u_int;" + * "typedef unsigned int u_int [10];" + * + * If looking at a typedef, we save a copy of the last token + * found. Then, when we find the ';' we take the current + * token if it starts with a valid token name, else we take + * the one we saved. There's probably some reasonable + * alternative to this... + */ + case ';': + if (t_def && level == t_level) { + t_def = NO; + getline(); + if (sp != tok) + *sp = EOS; + pfnote(tok, lineno); + break; + } + goto storec; + +#if YACC + case '%': + if (yaccstatus == DECLARATIONS || yaccstatus == RULES) { + if (GETC(==, '%')) { + level = 0; + if (yaccstatus == DECLARATIONS) { + if (!rflag) { + getline(); + pfnote("yyparse", lineno); + } + yaccstatus = RULES; + } else if (yaccstatus == RULES) { + yaccstatus = PROGRAMS; + } + inyacc = (yaccstatus == PROGRAMS) ? NO : YES; + } else if (c == '{') { + level = 0; + inyacc = NO; + } else if (c == '}') { + level = 0; + inyacc = YES; + } else { + (void)ungetc(c, inf); + } + break; + } + /* else fall throuth */ +#endif + /* + * store characters until one that can't be part of a token + * comes along; check the current token against certain + * reserved words. + */ + default: +#ifdef BUGFIX + /* + * to treat following function. + * func (arg) { + * .... + * } + */ + if (c == ' ' || c == '\t') { + int save = c; + while (GETC(!=, EOF) && (c == ' ' || c == '\t')) + ; + if (c == EOF) + return; + (void)ungetc(c, inf); + c = save; + } +#endif + storec: if (!intoken(c)) { + if (sp == tok) + break; + *sp = EOS; +#ifdef GTAGS + if (!memcmp(tok, "extern",7)) { + while (GETC(!=, EOF) && c != ';') { + if (c == '\n') + SETLINE; + } + if (c == EOF) + return; + break; + } +#endif + if (tflag) { + /* no typedefs inside typedefs */ + if (!t_def && + !memcmp(tok, "typedef",8)) { + t_def = YES; + t_level = level; + break; + } + /* catch "typedef struct" */ + if ((!t_def || t_level < level) + && (!memcmp(tok, "struct", 7) + || !memcmp(tok, "union", 6) + || !memcmp(tok, "enum", 5))) { + /* + * get line immediately; + * may change before '{' + */ + getline(); + if (str_entry(c)) + ++level; + break; + /* } */ + } + } + sp = tok; + } + else if (sp != tok || begtoken(c)) { + *sp++ = c; + token = YES; + } + continue; + /* end of default */ + } /* end of switch */ + /* + * 'break' statement in switch block come here. + */ + sp = tok; + token = NO; + } /* end of while */ +} + +/* + * func_entry -- + * handle a function reference + */ +static int +func_entry() +{ + int c; /* current character */ + int level = 0; /* for matching '()' */ + + /* + * Find the end of the assumed function declaration. + * Note that ANSI C functions can have type definitions so keep + * track of the parentheses nesting level. + */ + while (GETC(!=, EOF)) { + switch (c) { + case '\'': + case '"': + /* skip strings and character constants */ + skip_string(c); + break; + case '/': + /* skip comments */ + if (GETC(==, '*')) + skip_comment(); + break; + case '(': + level++; + break; + case ')': + if (level == 0) + goto fnd; + level--; + break; + case '\n': + SETLINE; + } + } + return (NO); +fnd: + /* + * we assume that the character after a function's right paren + * is a token character if it's a function and a non-token + * character if it's a declaration. Comments don't count... + */ + for (;;) { + while (GETC(!=, EOF) && iswhite(c)) + if (c == '\n') + SETLINE; + if (intoken(c) || c == '{') + break; + if (c == '/' && GETC(==, '*')) + skip_comment(); + else { /* don't ever "read" '/' */ + (void)ungetc(c, inf); + return (NO); + } + } + if (c != '{') + (void)skip_key('{'); + return (YES); +} + +/* + * hash_entry -- + * handle a line starting with a '#' + */ +static void +hash_entry() +{ + int c; /* character read */ + int curline; /* line started on */ + char *sp; /* buffer pointer */ + char tok[MAXTOKEN]; /* storage buffer */ + +#ifdef BUGFIX + /* + * to treat following macro. + * # macro(arg) .... + */ + while (GETC(!=, EOF) && (c == ' ' || c == '\t')) + ; + (void)ungetc(c, inf); +#endif + curline = lineno; + for (sp = tok;;) { /* get next token */ + if (GETC(==, EOF)) + return; + if (iswhite(c)) + break; + *sp++ = c; + } + *sp = EOS; + if (memcmp(tok, "define", 6)) /* only interested in #define's */ + goto skip; + for (;;) { /* this doesn't handle "#define \n" */ + if (GETC(==, EOF)) + return; + if (!iswhite(c)) + break; + } + for (sp = tok;;) { /* get next token */ + *sp++ = c; + if (GETC(==, EOF)) + return; + /* + * this is where it DOESN'T handle + * "#define \n" + */ + if (!intoken(c)) + break; + } + *sp = EOS; +#ifdef GTAGS + if (rflag) { + /* + * #define XXX\n + */ + if (c == '\n' || (c == '\r' && GETC(==, '\n'))) { + SETLINE; + return; + } + /* + * v + * #define XXX(X) XXXXXX + */ + if (c == '(') + (void)skip_key(')'); + /* + * v + * #define XXX(X) XXXXXX + */ + while (GETC(!=, EOF)) { + if (c != ' ' && c != '\t') { + (void)ungetc(c, inf); + break; + } + } + /* + * v + * #define XXX(X) XXXXXX + */ + define_line(); + return; + } +#endif + if (dflag || c == '(') { /* only want macros */ + getline(); + pfnote(tok, curline); + } +skip: if (c == '\n') { /* get rid of rest of define */ + SETLINE +#ifdef MODIFY + if (*(sp - 1) == '\r') { + if (*(sp - 2) != '\\') + return; + } else +#endif + if (*(sp - 1) != '\\') + return; + } + (void)skip_key('\n'); +} + +#ifdef GTAGS + /* sorted by alphabet */ +static struct words { + char *name; +} words[] = { + {"__P"}, + {"auto"}, + {"break"}, + {"case"}, + {"char"}, + {"continue"}, + {"default"}, + {"do"}, + {"double"}, + {"else"}, + {"extern"}, + {"float"}, + {"for"}, + {"goto"}, + {"if"}, + {"int"}, + {"long"}, + {"register"}, + {"return"}, + {"short"}, + {"sizeof"}, + {"static"}, + {"struct"}, + {"switch"}, + {"typedef"}, + {"union"}, + {"unsigned"}, + {"void"}, + {"while"}, +}; + +static int +cmp(s1, s2) + const void *s1, *s2; +{ + return strcmp(((struct words *)s1)->name, ((struct words *)s2)->name); +} + +static int +isstatement(token) + char *token; +{ + struct words tmp; + + tmp.name = token; + if (bsearch(&tmp, words, sizeof(words)/sizeof(struct words), sizeof(struct words), cmp)) + return YES; + return NO; +} + +static void +define_line() +{ + int c; /* character read */ + int level; /* brace level */ + int token; /* if reading a token */ + char *sp; /* buffer pointer */ + char tok[MAXTOKEN]; /* storage buffer */ + + sp = tok; token = NO; level = 0; + while (GETC(!=, EOF)) { + switch (c) { + case '{': + ++level; + goto endtok; + case '}': + if (--level < 0) + level = 0; + goto endtok; + + case '\\': + if (GETC(==, '\n') || (c == '\r' && GETC(==, '\n'))) { + SETLINE; + } + continue; + + case '\n': + SETLINE; + return; + endtok: if (sp > tok) { + *sp = EOS; + token = YES; + sp = tok; + } + else + token = NO; + continue; + + case '"': + case '\'': + (void)skip_string(c); + break; + + case '/': + if (GETC(==, '*')) { + skip_comment(); + continue; + } + (void)ungetc(c, inf); + c = '/'; + goto storec; + + case '(': + if (token) { + if (sp != tok) + *sp = EOS; + getline(); + if (!isstatement(tok) && isdefined(tok)) + pfnote(tok, lineno); + break; + } + goto storec; + + case ';': + goto storec; + + default: +storec: if (!intoken(c)) { + if (sp == tok) + break; + *sp = EOS; + sp = tok; + } + else if (sp != tok || begtoken(c)) { + *sp++ = c; + token = YES; + } + continue; + } + + sp = tok; + token = NO; + } +} +#endif +/* + * str_entry -- + * handle a struct, union or enum entry + */ +static int +str_entry(c) + int c; /* current character */ +{ + int curline; /* line started on */ + char *sp; /* buffer pointer */ + char tok[LINE_MAX]; /* storage buffer */ + + curline = lineno; + while (iswhite(c)) + if (GETC(==, EOF)) + return (NO); + if (c == '{') /* it was "struct {" */ + return (YES); + for (sp = tok;;) { /* get next token */ + *sp++ = c; + if (GETC(==, EOF)) + return (NO); + if (!intoken(c)) + break; + } + switch (c) { + case '{': /* it was "struct foo{" */ + --sp; + break; + case '\n': /* it was "struct foo\n" */ + SETLINE; + /*FALLTHROUGH*/ + default: /* probably "struct foo " */ + while (GETC(!=, EOF)) + if (!iswhite(c)) + break; + if (c != '{') { + (void)ungetc(c, inf); + return (NO); + } + } + *sp = EOS; + pfnote(tok, curline); + return (YES); +} + +/* + * skip_comment -- + * skip over comment + */ +void +skip_comment() +{ + int c; /* character read */ + int star; /* '*' flag */ + + for (star = 0; GETC(!=, EOF);) + switch(c) { + /* comments don't nest, nor can they be escaped. */ + case '*': + star = YES; + break; + case '/': + if (star) + return; + break; + case '\n': + SETLINE; + /*FALLTHROUGH*/ + default: + star = NO; + break; + } +} + +/* + * skip_string -- + * skip to the end of a string or character constant. + */ +static void +skip_string(key) + int key; +{ + int c, + skip; + + for (skip = NO; GETC(!=, EOF); ) + switch (c) { + case '\\': /* a backslash escapes anything */ + skip = !skip; /* we toggle in case it's "\\" */ + break; +#ifdef MODIFY + case '\r': + break; +#endif + case '\n': + SETLINE; + /*FALLTHROUGH*/ + default: + if (c == key && !skip) + return; + skip = NO; + } +} + +/* + * skip_key -- + * skip to next char "key" + */ +int +skip_key(key) + int key; +{ + int c, + skip, + retval; + + for (skip = retval = NO; GETC(!=, EOF);) + switch(c) { + case '\\': /* a backslash escapes anything */ + skip = !skip; /* we toggle in case it's "\\" */ + break; + case ';': /* special case for yacc; if one */ + case '|': /* of these chars occurs, we may */ + retval = YES; /* have moved out of the rule */ + break; /* not used by C */ + case '\'': + case '"': + /* skip strings and character constants */ + skip_string(c); + break; + case '/': + /* skip comments */ + if (GETC(==, '*')) { + skip_comment(); + break; + } + (void)ungetc(c, inf); + c = '/'; + goto norm; +#ifdef MODIFY + case '\r': + break; +#endif + case '\n': + SETLINE; + /*FALLTHROUGH*/ + default: + norm: + if (c == key && !skip) + return (retval); + skip = NO; + } + return (retval); +} diff --git a/usr.bin/global/gctags/Makefile b/usr.bin/global/gctags/Makefile new file mode 100644 index 0000000..bc0cbbf --- /dev/null +++ b/usr.bin/global/gctags/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= gctags +CFLAGS+=-I${.CURDIR} -DGTAGS -DBUGFIX -DMODIFY -DYACC +SRCS= C.c ctags.c fortran.c lisp.c print.c tree.c yacc.c + +.include <bsd.prog.mk> diff --git a/usr.bin/global/gctags/ctags.c b/usr.bin/global/gctags/ctags.c new file mode 100644 index 0000000..e0f0428 --- /dev/null +++ b/usr.bin/global/gctags/ctags.c @@ -0,0 +1,402 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1987, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)ctags.c 8.3 (Berkeley) 4/2/94"; +#endif /* LIBC_SCCS and not lint */ + +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include "ctags.h" + +/* + * ctags: create a tags file + */ + +NODE *head; /* head of the sorted binary tree */ + + /* boolean "func" (see init()) */ +bool _wht[256], _etk[256], _itk[256], _btk[256], _gd[256]; + +FILE *inf; /* ioptr for current input file */ +FILE *outf; /* ioptr for tags file */ + +long lineftell; /* ftell after getc( inf ) == '\n' */ + +int lineno; /* line number of current line */ +int dflag; /* -d: non-macro defines */ +#ifdef GTAGS +int eflag; /* -e: '{' at 0 column force function end */ +#endif +int tflag; /* -t: create tags for typedefs */ +int vflag; /* -v: vgrind style index output */ +int wflag; /* -w: suppress warnings */ +int xflag; /* -x: cxref style output */ +#ifdef GTAGS +int Dflag; /* -D: allow duplicate entrys */ +int rflag; /* -r: function reference */ +#endif +#ifdef YACC +int yaccfile; /* yacc file */ +#endif + +char *curfile; /* current input file name */ +char searchar = '/'; /* use /.../ searches by default */ +char lbuf[LINE_MAX]; + +void init __P((void)); +void find_entries __P((char *)); +int main __P((int, char **)); + +int +main(argc, argv) + int argc; + char **argv; +{ + static char *outfile = "tags"; /* output file */ + int aflag; /* -a: append to tags */ + int uflag; /* -u: update tags */ + int exit_val; /* exit value */ + int step; /* step through args */ + int ch; /* getopts char */ + char cmd[100]; /* too ugly to explain */ + +#ifndef lint + copyright[0] = copyright[0]; /* to satisfy compiler */ +#endif + aflag = uflag = NO; +#ifdef GTAGS + while ((ch = getopt(argc, argv, "BDFadef:rtuwvxy")) != EOF) +#else + while ((ch = getopt(argc, argv, "BFadf:tuwvx")) != EOF) +#endif + switch(ch) { + case 'B': + searchar = '?'; + break; +#ifdef GTAGS + case 'D': + Dflag++; + break; +#endif + case 'F': + searchar = '/'; + break; + case 'a': + aflag++; + break; + case 'd': + dflag++; + break; +#ifdef GTAGS + case 'e': + eflag++; + break; +#endif + case 'f': + outfile = optarg; + break; +#ifdef GTAGS + case 'r': + rflag++; + break; +#endif + case 't': + tflag++; + break; + case 'u': + uflag++; + break; + case 'w': + wflag++; + break; + case 'v': + vflag++; + case 'x': + xflag++; + break; + case '?': + default: + goto usage; + } + argv += optind; + argc -= optind; + if (!argc) { +usage: (void)fprintf(stderr, +#ifdef GTAGS + "usage: ctags [-BDFadrtuwvx] [-f tagsfile] file ...\n"); +#else + "usage: ctags [-BFadtuwvx] [-f tagsfile] file ...\n"); +#endif + exit(1); + } +#ifdef GTAGS + if (rflag) + gtagopen(); +#endif + init(); + + for (exit_val = step = 0; step < argc; ++step) + if (!(inf = fopen(argv[step], "r"))) { + fprintf(stderr, "gctags: %s cannot open\n", argv[step]); + exit_val = 1; + } + else { + curfile = argv[step]; + find_entries(argv[step]); + (void)fclose(inf); + } + + if (head) + if (xflag) + put_entries(head); + else { + if (uflag) { + for (step = 0; step < argc; step++) { + (void)sprintf(cmd, + "mv %s OTAGS; fgrep -v '\t%s\t' OTAGS >%s; rm OTAGS", + outfile, argv[step], + outfile); + system(cmd); + } + ++aflag; + } + if (!(outf = fopen(outfile, aflag ? "a" : "w"))) { + fprintf(stderr, "gctags: %s cannot open\n", outfile); + exit(exit_val); + } + put_entries(head); + (void)fclose(outf); + if (uflag) { + (void)sprintf(cmd, "sort -o %s %s", + outfile, outfile); + system(cmd); + } + } +#ifdef GTAGS + if (rflag) + gtagclose(); +#endif + exit(exit_val); +} + +/* + * init -- + * this routine sets up the boolean psuedo-functions which work by + * setting boolean flags dependent upon the corresponding character. + * Every char which is NOT in that string is false with respect to + * the pseudo-function. Therefore, all of the array "_wht" is NO + * by default and then the elements subscripted by the chars in + * CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in + * the string CWHITE, else NO. + */ +void +init() +{ + int i; + unsigned char *sp; + + for (i = 0; i < 256; i++) { + _wht[i] = _etk[i] = _itk[i] = _btk[i] = NO; + _gd[i] = YES; + } +#define CWHITE " \f\t\n" + for (sp = (unsigned char *)CWHITE; *sp; sp++) /* white space chars */ + _wht[*sp] = YES; +#define CTOKEN " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?" + for (sp = (unsigned char *)CTOKEN; *sp; sp++) /* token ending chars */ + _etk[*sp] = YES; +#define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789" + for (sp = (unsigned char *)CINTOK; *sp; sp++) /* valid in-token chars */ + _itk[*sp] = YES; +#define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" + for (sp = (unsigned char *)CBEGIN; *sp; sp++) /* token starting chars */ + _btk[*sp] = YES; +#define CNOTGD ",;" + for (sp = (unsigned char *)CNOTGD; *sp; sp++) /* invalid after-function chars */ + _gd[*sp] = NO; +} + +/* + * find_entries -- + * this routine opens the specified file and calls the function + * which searches the file. + */ +void +find_entries(file) + char *file; +{ + char *cp; + + lineno = 0; /* should be 1 ?? KB */ + if ((cp = strrchr(file, '.')) != NULL) { + if (cp[1] == 'l' && !cp[2]) { + int c; + +#ifdef GTAGS + if (rflag) + fprintf(stderr, "-r option is ignored in lisp file (Warning only)\n"); +#endif + for (;;) { + if (GETC(==, EOF)) + return; + if (!iswhite(c)) { + rewind(inf); + break; + } + } +#define LISPCHR ";([" +/* lisp */ if (strchr(LISPCHR, c)) { + l_entries(); + return; + } +/* lex */ else { + /* + * we search all 3 parts of a lex file + * for C references. This may be wrong. + */ + toss_yysec(); + (void)strcpy(lbuf, "%%$"); + pfnote("yylex", lineno); + rewind(inf); + } + } +/* yacc */ else if (cp[1] == 'y' && !cp[2]) { +#ifdef YACC + /* + * we search all part of a yacc file for C references. + * but ignore yacc rule tags. + */ + yaccfile = YES; + c_entries(); + return; +#endif + /* + * we search only the 3rd part of a yacc file + * for C references. This may be wrong. + */ + toss_yysec(); + (void)strcpy(lbuf, "%%$"); + pfnote("yyparse", lineno); + y_entries(); + } +/* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) { +#ifdef GTAGS + if (rflag) + fprintf(stderr, "-r option is ignored in fortran file (Warning only)\n"); +#endif + if (PF_funcs()) + return; + rewind(inf); + } + } +#ifdef YACC + yaccfile = NO; +#endif +/* C */ c_entries(); +} + +#ifdef GTAGS +#include <db.h> +DB *db; + +void +gtagopen() +{ + BTREEINFO info; + char *env; + char dbname[200]; + + strcpy(dbname, "."); + if ((env = getenv("GTAGDBPATH"))) { + strcpy(dbname, env); + } + strcat(dbname, "/GTAGS"); + + info.flags = 0; + info.cachesize = 500000; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = 0; + info.prefix = 0; + info.lorder = 0; + +#define O_RDONLY 0x0000 /* open for reading only */ + db = dbopen(dbname, O_RDONLY, 0, DB_BTREE, &info); + if (db == 0) { + fprintf(stderr, "GTAGS file needed.\n"); + exit(1); + } +} +int +isdefined(skey) +char *skey; +{ + DBT dat, key; + int status; + + key.data = skey; + key.size = strlen(skey)+1; + + status = (*db->get)(db, &key, &dat, 0); + switch (status) { + case RET_SUCCESS: + return(1); /* exist */ + case RET_ERROR: + fprintf(stderr, "db->get failed.\n"); + exit(1); + case RET_SPECIAL: /* not exist */ + break; + } + return 0; +} +void +gtagclose() +{ + if (db->close(db)) { + fprintf(stderr, "GTAGS cannot close.(dbclose)\n"); + exit(1); + } +} +#endif diff --git a/usr.bin/global/gctags/ctags.h b/usr.bin/global/gctags/ctags.h new file mode 100644 index 0000000..7fa84b8 --- /dev/null +++ b/usr.bin/global/gctags/ctags.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ctags.h 8.3 (Berkeley) 4/2/94 + */ + +#define bool char + +#define YES 1 +#define NO 0 +#define EOS '\0' + +#define ENDLINE 50 /* max length of pattern */ +#define MAXTOKEN 250 /* max size of single token */ + +#ifndef LINE_MAX +#define LINE_MAX 2048 +#endif + +#define SETLINE {++lineno;lineftell = ftell(inf);} +#define GETC(op,exp) ((c = getc(inf)) op (int)exp) + +#define iswhite(arg) (_wht[(unsigned)arg]) /* T if char is white */ +#define begtoken(arg) (_btk[(unsigned)arg]) /* T if char can start token */ +#define intoken(arg) (_itk[(unsigned)arg]) /* T if char can be in token */ +#define endtoken(arg) (_etk[(unsigned)arg]) /* T if char ends tokens */ +#define isgood(arg) (_gd[(unsigned)arg]) /* T if char can be after ')' */ + +typedef struct nd_st { /* sorting structure */ + struct nd_st *left, + *right; /* left and right sons */ + char *entry, /* function or type name */ + *file, /* file name */ + *pat; /* search pattern */ + int lno; /* for -x option */ + bool been_warned; /* set if noticed dup */ +} NODE; + +extern char *curfile; /* current input file name */ +extern NODE *head; /* head of the sorted binary tree */ +extern FILE *inf; /* ioptr for current input file */ +extern FILE *outf; /* ioptr for current output file */ +extern long lineftell; /* ftell after getc( inf ) == '\n' */ +extern int lineno; /* line number of current line */ +#ifdef GTAGS +extern int eflag; /* -e: '{' at 0 column force function end */ +extern int Dflag; /* -D: allow duplicate entrys */ +extern int rflag; /* -r: function reference */ +#endif /* GTAGS */ +extern int dflag; /* -d: non-macro defines */ +extern int tflag; /* -t: create tags for typedefs */ +extern int vflag; /* -v: vgrind style index output */ +extern int wflag; /* -w: suppress warnings */ +extern int xflag; /* -x: cxref style output */ +extern bool _wht[], _etk[], _itk[], _btk[], _gd[]; +extern char lbuf[LINE_MAX]; +extern char *lbp; +extern char searchar; /* ex search character */ + +#ifndef __P +#ifdef __STDC__ +#define __P(protos) protos +#else +#define __P(protos) () +#endif +#endif + +int cicmp __P((char *)); +void getline __P((void)); +void pfnote __P((char *, int)); +int skip_key __P((int)); +void put_entries __P((NODE *)); +void toss_yysec __P((void)); +void l_entries __P((void)); +void y_entries __P((void)); +int PF_funcs __P((void)); +void c_entries __P((void)); +void skip_comment __P((void)); +void gtagopen __P((void)); +int isdefined __P((char *)); +void gtagclose __P((void)); diff --git a/usr.bin/global/gctags/fortran.c b/usr.bin/global/gctags/fortran.c new file mode 100644 index 0000000..2a33aff --- /dev/null +++ b/usr.bin/global/gctags/fortran.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)fortran.c 8.3 (Berkeley) 4/2/94"; +#endif /* LIBC_SCCS and not lint */ + +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#include "ctags.h" + +static void takeprec __P((void)); + +char *lbp; /* line buffer pointer */ + +int +PF_funcs() +{ + bool pfcnt; /* pascal/fortran functions found */ + char *cp; + char tok[MAXTOKEN]; + + for (pfcnt = NO;;) { + lineftell = ftell(inf); + if (!fgets(lbuf, sizeof(lbuf), inf)) + return (pfcnt); + ++lineno; + lbp = lbuf; + if (*lbp == '%') /* Ratfor escape to fortran */ + ++lbp; + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + switch (*lbp | ' ') { /* convert to lower-case */ + case 'c': + if (cicmp("complex") || cicmp("character")) + takeprec(); + break; + case 'd': + if (cicmp("double")) { + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + if (cicmp("precision")) + break; + continue; + } + break; + case 'i': + if (cicmp("integer")) + takeprec(); + break; + case 'l': + if (cicmp("logical")) + takeprec(); + break; + case 'r': + if (cicmp("real")) + takeprec(); + break; + } + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + switch (*lbp | ' ') { + case 'f': + if (cicmp("function")) + break; + continue; + case 'p': + if (cicmp("program") || cicmp("procedure")) + break; + continue; + case 's': + if (cicmp("subroutine")) + break; + default: + continue; + } + for (; isspace(*lbp); ++lbp) + continue; + if (!*lbp) + continue; + for (cp = lbp + 1; *cp && intoken(*cp); ++cp) + continue; + if (cp == lbp + 1) + continue; + *cp = EOS; + (void)strcpy(tok, lbp); + getline(); /* process line for ex(1) */ + pfnote(tok, lineno); + pfcnt = YES; + } + /*NOTREACHED*/ +} + +/* + * cicmp -- + * do case-independent strcmp + */ +int +cicmp(cp) + char *cp; +{ + int len; + char *bp; + + for (len = 0, bp = lbp; *cp && (*cp &~ ' ') == (*bp++ &~ ' '); + ++cp, ++len) + continue; + if (!*cp) { + lbp += len; + return (YES); + } + return (NO); +} + +static void +takeprec() +{ + for (; isspace(*lbp); ++lbp) + continue; + if (*lbp == '*') { + for (++lbp; isspace(*lbp); ++lbp) + continue; + if (!isdigit(*lbp)) + --lbp; /* force failure */ + else + while (isdigit(*++lbp)) + continue; + } +} diff --git a/usr.bin/global/gctags/gctags.1 b/usr.bin/global/gctags/gctags.1 new file mode 100644 index 0000000..927efc5 --- /dev/null +++ b/usr.bin/global/gctags/gctags.1 @@ -0,0 +1,228 @@ +.\" Copyright (c) 1987, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)gctags.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt GCTAGS 1 +.Os BSD 4 +.Sh NAME +.Nm gctags +.Nd create a tags file (special command for GLOBAL) +.Sh SYNOPSIS +.Nm gctags +.Op Fl BDFadertuwvx +.Op Fl f Ar tagsfile +.Ar name ... +.Sh DESCRIPTION +.Nm Gctags +makes a tags file for +.Xr ex 1 +from the specified C, +Pascal, Fortran, +.Tn YACC , +lex, and lisp sources. +A tags file gives the locations of specified objects in a group of files. +Each line of the tags file contains the object name, the file in which it +is defined, and a search pattern for the object definition, separated by +white-space. +Using the +.Ar tags +file, +.Xr ex 1 +can quickly locate these object definitions. +Depending upon the options provided to +.Nm gctags , +objects will consist of subroutines, typedefs, defines, structs, +enums and unions. +.Bl -tag -width Ds +.It Fl B +use backward searching patterns +.Pq Li ?...? . +.It Fl D +allow duplicate object names. +.It Fl F +use forward searching patterns +.Pq Li /.../ +(the default). +.It Fl a +append to +.Ar tags +file. +.It Fl d +create tags for +.Li #defines +that don't take arguments; +.Li #defines +that take arguments are tagged automatically. +.It Fl e +forece a function to end when reach a '}' at the first column. (C source only) +.It Fl f +Places the tag descriptions in a file called +.Ar tagsfile . +The default behavior is to place them in a file called +.Ar tags . +.It Fl r +locate function references instead of function definitions. GTAGS file is +needed at the current directory. (C source only) +.It Fl t +create tags for typedefs, structs, unions, and enums. +.It Fl u +update the specified files in the +.Ar tags +file, that is, all +references to them are deleted, and the new values are appended to the +file. (Beware: this option is implemented in a way which is rather +slow; it is usually faster to simply rebuild the +.Ar tags +file.) +.It Fl v +An index of the form expected by +.Xr vgrind 1 +is produced on the standard output. This listing +contains the object name, file name, and page number (assuming 64 +line pages). Since the output will be sorted into lexicographic order, +it may be desired to run the output through +.Xr sort 1 . +Sample use: +.Bd -literal -offset indent +gctags \-v files \&| sort \-f > index +vgrind \-x index +.Ed +.It Fl w +suppress warning diagnostics. +.It Fl x +.Nm gctags +produces a list of object +names, the line number and file name on which each is defined, as well +as the text of that line and prints this on the standard output. This +is a simple index which can be printed out as an off-line readable +function index. +.El +.Pp +Files whose names end in +.Nm \&.c +or +.Nm \&.h +are assumed to be C +source files and are searched for C style routine and macro definitions. +Files whose names end in +.Nm \&.y +are assumed to be +.Tn YACC +source files. +Files whose names end in +.Nm \&.l +are assumed to be lisp files if their +first non-blank character is `;', `(', or `[', +otherwise, they are +treated as lex files. Other files are first examined to see if they +contain any Pascal or Fortran routine definitions, and, if not, are +searched for C style definitions. +.Pp +The tag +.Li main +is treated specially in C programs. The tag formed +is created by prepending +.Ar M +to the name of the file, with the +trailing +.Nm \&.c +and any leading pathname components removed. This +makes use of +.Nm gctags +practical in directories with more than one +program. +.Pp +Yacc and lex files each have a special tag. +.Ar Yyparse +is the start +of the second section of the yacc file, and +.Ar yylex +is the start of +the second section of the lex file. +.Sh FILES +.Bl -tag -width tags -compact +.It Pa tags +default output tags file +.It Pa GTAGS +tags file for GLOBAL +.El +.Sh DIAGNOSTICS +.Nm Gctags +exits with a value of 1 if an error occurred, 0 otherwise. +Duplicate objects are not considered errors. +.Sh SEE ALSO +.Xr ex 1 , +.Xr vi 1 , +.Xr gtags 1 +.Sh BUGS +.Pp +Recognition of +.Nm functions , +.Nm subroutines +and +.Nm procedures +for +.Tn FORTRAN +and Pascal is done is a very simpleminded way. No attempt +is made to deal with block structure; if you have two Pascal procedures +in different blocks with the same name you lose. +.Nm Gctags +doesn't +understand about Pascal types. +.Pp +The method of deciding whether to look for C, Pascal or +.Tn FORTRAN +functions is a hack. +.Pp +.Nm Gctags +relies on the input being well formed, and any syntactical +errors will completely confuse it. It also finds some legal syntax +confusing; for example, since it doesn't understand +.Li #ifdef Ns 's +(incidentally, that's a feature, not a bug), any code with unbalanced +braces inside +.Li #ifdef Ns 's +will cause it to become somewhat disoriented. +In a similar fashion, multiple line changes within a definition will +cause it to enter the last line of the object, rather than the first, as +the searching pattern. The last line of multiple line +.Li typedef Ns 's +will similarly be noted. +.Sh HISTORY +The +.Nm Ctags +command appeared in +.Bx 3.0 . +The +.Nm +command appeared in GLOBAL 1.6 . diff --git a/usr.bin/global/gctags/lisp.c b/usr.bin/global/gctags/lisp.c new file mode 100644 index 0000000..ebf5184 --- /dev/null +++ b/usr.bin/global/gctags/lisp.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)lisp.c 8.3 (Berkeley) 4/2/94"; +#endif /* LIBC_SCCS and not lint */ + +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#include "ctags.h" + +/* + * lisp tag functions + * just look for (def or (DEF + */ +void +l_entries() +{ + int special; + char *cp; + char savedc; + char tok[MAXTOKEN]; + + for (;;) { + lineftell = ftell(inf); + if (!fgets(lbuf, sizeof(lbuf), inf)) + return; + ++lineno; + lbp = lbuf; + if (!cicmp("(def")) + continue; + special = NO; + switch(*lbp | ' ') { + case 'm': + if (cicmp("method")) + special = YES; + break; + case 'w': + if (cicmp("wrapper") || cicmp("whopper")) + special = YES; + } + for (; !isspace(*lbp); ++lbp) + continue; + for (; isspace(*lbp); ++lbp) + continue; + for (cp = lbp; *cp && *cp != '\n'; ++cp) + continue; + *cp = EOS; + if (special) { + if (!(cp = strchr(lbp, ')'))) + continue; + for (; cp >= lbp && *cp != ':'; --cp) + continue; + if (cp < lbp) + continue; + lbp = cp; + for (; *cp && *cp != ')' && *cp != ' '; ++cp) + continue; + } + else + for (cp = lbp + 1; + *cp && *cp != '(' && *cp != ' '; ++cp) + continue; + savedc = *cp; + *cp = EOS; + (void)strcpy(tok, lbp); + *cp = savedc; + getline(); + pfnote(tok, lineno); + } + /*NOTREACHED*/ +} diff --git a/usr.bin/global/gctags/print.c b/usr.bin/global/gctags/print.c new file mode 100644 index 0000000..692d36b --- /dev/null +++ b/usr.bin/global/gctags/print.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)print.c 8.3 (Berkeley) 4/2/94"; +#endif /* LIBC_SCCS and not lint */ + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "ctags.h" + +/* + * getline -- + * get the line the token of interest occurred on, + * prepare it for printing. + */ +void +getline() +{ + long saveftell; + int c; + int cnt; + char *cp; + + saveftell = ftell(inf); + (void)fseek(inf, lineftell, SEEK_SET); + if (xflag) + for (cp = lbuf; GETC(!=, '\n'); *cp++ = c) + continue; + /* + * do all processing here, so we don't step through the + * line more than once; means you don't call this routine + * unless you're sure you've got a keeper. + */ + else for (cnt = 0, cp = lbuf; GETC(!=, EOF) && cnt < ENDLINE; ++cnt) { + if (c == '\\') { /* backslashes */ + if (cnt > ENDLINE - 2) + break; + *cp++ = '\\'; *cp++ = '\\'; + ++cnt; + } + else if (c == (int)searchar) { /* search character */ + if (cnt > ENDLINE - 2) + break; + *cp++ = '\\'; *cp++ = c; + ++cnt; + } + else if (c == '\n') { /* end of keep */ + *cp++ = '$'; /* can find whole line */ + break; + } + else + *cp++ = c; + } + *cp = EOS; + (void)fseek(inf, saveftell, SEEK_SET); +} + +/* + * put_entries -- + * write out the tags + */ +void +put_entries(node) + NODE *node; +{ + + if (node->left) + put_entries(node->left); + if (vflag) + printf("%s %s %d\n", + node->entry, node->file, (node->lno + 63) / 64); + else if (xflag) +#ifdef MODIFY + /* separate 'entry' and 'lno' */ + if (strlen(node->entry) >= 16 && node->lno >= 1000) + printf("%-16s %4d %-16s %s\n", + node->entry, node->lno, node->file, node->pat); + else /* for compatibility */ +#endif + printf("%-16s%4d %-16s %s\n", + node->entry, node->lno, node->file, node->pat); + else + fprintf(outf, "%s\t%s\t%c^%s%c\n", + node->entry, node->file, searchar, node->pat, searchar); + if (node->right) + put_entries(node->right); +} diff --git a/usr.bin/global/gctags/test/ctags.test b/usr.bin/global/gctags/test/ctags.test new file mode 100644 index 0000000..1f334ac --- /dev/null +++ b/usr.bin/global/gctags/test/ctags.test @@ -0,0 +1,67 @@ +int bar = (1 + 5); + +FOO("here is a #define test: ) {"); +char sysent[20]; +int nsysent = sizeof (sysent) / sizeof (sysent[0]); +/* + * now is the time for a comment. + * four lines in length... + */struct struct_xtra{int list;};r4(x,y){};typedef struct{int bar;}struct_xxe; +#define FOO BAR +struct struct_three { + int list; +}; +#define SINGLE +int BAD(); +enum color {red, green, gold, brown}; +char qq[] = " quote(one,two) {int bar;} "; +typedef struct { + int bar; + struct struct_two { + int foo; + union union_3 { + struct struct_three entry; + char size[25]; + }; + struct last { + struct struct_three xentry; + char list[34]; + }; + }; +} struct_one; +#define TWOLINE ((MAXLIST + FUTURE + 15) \ + / (time_to_live ? 3 : 4)) +#if (defined(BAR)) +int bar; +#endif +#define MULTIPLE {\ + multiple(one,two); \ + lineno++; \ + callroute(one,two); \ +} +#if defined(BAR) +int bar; +#endif +union union_one { + struct struct_three s3; + char foo[25]; +}; +#define XYZ(A,B) (A + B / 2) * (3 - 26 + l_lineno) +routine1(one,two) /* comments here are fun... */ + struct { + int entry; + char bar[34]; + } *one; + char two[10]; +{ +typedef unsigned char u_char; + register struct buf *bp; + five(one,two); +} + routine2 (one,two) { puts("hello\n"); } + routine3 +(one, +two) { puts("world\n"); } +routine4(int one, char (*two)(void)) /* test ANSI arguments */ +{ +} diff --git a/usr.bin/global/gctags/tree.c b/usr.bin/global/gctags/tree.c new file mode 100644 index 0000000..831691a --- /dev/null +++ b/usr.bin/global/gctags/tree.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)tree.c 8.3 (Berkeley) 4/2/94"; +#endif /* LIBC_SCCS and not lint */ + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ctags.h" + +static void add_node __P((NODE *, NODE *)); +static void free_tree __P((NODE *)); + +/* + * pfnote -- + * enter a new node in the tree + */ +void +pfnote(name, ln) + char *name; + int ln; +{ + NODE *np; + char *fp; + char nbuf[MAXTOKEN]; + + /*NOSTRICT*/ + if (!(np = (NODE *)malloc(sizeof(NODE)))) { + fprintf(stderr, "too many entries to sort"); + put_entries(head); + free_tree(head); + /*NOSTRICT*/ + if (!(head = np = (NODE *)malloc(sizeof(NODE)))) { + fprintf(stderr, "gctags: out of space\n"); + exit(1); + } + } + if (!xflag && !strcmp(name, "main")) { + if (!(fp = strrchr(curfile, '/'))) + fp = curfile; + else + ++fp; + (void)sprintf(nbuf, "M%s", fp); + fp = strrchr(nbuf, '.'); + if (fp && !fp[2]) + *fp = EOS; + name = nbuf; + } + if (!(np->entry = strdup(name))) { + fprintf(stderr, "gctags: out of space\n"); + exit(1); + } + np->file = curfile; + np->lno = ln; + np->left = np->right = 0; + if (!(np->pat = strdup(lbuf))) { + fprintf(stderr, "gctags: out of space\n"); + exit(1); + } + if (!head) + head = np; + else + add_node(np, head); +} + +static void +add_node(node, cur_node) + NODE *node, + *cur_node; +{ + int dif; + + dif = strcmp(node->entry, cur_node->entry); +#ifdef GTAGS + if (!Dflag && !dif) /* -D option allows duplicate entries. */ +#else + if (!dif) +#endif + { + if (node->file == cur_node->file) { + if (!wflag) + fprintf(stderr, "Duplicate entry in file %s, line %d: %s\nSecond entry ignored\n", node->file, lineno, node->entry); + return; + } + if (!cur_node->been_warned) + if (!wflag) + fprintf(stderr, "Duplicate entry in files %s and %s: %s (Warning only)\n", node->file, cur_node->file, node->entry); + cur_node->been_warned = YES; + } + else if (dif < 0) + if (cur_node->left) + add_node(node, cur_node->left); + else + cur_node->left = node; + else if (cur_node->right) + add_node(node, cur_node->right); + else + cur_node->right = node; +} + +static void +free_tree(node) + NODE *node; +{ + while (node) { + if (node->right) + free_tree(node->right); + free(node); + node = node->left; + } +} diff --git a/usr.bin/global/gctags/yacc.c b/usr.bin/global/gctags/yacc.c new file mode 100644 index 0000000..9dcdd5a --- /dev/null +++ b/usr.bin/global/gctags/yacc.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)yacc.c 8.3 (Berkeley) 4/2/94"; +#endif /* LIBC_SCCS and not lint */ + +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#include "ctags.h" + +/* + * y_entries: + * find the yacc tags and put them in. + */ +void +y_entries() +{ + int c; + char *sp; + bool in_rule; + char tok[MAXTOKEN]; + + in_rule = NO; + + while (GETC(!=, EOF)) + switch (c) { + case '\n': + SETLINE; + /* FALLTHROUGH */ + case ' ': + case '\f': + case '\r': + case '\t': + break; + case '{': + if (skip_key('}')) + in_rule = NO; + break; + case '\'': + case '"': + if (skip_key(c)) + in_rule = NO; + break; + case '%': + if (GETC(==, '%')) + return; + (void)ungetc(c, inf); + break; + case '/': + if (GETC(==, '*')) + skip_comment(); + else + (void)ungetc(c, inf); + break; + case '|': + case ';': + in_rule = NO; + break; + default: + if (in_rule || (!isalpha(c) && c != '.' && c != '_')) + break; + sp = tok; + *sp++ = c; + while (GETC(!=, EOF) && (intoken(c) || c == '.')) + *sp++ = c; + *sp = EOS; + getline(); /* may change before ':' */ + while (iswhite(c)) { + if (c == '\n') + SETLINE; + if (GETC(==, EOF)) + return; + } + if (c == ':') { + pfnote(tok, lineno); + in_rule = YES; + } + else + (void)ungetc(c, inf); + } +} + +/* + * toss_yysec -- + * throw away lines up to the next "\n%%\n" + */ +void +toss_yysec() +{ + int c; /* read character */ + int state; + + /* + * state == 0 : waiting + * state == 1 : received a newline + * state == 2 : received first % + * state == 3 : recieved second % + */ + lineftell = ftell(inf); + for (state = 0; GETC(!=, EOF);) + switch (c) { + case '\n': + ++lineno; + lineftell = ftell(inf); + if (state == 3) /* done! */ + return; + state = 1; /* start over */ + break; + case '%': + if (state) /* if 1 or 2 */ + ++state; /* goto 3 */ + break; + default: + state = 0; /* reset */ + break; + } +} diff --git a/usr.bin/global/global/Makefile b/usr.bin/global/global/Makefile new file mode 100644 index 0000000..256ea71 --- /dev/null +++ b/usr.bin/global/global/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 1.0 (Berkeley) 4/21/96 + +MAN1= global.1 + +beforeinstall: + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${.CURDIR}/global.pl ${DESTDIR}/usr/bin/global + +.include <bsd.prog.mk> diff --git a/usr.bin/global/global/global.1 b/usr.bin/global/global/global.1 new file mode 100644 index 0000000..f86f40a --- /dev/null +++ b/usr.bin/global/global/global.1 @@ -0,0 +1,130 @@ +.\" +.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Shigio Yamaguchi. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd Jul 28, 1996 +.Dt GLOBAL 1 +.Os BSD 4 +.Sh NAME +.Nm global +.Nd print the locations of specified function in C and Yacc source files. +.Sh SYNOPSIS +.Nm global +.Op Fl acrx +.Ar name +.Sh DESCRIPTION +.Nm Global +find the locatins of specified function in C and Yacc source files. +.Nm Global +can treat a source tree, that is, a directory that has subdirectories and +source files. +You can get the relative path of objects from anywhere within the tree. + +.Nm Global +can locate not only function definitions but also function references and +allow duplicate entries too. +.Pp +In advance of using this command, you must execute +.Xr gtags 1 +at the root directory of the source tree. +.Pp +The following options are available: +.Bl -tag -width Ds +.It Fl a +print absolute path name. By default, print relative path name. +.It Fl c +print candidate function names which start with specified string. +If string is not specified, print all function names. +.It Fl r +print the locations of function references. By default, print function +definitions. +.It Fl x +In addition to the default output, produce the line number and +the line contents. +.It Ar name +function name. It can include perl's regular expression. +.Sh FILES +.Bl -tag -width tags -compact +.It Pa GTAGS +tags file for function definitions. +.It Pa GRTAGS +tags file for function references. +.El +.Sh ENVIRONMENT +The following environment variables affect the execution of global. +.Pp +.Bl -tag -width indent +.It Ev GTAGSROOT +The directory which is the root of source tree. +.It Ev GTAGSDBPATH +The directory on which gtags database exist. This value is ignored +when GTAGSROOT is not defined. +.It Ev GTAGSLIBPATH +If this variable is set, its value is used as the path to search for library +functions. If specified function is not found in a source tree, +global search in these path too. +.Sh EXAMPLES + + % ls -F + Makefile src/ lib/ + % gtags + % global main + src/main.c + % global -x main + main 10 src/main.c main (argc, argv) { + % global -x '^[sg]et' + set_num 20 lib/util.c set_num(values) + get_num 30 lib/util.c get_num() { + % global -rx '^[sg]et' + set_num 113 src/op.c set_num(32); + set_num 225 src/opop.c if (set_num(0) > 0) { + get_num 90 src/op.c while (get_num() > 0) { + % cd lib + % global -rx '^[sg]et' + set_num 113 ../src/op.c set_num(32); + set_num 225 ../src/opop.c if (set_num(0) > 0) { + get_num 90 ../src/op.c while (get_num() > 0) { + % global strlen + % (cd /usr/src/sys; gtags) + % setenv GTAGSLIBPATH /usr/src/sys + % global strlen + ../../../usr/src/sys/libkern/strlen.c + % (cd /usr/src/lib; gtags) + % setenv GTAGSLIBPATH /usr/src/lib:/usr/src/sys + % global strlen + ../../../usr/src/lib/libc/string/strlen.c + +.Sh DIAGNOSTICS +.Nm Global +exits with a non 0 value if an error occurred, 0 otherwise. +.Sh SEE ALSO +.Xr gtags 1 , +.Xr btreeop 1 +.Sh AUTHORS +Shigio Yamaguchi (shigio@wafu.netgate.net) diff --git a/usr.bin/global/global/global.pl b/usr.bin/global/global/global.pl new file mode 100644 index 0000000..f1e0cb9 --- /dev/null +++ b/usr.bin/global/global/global.pl @@ -0,0 +1,213 @@ +#!/usr/bin/perl +# +# Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Shigio Yamaguchi. +# 4. Neither the name of the author nor the names of any co-contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# global.pl 14-Apr-97 +# +sub getcwd { + local($dir); + chop($dir = `/bin/pwd`); + $dir; +} +$com = $0; +$com =~ s/.*\///; +$usage = "usage:\t$com [-a][-r][-x] pattern\n\t$com -c [name]\n"; +# +# options check +# +while ($ARGV[0] =~ /^-/) { + $opt = shift; + if ($opt =~ /a/) { $aflag = 1; } + if ($opt =~ /c/) { $cflag = 1; } + if ($opt =~ /r/) { $rflag = 1; } + if ($opt =~ /x/) { $xflag = 1; } +} +if (@ARGV == 0) { + die($usage) if (! $cflag); +} elsif ($ARGV[0] =~ /[][.*\^\$+?|(){}\\]/) { # include regular expression ? + $regex = 1; +} +if ($cflag) { + die($usage) if ($aflag || $rflag || $xflag); + die("$com: regular expression not allowed with -c option.\n") if ($regex); +} +$current = &getcwd; +# +# get $dbpath and $root +# +if (defined($ENV{'GTAGSROOT'})) { + $root = $ENV{'GTAGSROOT'}; + if (defined($ENV{'GTAGSDBPATH'})) { + $dbpath = $ENV{'GTAGSDBPATH'}; + } else { + $dbpath = $root; + } + unless ($current =~ /$root/) { + die("$com: illegal GTAGSROOT.\n"); + } + chdir($dbpath) || die("$com: directory $dbpath not found.\n"); + $dbpath = &getcwd; + chdir($current); + chdir($root) || die("$com: directory $root not found.\n"); + $root = &getcwd; +} +chdir($current) || die("$com: cannot return current directory.\n"); +$gtagsname = ($rflag) ? 'GRTAGS' : 'GTAGS'; +# +# make a sed command to make paths into relative +# +if (! defined($root)) { + chdir($current); + while (! -r $gtagsname && ! -r "obj/$gtagsname") { + if (&getcwd =~ m!^/$!) { die "$com: $gtagsname not found.\n"; } + chdir('..'); + } + $dbpath = $root = &getcwd; + $dbpath = "$dbpath/obj" if (! -r $gtagsname); +} +$cur = $current; +$cur =~ s!$root!!; +$cur =~ s!^/!!; +@step = split('/', $cur); +$downpath = '\\.\\./' x @step; +push(@com, "-e 's!\\./!$downpath!'"); +foreach $step (@step) { + push(@com, "-e 's!\\.\\./$step/!!'"); +} +# +# complete function name +# +if ($cflag) { + open(PIPEIN, "btreeop $dbpath/GTAGS | awk '{print \$1}' | sort | uniq |") || die("$com: btreeop cannot exec.\n"); + while (<PIPEIN>) { + print if (@ARGV == 0 || $_ =~ /^$ARGV[0]/o); + } + close(PIPEIN); + exit(0); +} +# +# search in current source tree. +# +$cnt = &search($ARGV[0], $dbpath, $gtagsname, @com); +# +# search in library path. +# +if ($cnt == 0 && ! $regex && ! $rflag && defined($ENV{'GTAGSLIBPATH'})) { + foreach $lib (split(':', $ENV{'GTAGSLIBPATH'})) { + next unless (-f "$lib/GTAGS"); + next if ($dbpath eq $lib); + chdir($lib) || die("$com: cannot chdir to $lib.\n"); + $dbpath = &getcwd; + $common = &common($dbpath, $current); + $up = $dbpath; + $up =~ s/$common//; + $down = $current; + $down =~ s/$common//; + $down =~ s![^/]+!..!g; + next if ($down eq '' || $up eq ''); + $cnt = &search($ARGV[0], $dbpath, 'GTAGS', ("-e 's!\\./!$down/$up/!'")); + last if ($cnt > 0); + } +} +exit(0); +# +# common: extract a common part of two paths. +# +# i) $p1, $p2 paths +# r) common part +# +sub common { + local($p1, $p2) = @_; + local(@p1, @p2, @common, $common); + + @p1 = split('/', $p1); + @p2 = split('/', $p2); + while (@p1 && @p2 && $p1[0] eq $p2[0]) { + push(@common, shift @p1); + shift @p2; + } + $common = join('/', @common); + $common .= '/'; + $common; +} +# +# search: search specified function +# +# i) $pattern search pattern +# i) $dbpath where GTAGS exist +# i) $gtagsname gtags name (GTAGS or GRTAGS) +# i) @com sed's command +# gi) $xflag -x option +# gi) $rflag -r option +# gi) $regex regular expression +# r) count of output lines +# +sub search { + local($pattern, $dbpath, $gtagsname, @com) = @_; + local($cnt); + # + # make input filter + # + if ($regex) { # regular expression + $infilter = "btreeop $dbpath/$gtagsname |"; + } else { + $infilter = "btreeop -K '$pattern' $dbpath/$gtagsname |"; + } + # + # make output filter + # gtags fields is same to ctags -x format. + # 0:tag, 1:lineno, 2:filename, 3: pattern. + # + if ($xflag) { + $outfilter = "| sort +0b -1 +2b -3 +1n -2"; + } else { + $outfilter = "| awk '{print \$3}' | sort | uniq"; + } + # + # if absolute path needed + # + if ($aflag) { + @com = ("-e 's!\\.!$dbpath!'"); + } + $outfilter .= "| sed @com"; + open(PIPEIN, $infilter) || die("$com: database not found.\n"); + open(PIPEOUT, $outfilter) || die("$com: pipe cannot open.\n"); + $cnt = 0; + while (<PIPEIN>) { + ($tag) = split; + if (! $regex || $tag =~ /$pattern/o) { + $cnt++; + print PIPEOUT $_; + } + } + close(PIPEIN); + close(PIPEOUT); + $cnt; +} diff --git a/usr.bin/global/gtags/Makefile b/usr.bin/global/gtags/Makefile new file mode 100644 index 0000000..53355f3 --- /dev/null +++ b/usr.bin/global/gtags/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 1.0 (Berkeley) 4/21/96 + +MAN1= gtags.1 + +beforeinstall: + install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${.CURDIR}/gtags.sh ${DESTDIR}/${BINDIR}/gtags + +.include <bsd.prog.mk> diff --git a/usr.bin/global/gtags/gtags.1 b/usr.bin/global/gtags/gtags.1 new file mode 100644 index 0000000..dca7a42 --- /dev/null +++ b/usr.bin/global/gtags/gtags.1 @@ -0,0 +1,81 @@ +.\" +.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Shigio Yamaguchi. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd Feb 17, 1997 +.Dt GTAGS 1 +.Os BSD 4 +.Sh NAME +.Nm gtags +.Nd create GTAGS, GRTAGS file +.Sh SYNOPSIS +.Nm gtags +.Op Fl e +.Op Fl s +.Op Ar dbpath +.Sh DESCRIPTION +.Nm Gtags +makes GTAGS, GRTAGS files for global(1). +.Nm Gtags +trace subdirectories, read source files, +locate the functions and save the information into tag files. +C, yacc and assembler source files are supported. +You should execute this command at the root of the source tree. +.Pp +If your source directory is on a read only device like CDROM, specify +.Ar dbpath +of the directory on which make tags files. +.Pp +.Bl -tag -width Ds +.It Fl e +force a function to end when reach a '}' at the first column in C source file. +.It Fl s +treat assembler source file (*.s, *.S). +.Sh FILES +.Bl -tag -width tags -compact +.It Pa GTAGS +tags file for function definitions. +.It Pa GRTAGS +tags file for function references. +.El +.Sh DIAGNOSTICS +.Nm Gtags +exits with a value of 1 if an error occurred, 0 otherwise. +.Sh SEE ALSO +.Xr global 1 , +.Xr btreeop 1 , +.Xr gctags 1 +.Sh BUG +GTAGS, GRTAGS are very large. In advance, check the space of your disk. + +Assembler support is far from completeness. It extracts only ENTRY() +and ALTENTRY() from source file. Probably valid only for FreeBSD and Linux +kernel source. +.Sh AUTHORS +Shigio Yamaguchi (shigio@wafu.netgate.net) diff --git a/usr.bin/global/gtags/gtags.sh b/usr.bin/global/gtags/gtags.sh new file mode 100644 index 0000000..85458bc --- /dev/null +++ b/usr.bin/global/gtags/gtags.sh @@ -0,0 +1,98 @@ +#!/bin/sh +# +# Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Shigio Yamaguchi. +# 4. Neither the name of the author nor the names of any co-contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# gtags.sh 17-Feb-97 +# +com=`echo $0 | sed 's/.*\///'` # command name +usage="usage: $com [-e][-s][dbpath]" +# +# ctags flag +# +eflag= +sflag= +while :; do + case $1 in + -*) + if echo $1 | grep '[^-es]' >/dev/null; then + echo $usage >/dev/tty; exit 1 + fi + case $1 in + -*e*) eflag=e;; + esac + case $1 in + -*s*) sflag=1;; + esac + shift;; + *) + break;; + esac +done +export eflag sflag +case $1 in +"") dbpath=".";; +*) dbpath=$1;; +esac +if [ -f $dbpath/GTAGS -a -f $dbpath/GRTAGS ]; then + if [ ! -w $dbpath/GTAGS ]; then + echo "$com: cannot write to GTAGS." + exit 1 + elif [ ! -w $dbpath/GRTAGS ]; then + echo "$com: cannot write to GRTAGS." + exit 1 + fi +elif [ ! -w $dbpath ]; then + echo "$com: cannot write to the directory $dbpath." + exit 1 +fi +# +# make global database +# +for db in GTAGS GRTAGS; do + # currently only *.c *.h *.y are supported. + # *.s *.S is valid only when -s option specified. + find . -type f -name "*.[chysS]" -print | while read f; do + case $f in + *y.tab.c|*y.tab.h) + continue;; + *.s|*.S) + [ ${sflag}x = x -o $db = GRTAGS ] && continue + perl -ne '($nouse, $tag) = /^(ENTRY|ALTENTRY)\((\w+)\)/; + if ($tag) {printf("%-16s%4d %-16s %s", $tag, $., $ARGV, $_)} ' $f + continue;; + esac + case $db in + GRTAGS) flag=${eflag}Dxr;; + GTAGS) flag=${eflag}Dx;; + esac + GTAGDBPATH=$dbpath gctags -$flag $f || exit 1 + done | btreeop -C $dbpath/$db +done +exit 0 diff --git a/usr.bin/global/htags/Makefile b/usr.bin/global/htags/Makefile new file mode 100644 index 0000000..f53639a --- /dev/null +++ b/usr.bin/global/htags/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 1.0 (Berkeley) 4/21/96 + +MAN1= htags.1 + +beforeinstall: + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${.CURDIR}/htags.pl ${DESTDIR}/usr/bin/htags + +.include <bsd.prog.mk> diff --git a/usr.bin/global/htags/htags.1 b/usr.bin/global/htags/htags.1 new file mode 100644 index 0000000..f82b37c --- /dev/null +++ b/usr.bin/global/htags/htags.1 @@ -0,0 +1,99 @@ +.\" +.\" Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Shigio Yamaguchi. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd Feb 17, 1997 +.Dt HTAGS 1 +.Os BSD 4 +.Sh NAME +.Nm htags +.Nd generate hypertext from C and Yacc source code +.Sh SYNOPSIS +.Nm htags +.Op Fl a +.Op Fl v +.Op Fl w +.Op Fl d Ar tagdir +.Op Fl t Ar title +.Op Ar dir +.Sh DESCRIPTION +.Nm Htags +makes hypertext from C and Yacc source code using GLOBAL database. +.Pp +In advance of using this command, you must execute +.Xr gtags 1 +at the root directory of the source tree. +Then you can execute +.Nm htags +at the same place. +.Nm Htags +makes HTML directory and generate hypertext in it. +.Pp +You can start browsing from 'HTML/index.html'. +Once hypertext generated, you can move it anywhere and browse it +by any browsers. +.Pp +.br +.Bl -tag -width Ds +.It Fl a +make alphabetical function index. It's suitable to large project. +.It Fl v +verbose mode. +.It Fl w +print warning message. +.It Fl d Ar tagdir +the directory in which GTAGS and GRTAGS exist. Default is current directory. +.It Fl t Ar title +Tile of this hypertext. Default is the last conponent of current path. +.It Ar dir +the directory in which hypertext generated. Default is current directory. +.Sh EXAMPLES + % cd /usr/src/sys + # gtags -se + # htags -vat 'Welcom to FreeBSD kernel source tour!' + % lynx HTML/index.html +.Sh FILES +.Bl -tag -width tags -compact +.It Pa HTML/index.html +Index file. +.It Pa GTAGS +tags file for function definitions. +.It Pa GRTAGS +tags file for function references. +.El +.Sh DIAGNOSTICS +.Nm Htags +exits with a value of 1 if an error occurred, 0 otherwise. +.Sh SEE ALSO +.Xr gtags 1 , +.Xr btreeop 1 +.Sh BUG +Generated hypertext is VERY LARGE. In advance, check the space of your disk. +.Sh AUTHORS +Shigio Yamaguchi (shigio@wafu.netgate.net) diff --git a/usr.bin/global/htags/htags.pl b/usr.bin/global/htags/htags.pl new file mode 100755 index 0000000..9c1a275 --- /dev/null +++ b/usr.bin/global/htags/htags.pl @@ -0,0 +1,1043 @@ +#!/usr/bin/perl +# +# Copyright (c) 1996, 1997 Shigio Yamaguchi. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Shigio Yamaguchi. +# 4. Neither the name of the author nor the names of any co-contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# htags.pl 5-Apr-97 +# +$com = $0; +$com =~ s/.*\///; +$usage = "usage: $com [-a][-v][-w][-t title][-d tagdir][dir]"; +#------------------------------------------------------------------------- +# CONFIGURATION +#------------------------------------------------------------------------- +# columns of line number +$ncol = 4; +# font +$comment_begin = '<I><FONT COLOR=green>'; # /* ... */ +$comment_end = '</FONT></I>'; +$sharp_begin = '<FONT COLOR=darkred>'; # #define, #include or so on +$sharp_end = '</FONT>'; +$brace_begin = '<FONT COLOR=blue>'; # { ... } +$brace_end = '</FONT>'; +$reserved_begin = '<B>'; # if, while, for or so on +$reserved_end = '</B>'; +# reserved words +$reserved_words = "auto|break|case|char|continue|default|do|double|else|extern|float|for|goto|if|int|long|register|return|short|sizeof|static|struct|switch|typedef|union|unsigned|void|while"; +# temporary directory +$tmp = '/tmp'; +#------------------------------------------------------------------------- +# DEFINITION +#------------------------------------------------------------------------- +# unit for a path +$SEP = ' '; # source file path must not include $SEP charactor +$ESCSEP = &escape($SEP); +$SRCS = 'S'; +$DEFS = 'D'; +$REFS = 'R'; +$FILES = 'files'; +$FUNCS = 'funcs'; +#------------------------------------------------------------------------- +# JAVASCRIPT PARTS +#------------------------------------------------------------------------- +# escaped angle +$langle = sprintf("unescape('%s')", &escape('<')); +$rangle = sprintf("unescape('%s')", &escape('>')); +# frame name +$f_mains = 'mains'; # for main view +$f_funcs = 'funcs'; # for function index +$f_files = 'files'; # for file index +$begin_script="<SCRIPT LANGUAGE=javascript>\n<!--\n"; +$end_script="<!-- end of script -->\n</SCRIPT>\n"; +$defaultview= + "// if your browser doesn't support javascript, write a BASE tag statically.\n" . + "if (parent.frames.length)\n" . + " document.write($langle+'BASE TARGET=$f_mains'+$rangle)\n"; +$rewrite_href_funcs = + "// IE3.0 seems to be not able to treat following code.\n" . + "if (parent.frames.length && parent.$f_funcs == self) {\n" . + " document.links[0].href = '../funcs.html';\n" . + " document.links[document.links.length - 1].href = '../funcs.html';\n" . + "}\n"; +$rewrite_href_files = + "// IE3.0 seems to be not able to treat following code.\n" . + "if (parent.frames.length && parent.$f_files == self) {\n" . + " document.links[0].href = '../files.html';\n" . + " document.links[document.links.length - 1].href = '../files.html';\n" . + "}\n"; +#------------------------------------------------------------------------- +# UTIRITIES +#------------------------------------------------------------------------- +sub getcwd { + local($dir) = `/bin/pwd`; + chop($dir); + $dir; +} +sub date { + local($date) = `date`; + chop($date); + $date; +} +sub error { + local($msg) = @_; + &clean(); + die($msg); +} +sub clean { + &anchor'finish(); + &cache'close(); +} +sub escape { + local($c) = @_; + '%' . sprintf("%x", ord($c)); +} +#------------------------------------------------------------------------- +# PROCESS START +#------------------------------------------------------------------------- +# +# options check +# +$aflag = $vflag = $wflag = $sflag = ''; # $sflag is set internally +while ($ARGV[0] =~ /^-/) { + $opt = shift; + if ($opt =~ /[^-avwdt]/) { + print STDERR "$usage\n"; + exit 1; + } + if ($opt =~ /a/) { $aflag = 1; } + if ($opt =~ /v/) { $vflag = 1; } + if ($opt =~ /w/) { $wflag = 1; } + if ($opt =~ /t/) { + $opt = shift; + last if ($opt eq ''); + $title = $opt; + } elsif ($opt =~ /d/) { + $opt = shift; + last if ($opt eq ''); + $dbpath = $opt; + } +} +if (!$title) { + @cwd = split('/', &getcwd); + $title = $cwd[$#cwd]; +} +if (!$dbpath) { + $dbpath = '.'; +} +unless (-r "$dbpath/GTAGS" && -r "$dbpath/GRTAGS") { + &error("GTAGS and GRTAGS not found. please type 'gtags[RET]'\n"); +} +$html = &getcwd() . '/HTML'; +if ($ARGV[0]) { + $cwd = &getcwd(); + unless (-w $ARGV[0]) { + &error("$ARGV[0] is not writable directory.\n"); + } + chdir($ARGV[0]) || &error("directory $ARGV[0] not found.\n"); + $html = &getcwd() . '/HTML'; + chdir($cwd) || &error("cannot return directory.\n"); +} +# +# set sflag if *.[sS] are included. +# +open(CHECK, "btreeop $dbpath/GTAGS |") || &error("btreeop $dbpath/GTAGS failed.\n"); +while (<CHECK>) { + local($tag, $lno, $filename) = split; + if ($filename =~ /\.[sS]$/) { + $'sflag = 1; + last; + } +} +close(CHECK); +#------------------------------------------------------------------------- +# MAKE FILES +#------------------------------------------------------------------------- +# HTML/help.html ... help file (2) +# HTML/funcs.html ... function index (3) +# HTML/$FUNCS/* ... function index (3) +# HTML/$REFS/* ... referencies (4) +# HTML/$DEFS/* ... definitions (4) +# HTML/files.html ... file index (5) +# HTML/$FILES/* ... file index (5) +# HTML/index.html ... index file (6) +# HTML/mains.html ... main index (7) +# HTML/$SRCS/ ... source files (8) +#------------------------------------------------------------------------- +print STDERR "[", &date, "] ", "Htags started\n" if ($vflag); +# +# (1) make directories +# +print STDERR "[", &date, "] ", "(1) making directories ...\n" if ($vflag); +mkdir($html, 0777) || &error("cannot make directory <$html>.\n") if (! -d $html); +foreach $d ($SRCS, $REFS, $DEFS, $FILES, $FUNCS) { + mkdir("$html/$d", 0775) || &error("cannot make HTML directory\n") if (! -d "$html/$d"); +} +# +# (2) make help file +# +print STDERR "[", &date, "] ", "(2) making help.html ...\n" if ($vflag); +&makehelp("$html/help.html"); +# +# (3) make function index (funcs.html and $FUNCS/*) +# PRODUCE @funcs +# +print STDERR "[", &date, "] ", "(3) making function index ...\n" if ($vflag); +$func_total = &makefuncindex("$html/funcs.html"); +print STDERR "Total $func_total functions.\n" if ($vflag); +# +# (4) make function entries ($DEFS/* and $REFS/*) +# MAKING TAG CACHE +# +print STDERR "[", &date, "] ", "(4) making duplicate entries ...\n" if ($vflag); +sub suddenly { &clean(); exit 1} +$SIG{'INT'} = 'suddenly'; +$SIG{'QUIT'} = 'suddenly'; +$SIG{'TERM'} = 'suddenly'; +&cache'open(100000); +$func_total = &makedupindex($func_total); +print STDERR "Total $func_total functions.\n" if ($vflag); +# +# (5) make file index (files.html and $FILES/*) +# PRODUCE @files +# +print STDERR "[", &date, "] ", "(5) making file index ...\n" if ($vflag); +$file_total = &makefileindex("$html/files.html"); +print STDERR "Total $file_total files.\n" if ($vflag); +# +# [#] make a common part for mains.html and index.html +# USING @funcs @files +# +print STDERR "[", &date, "] ", "(#) making a common part ...\n" if ($vflag); +$index = &makecommonpart($title); +# +# (6)make index file (index.html) +# +print STDERR "[", &date, "] ", "(6) making index file ...\n" if ($vflag); +&makeindex("$html/index.html", $title, $index); +# +# (7) make main index (mains.html) +# +print STDERR "[", &date, "] ", "(7) making main index ...\n" if ($vflag); +&makemainindex("$html/mains.html", $index); +# +# (#) make anchor database +# +print STDERR "[", &date, "] ", "(#) making temporary database ...\n" if ($vflag); +&anchor'create(); +# +# (8) make HTML files ($SRCS/*) +# USING TAG CACHE +# +print STDERR "[", &date, "] ", "(8) making hypertext from source code ...\n" if ($vflag); +&makehtml($file_total); +&clean(); +print STDERR "[", &date, "] ", "Done.\n" if ($vflag); +exit 0; +#------------------------------------------------------------------------- +# SUBROUTINES +#------------------------------------------------------------------------- +# +# makehelp: make help file +# +sub makehelp { + local($file) = @_; + + open(HELP, ">$file") || &error("cannot make help file.\n"); + print HELP "<HTML>\n<HEAD><TITLE>HELP</TITLE></HEAD>\n<BODY>\n"; + print HELP "<H2>Usage of Links</H2>\n"; + print HELP "<PRE>/* [<][>][^][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); +} +# +# makefuncindex: make function index (including alphabetic index) +# +# i) file function index file +# go) @funcs +# +sub makefuncindex { + local($file) = @_; + local($count) = 0; + + open(FUNCTIONS, ">$file") || &error("cannot make function index <$file>.\n"); + print FUNCTIONS "<HTML>\n<HEAD><TITLE>FUNCTION INDEX</TITLE>\n"; + print FUNCTIONS "$begin_script$defaultview$end_script</HEAD>\n<BODY>\n"; + print FUNCTIONS "<H2>FUNCTION INDEX</H2>\n"; + print FUNCTIONS "<OL>\n" if (!$aflag); + local($old) = select(FUNCTIONS); + open(TAGS, "btreeop $dbpath/GTAGS | awk '{print \$1}' | sort | uniq |") || &error("btreeop $dbpath/GTAGS failed.\n"); + local($alpha) = ''; + @funcs = (); # [A][B][C]... + while (<TAGS>) { + $count++; + chop; + local($tag) = $_; + print STDERR " [$count] adding $tag\n" if ($vflag); + if ($aflag && $alpha ne substr($tag, 0, 1)) { + if ($alpha) { + print ALPHA "</OL>\n"; + print ALPHA "<A HREF=../mains.html TARGET=_self>[index]</A>\n"; + print ALPHA "$begin_script$rewrite_href_funcs$end_script"; + print ALPHA "</BODY>\n</HTML>\n"; + close(ALPHA); + } + $alpha = substr($tag, 0, 1); + push(@funcs, "<A HREF=$FUNCS/$alpha.html TARGET=_self>[$alpha]</A>\n"); + open(ALPHA, ">$html/$FUNCS/$alpha.html") || &error("cannot make alphabetical function index.\n"); + print ALPHA "<HTML>\n<HEAD><TITLE>$alpha</TITLE>\n"; + print ALPHA "$begin_script$defaultview$end_script"; + print ALPHA "</HEAD>\n<BODY>\n<H2>[$alpha]</H2>\n"; + print ALPHA "<A HREF=../mains.html TARGET=_self>[index]</A>\n"; + print ALPHA "<OL>\n"; + select(ALPHA); + } + open(LIST, "btreeop -K $tag $dbpath/GTAGS |") || &error("btreeop -K $tag $dbpath/GTAGS failed.\n");; + local($line1, $line2); + if ($line1 = <LIST>) { + $line2 = <LIST>; + } + close(LIST); + if ($line2) { + print "<LI><A HREF=", ($aflag) ? "../" : "", "D/$tag.html>$tag</A>\n"; + } else { + local($nouse, $lno, $filename) = split(/[ \t]+/, $line1); + $nouse = ''; # to make perl quiet + $filename =~ s/^\.\///; + $filename =~ s/\//$ESCSEP/g; + print "<LI><A HREF=", ($aflag) ? "../" : "", "$SRCS/$filename.html#$lno>$tag</A>\n"; + } + close(LIST); + } + close(TAGS); + select($old); + if ($aflag) { + print ALPHA "</OL>\n"; + print ALPHA "<A HREF=../mains.html TARGET=_self>[index]</A>\n"; + print ALPHA "$begin_script$rewrite_href_funcs$end_script"; + print ALPHA "</BODY>\n</HTML>\n"; + close(ALPHA); + + print FUNCTIONS @funcs; + } + print FUNCTIONS "</OL>\n" if (!$aflag); + print FUNCTIONS "</BODY>\n</HTML>\n"; + close(FUNCTIONS); + $count; +} +# +# makedupindex: make duplicate entries index ($DEFS/* and $REFS/*) +# +# i) $total functions total +# r) $count +# +sub makedupindex { + local($total) = @_; + local($count) = 0; + + open(TAGS, "btreeop $dbpath/GTAGS | awk '{print \$1}' | sort | uniq |") || &error("btreeop $dbpath/GTAGS failed.\n"); + while (<TAGS>) { + $count++; + chop; + local($tag) = $_; + print STDERR " [$count/$total] adding $tag\n" if ($vflag); + foreach $db ('GTAGS', 'GRTAGS') { + open(LIST, "btreeop -K $tag $dbpath/$db | sort +0b -1 +2b -3 +1n -2|") || &error("btreeop -K $tag $dbpath/$db failed.\n");; + local($line1, $line2); + if ($line1 = <LIST>) { + $line2 = <LIST>; + } + &cache'put($db, $tag, ($line2) ? '' : $line1) if ($line1); + if ($line2) { # two or more entries exist + local($type) = ($db eq 'GTAGS') ? $'DEFS : $'REFS; + open(FILE, ">$html/$type/$tag.html") || &error("cannot make file <$html/$type/$tag.html>.\n"); + print FILE "<HTML>\n<HEAD><TITLE>$tag</TITLE></HEAD>\n<BODY>\n"; + print FILE "<PRE>\n"; + for (;;) { + if ($line1) { + $_ = $line1; + $line1 = ''; + } elsif ($line2) { + $_ = $line2; + $line2 = ''; + } elsif (!($_ = <LIST>)) { + last; + } + s/\.\///; + s/&/&/g; + s/</</g; + s/>/>/g; + local($nouse, $lno, $filename) = split; + $nouse = ''; # to make perl quiet + $filename =~ s/\//$ESCSEP/g; + s/^$tag/<A HREF=..\/$SRCS\/$filename.html#$lno>$tag<\/A>/; + print FILE; + } + print FILE "</PRE>\n</BODY>\n</HTML>\n"; + close(FILE); + } + close(LIST); + } + } + close(TAGS); + $count; +} +# +# makefileindex: make file index +# +# i) file name +# go) @files +# +sub makefileindex { + local($file) = @_; + local($count) = 0; + + open(FILES, ">$file") || &error("cannot make file <$file>.\n"); + print FILES "<HTML>\n<HEAD><TITLE>FILES</TITLE>\n"; + print FILES "$begin_script$defaultview$end_script"; + print FILES "</HEAD>\n<BODY>\n<H2>FILE INDEX</H2>\n"; + print FILES "<OL>\n"; + local($old) = select(FILES); + open(FIND, "find . -name '*.[chysS]' -print | sort |") || &error("cannot exec find.\n"); + local($lastdir) = ''; + @files = (); + while (<FIND>) { + $count++; + chop; + s/^\.\///; + next if /(y\.tab\.c|y\.tab\.h)$/; + next if (!$'sflag && /\.[sS]$/); + local($filename) = $_; + print STDERR " [$count] adding $filename\n" if ($vflag); + local($dir); + if (index($filename, '/') >= 0) { + @split = split('/'); + $dir = $split[0]; + } else { + $dir = ''; + } + #if ($dir && $dir ne $lastdir) { + if ($dir ne $lastdir) { + if ($lastdir) { + print DIR "</OL>\n"; + print DIR "<A HREF=../mains.html TARGET=_self>[index]</A>\n"; + print DIR "$begin_script$rewrite_href_files$end_script"; + print DIR "</BODY>\n</HTML>\n"; + close(DIR); + } + if ($dir) { + push(@files, "<LI><A HREF=$FILES/$dir.html TARGET=_self>$dir/</A>\n"); + open(DIR, ">$html/$FILES/$dir.html") || &error("cannot make directory index.\n"); + print DIR "<HTML>\n<HEAD><TITLE>$dir/</TITLE>\n"; + print DIR "$begin_script$defaultview$end_script"; + print DIR "</HEAD>\n<BODY>\n<H2>$dir/</H2>\n"; + print DIR "<A HREF=../mains.html TARGET=_self>[index]</A>\n"; + print DIR "<OL>\n"; + } + $lastdir = $dir; + } + local($path) = $filename; + $path =~ s/\//$ESCSEP/g; + if ($dir eq '') { + push(@files, "<LI><A HREF=", ($dir) ? "../" : "", "$SRCS/$path.html>$filename</A>\n"); + } else { + print DIR "<LI><A HREF=../$SRCS/$path.html>$filename</A>\n"; + } + } + close(FIND); + select($old); + if ($lastdir) { + print DIR "</OL>\n"; + print DIR "<A HREF=../mains.html TARGET=_self>[index]</A>\n"; + print DIR "$begin_script$rewrite_href_files$end_script"; + print DIR "</BODY>\n</HTML>\n"; + close(DIR); + } + print FILES @files; + print FILES "</OL>\n"; + print FILES "</BODY>\n</HTML>\n"; + close(FILES); + + $count; +} +# +# makecommonpart: make a common part for mains.html and index.html +# +# gi) @files +# gi) @funcs +# +sub makecommonpart { + local($title) = @_; + local($index) = ''; + + $index .= "<H1><FONT COLOR=#cc0000>$title</FONT></H1>\n"; + $index .= "<P ALIGN=right>"; + $index .= "Last updated " . &date . "<BR>\n"; + $index .= "This hypertext was generated by <A HREF=http://wafu.netgate.net/tama/unix/indexe.html#global TARGET=_top>GLOBAL</A>.<BR>\n"; + $index .= "$begin_script"; + $index .= "if (parent.frames.length && parent.$f_mains == self)\n"; + $index .= " document.write($langle+'A HREF=mains.html TARGET=_top'+$rangle+'[No frame version is here.]'+$langle+'/A'+$rangle)\n"; + $index .= "$end_script"; + $index .= "</P>\n<HR>\n"; + $index .= "<H2>MAINS</H2>\n"; + $index .= "<PRE>\n"; + open(PIPE, "btreeop -K main $dbpath/GTAGS | sort +0b -1 +2b -3 +1n -2 |") || &error("btreeop -K main $dbpath/GTAGS failed.\n"); + while (<PIPE>) { + local($nouse, $lno, $filename) = split; + $nouse = ''; # to make perl quiet + $filename =~ s/^\.\///; + $filename =~ s/\//$ESCSEP/g; + s/(main)/<A HREF=$SRCS\/$filename.html#$lno>$1<\/A>/; + $index .= $_; + } + close(PIPE); + $index .= "</PRE>\n<HR>\n<H2>FUNCTIONS</H2>\n"; + if ($aflag) { + foreach $f (@funcs) { + $index .= $f; + } + } else { + $index .= "<PRE><A HREF=funcs.html>function index</A></PRE>\n"; + } + $index .= "<HR>\n<H2>FILES</H2>\n"; + $index .= "<OL>\n"; + foreach $f (@files) { + $index .= $f; + } + $index .= "</OL>\n<HR>\n"; + $index; +} +# +# makeindex: make index file +# +# i) $file file name +# i) $title title of index file +# i) $index common part +# +sub makeindex { + local($file, $title, $index) = @_; + + open(FRAME, ">$file") || &error("cannot open file <$file>.\n"); + print FRAME "<HTML>\n<HEAD><TITLE>$title</TITLE></HEAD>\n"; + print FRAME "<FRAMESET COLS='200,*'>\n"; + print FRAME "<NOFRAME>\n$index</NOFRAME>\n"; + print FRAME "<FRAMESET ROWS='50%,50%'>\n"; + print FRAME "<FRAME NAME=$f_funcs SRC=funcs.html>\n"; + print FRAME "<FRAME NAME=$f_files SRC=files.html>\n"; + print FRAME "</FRAMESET>\n"; + print FRAME "<FRAME NAME=$f_mains SRC=mains.html>\n"; + print FRAME "</FRAMESET>\n"; + print FRAME "</HTML>\n"; + close(FRAME); +} +# +# makemainindex: make main index +# +# i) $file file name +# i) $index common part +# +sub makemainindex { + local($file, $index) = @_; + + open(INDEX, ">$file") || &error("cannot create file <$file>.\n"); + print INDEX "<HTML>\n<HEAD><TITLE>MAINS</TITLE></HEAD>\n"; + print INDEX "<BODY>\n$index</BODY>\n</HTML>\n"; + close(INDEX); +} +# +# makehtml: make html files +# +sub makehtml { + local($total) = @_; + local($count) = 0; + + open(FIND, "find . -name '*.[chysS]' -print|") || &error("cannot exec find.\n"); + while (<FIND>) { + $count++; + chop; + s/^\.\///; + next if /y\.tab\.c|y\.tab\.h/; + next if (!$'sflag && /\.[sS]$/); + local($path) = $_; + $path =~ s/\//$SEP/g; + print STDERR " [$count/$total] converting $_\n" if ($vflag); + &convert'src2html($_, "$html/$SRCS/$path.html"); + } + close(FIND); +} +#========================================================================= +# CONVERT PACKAGE +#========================================================================= +package convert; +# +# src2html: convert source code into HTML +# +# i) $file source file - Read from +# i) $html HTML file - Write to +# +sub src2html { + local($file, $html) = @_; + local($ncol) = $'ncol; + + open(HTML, ">$html") || &error("cannot create file <$html>.\n"); + local($old) = select(HTML); + # + # load tags belonging to this file. + # + $file =~ s/^\.\///; + &anchor'load($file); + open(C, $file) || &error("cannot open file <$file>.\n"); + # + # print the header + # + print "<HTML>\n<HEAD><TITLE>$file</TITLE></HEAD>\n"; + print "<BODY><A NAME=TOP><H2>$file</H2>\n"; + print &link_format(&anchor'getlinks(0)); + print "\n<HR>\n"; + print "<H2>FUNCTIONS</H2>\n"; + print "This source file includes following functions.\n"; + print "<OL>\n"; + local($lno, $tag, $type); + for (($lno, $tag, $type) = &anchor'first(); $lno; ($lno, $tag, $type) = &anchor'next()) { + print "<LI><A HREF=#$lno>$tag</A>\n" if ($type eq 'D'); + } + print "</OL>\n"; + print "<HR>\n"; + # + # print source code + # + print "<PRE>\n"; + $INCOMMENT = 0; # initial status is out of comment + local($LNO, $TAG, $TYPE) = &anchor'first(); + while (<C>) { + s/\r$//; + s/&/&/g; # '<', '>' and '&' are used for HTML tag + s/</</g; + s/>/>/g; + &protect_line(); # protect quoted char, strings and comments + # painting source code + s/({|})/$'brace_begin$1$'brace_end/g; + $sharp = s/^(#\w+)// ? $1 : ''; # protect macro + s/\b($'reserved_words)\b/$'reserved_begin$1$'reserved_end/go if ($sharp ne '#include'); + s/^/$'sharp_begin$sharp$'sharp_end/ if ($sharp); # recover macro + + local($define_line) = 0; + local(@links) = (); + local($count) = 0; + local($first); + + for ($first = 1; int($LNO) == $.; ($LNO, $TAG, $TYPE) = &anchor'next()) { + if ($first) { + $first = 0; + print "<A NAME=$LNO>" + } + $define_line = $LNO if ($TYPE eq 'D'); + $db = ($TYPE eq 'D') ? 'GRTAGS' : 'GTAGS'; + local($line) = &cache'get($db, $TAG); + if (defined($line)) { + local($href, $dir); + if ($line) { + local($nouse, $lno, $filename) = split(/[ \t]+/, $line); + $nouse = ''; # to make perl quiet + $filename =~ s/^\.\///; + $filename =~ s/\//$'ESCSEP/g; + $href = "<A HREF=../$'SRCS/$filename.html#$lno>$TAG</A>"; + } else { + $dir = ($TYPE eq 'D') ? $'REFS : $'DEFS; + $href = "<A HREF=../$dir/$TAG.html>$TAG</A>"; + } + # set tag marks and push hyperlink into @links + if (s/\b$TAG\b/\005$count\005/) { + $count++; + push(@links, $href); + } else { + print STDERR "Error: $file $LNO $TAG($TYPE) tag must exist.\n" if ($'wflag); + } + } else { + print STDERR "Warning: $file $LNO $TAG($TYPE) found but not refered.\n" if ($'wflag); + } + } + # implant links + local($s); + for ($count = 0; @links; $count++) { + $s = shift @links; + unless (s/\005$count\005/$s/) { + print STDERR "Error: $file $LNO $TAG($TYPE) tag must exist.\n" if ($'wflag); + } + } + &unprotect_line(); + # print a line + printf "%${ncol}d ", $.; + print; + # print hyperlinks + if ($define_line && $file !~ /\.h$/) { + print ' ' x ($ncol + 1); + print &link_format(&anchor'getlinks($define_line)); + print "\n"; + } + } + print "</PRE>\n"; + print "<HR>\n"; + print "<A NAME=BOTTOM>\n"; + print &link_format(&anchor'getlinks(-1)); + print "\n"; + print "</BODY>\n</HTML>\n"; + close(C); + close(HTML); + select($old); + +} +# +# protect_line: protect quoted strings +# +# io) $_ source line +# +# \001 quoted(\) char +# \002 quoted('') char +# \003 quoted string +# \004 comment +# \032 temporary mark +# +sub protect_line { + @quoted_char1 = (); + while (/(\\.)/) { + push(@quoted_char1, $1); + s/\\./\001/; + } + @quoted_char2 = (); + while (/('[^']')/) { + push(@quoted_char2, $1); + s/'[^']'/\002/; + } + @quoted_strings = (); + while (/("[^"]*")/) { + push(@quoted_strings, $1); + s/"[^"]*"/\003/; + } + @comments = (); + s/^/\032/ if ($INCOMMENT); + while (1) { + if ($INCOMMENT == 0) { + if (/\/\*/) { # start comment + s/\/\*/\032\/\*/; + $INCOMMENT = 1; + } else { + last; + } + } else { + # Thanks to Jeffrey Friedl for his code. + if (m!\032(/\*)?[^*]*\*+([^/*][^*]*\*+)*/!) { + $INCOMMENT = 0; + # minimum matching + s!\032((/\*)?[^*]*\*+([^/*][^*]*\*+)*/)!\004!; + push(@comments, $1); + } else { + s/\032(.*)$/\004/; # mark comment + push(@comments, $1); + } + last if ($INCOMMENT); + } + } +} +# +# unprotect_line: recover quoted strings +# +# i) $_ source line +# +sub unprotect_line { + local($s); + + while (@comments) { + $s = shift @comments; + s/\004/$'comment_begin$s$'comment_end/; + } + while (@quoted_strings) { + $s = shift @quoted_strings; + s/\003/$s/; + } + while (@quoted_char2) { + $s = shift @quoted_char2; + s/\002/$s/; + } + while (@quoted_char1) { + $s = shift @quoted_char1; + s/\001/$s/; + } +} +# +# link_format: format hyperlinks. +# +# i) (previous, next, first, last, top, bottom) +# +sub link_format { + local(@tag) = @_; + local(@label) = ('<', '>', '^', 'v', 'top', 'bottom'); + + local($line) = "$'comment_begin/* "; + while ($label = shift @label) { + local($tag) = shift @tag; + $line .= "<A HREF=#$tag>" if ($tag); + $line .= "[$label]"; + $line .= "</A>" if ($tag); + } + $line .= "<A HREF=../mains.html>[index]</A>"; + $line .= "<A HREF=../help.html>[help]</A>"; + $line .= " */$'comment_end"; + + $line; +} + +#========================================================================= +# ANCHOR PACKAGE +#========================================================================= +package anchor; +# +# create: create anchors temporary database +# +sub create { + $ANCH = "$'tmp/ANCH$$"; + open(ANCH, "| btreeop -C $ANCH") || &error("btreeop -C $ANCH failed.\n"); + foreach $db ('GTAGS', 'GRTAGS') { + local($type) = ($db eq 'GTAGS') ? 'D' : 'R'; + open(PIPE, "btreeop $'dbpath/$db |") || &error("btreeop $'dbpath/$db failed.\n"); + while (<PIPE>) { + local($tag, $lno, $filename) = split; + print ANCH "$filename $lno $tag $type\n"; + } + close(PIPE); + } + close(ANCH); +} +# +# finish: remove anchors database +# +sub finish { + unlink("$ANCH") if (defined($ANCH)); +} +# +# load: load anchors in a file from database +# +# i) $file source file +# +sub load { + local($file) = @_; + + $file = './' . $file if ($file !~ /^\.\//); + + @ANCHORS = (); + open(ANCH, "btreeop -K $file $ANCH|") || &error("btreeop -K $file $ANCH failed.\n"); +$n = 0; + while (<ANCH>) { + local($filename, $lno, $tag, $type) = split; + local($line); + # START for DTFLAG + # don't refer to macros which is defined in other C source. + if ($type eq 'R' && ($line = &cache'get('GTAGS', $tag))) { + local($nouse1, $nouse2, $f, $def) = split(/[ \t]+/, $line); + if ($f !~ /\.h$/ && $f !~ $filename && $def =~ /^#/) { + print STDERR "Information: skip <$filename $lno $tag> because this is a macro which is defined in other C source.\n" if ($'wflag); + next; + } + } + # END for DTFLAG + push(@ANCHORS, "$lno,$tag,$type"); + } + close(ANCH); + local(@keys); + foreach (@ANCHORS) { + push(@keys, (split(/,/))[0]); + } + sub compare { $keys[$a] <=> $keys[$b]; } + @ANCHORS = @ANCHORS[sort compare 0 .. $#keys]; + local($c); + for ($c = 0; $c < @ANCHORS; $c++) { + local($lno, $tag, $type) = split(/,/, $ANCHORS[$c]); + if ($type eq 'D') { + $FIRST = $lno; + last; + } + } + for ($c = $#ANCHORS; $c >= 0; $c--) { + local($lno, $tag, $type) = split(/,/, $ANCHORS[$c]); + if ($type eq 'D') { + $LAST = $lno; + last; + } + } +} +# +# first: get first anchor +# +sub first { + $CURRENT = 0; + local($lno, $tag, $type) = split(/,/, $ANCHORS[$CURRENT]); + $CURRENTDEF = $CURRENT if ($type eq 'D'); + + ($lno, $tag, $type); +} +# +# next: get next anchor +# +sub next { + if (++$CURRENT > $#ANCHORS) { + return ('', '', ''); + } + local($lno, $tag, $type) = split(/,/, $ANCHORS[$CURRENT]); + $CURRENTDEF = $CURRENT if ($type eq 'D'); + + ($lno, $tag, $type); +} +# +# getlinks: get links +# +# i) linenumber >= 1: line number +# 0: header, -1: tailer +# gi) @ANCHORS tag table in current file +# r) (previous, next, first, last, top, bottom) +# +sub getlinks { + local($linenumber) = @_; + local($prev, $next, $first, $last, $top, $bottom); + + $prev = $next = $first = $last = $top = $bottom = 0; + if ($linenumber >= 1) { + local($c, $p, $n); + if ($CURRENTDEF == 0) { + for ($c = 0; $c <= $#ANCHORS; $c++) { + local($lno, $tag, $type) = split(/,/, $ANCHORS[$c]); + if ($lno == $linenumber && $type eq 'D') { + last; + } + } + $CURRENTDEF = $c; + } else { + for ($c = $CURRENTDEF; $c >= 0; $c--) { + local($lno, $tag, $type) = split(/,/, $ANCHORS[$c]); + if ($lno == $linenumber && $type eq 'D') { + last; + } + } + } + $p = $n = $c; + while (--$p >= 0) { + local($lno, $tag, $type) = split(/,/, $ANCHORS[$p]); + if ($type eq 'D') { + $prev = $lno; + last; + } + } + while (++$n <= $#ANCHORS) { + local($lno, $tag, $type) = split(/,/, $ANCHORS[$n]); + if ($type eq 'D') { + $next = $lno; + last; + } + } + } + $first = $FIRST if ($linenumber != $FIRST); + $last = $LAST if ($linenumber != $LAST); + $top = 'TOP' if ($linenumber != 0); + $bottom = 'BOTTOM' if ($linenumber != -1); + if ($FIRST == $LAST) { + $last = '' if ($linenumber == 0); + $first = '' if ($linenumber == -1); + } + + ($prev, $next, $first, $last, $top, $bottom); +} + +#========================================================================= +# CACHE PACKAGE +#========================================================================= +package cache; +# +# open: open tag cache +# +# i) size cache size +# -1: all cache +# 0: no cache +# other: sized cache +# +sub open { + ($cachesize) = @_; + + if ($cachesize == -1) { + return; + } + undef %CACH if defined(%CACH); + $cachecount = 0; +} +# +# put: put tag into cache +# +# i) $db database name +# i) $tag tag name +# i) $line tag line +# +sub put { + local($db, $tag, $line) = @_; + local($label) = ($db eq 'GTAGS') ? 'D' : 'R'; + + $cachecount++; + if ($cachesize >= 0 && $cachecount > $cachesize) { + $CACH = "$'tmp/CACH$$"; + dbmopen(%CACH, $CACH, 0600) || &error("make cache database.\n"); + $cachesize = -1; + } + $CACH{$label.$tag} = $line; +} +# +# get: get tag from cache +# +# i) $db database name +# i) $tag tag name +# r) tag line +# +sub get { + local($db, $tag) = @_; + local($label) = ($db eq 'GTAGS') ? 'D' : 'R'; + + defined($CACH{$label.$tag}) ? $CACH{$label.$tag} : undef; +} +# +# close: close cache +# +sub close { + #dbmclose(%CACH); + unlink("$CACH.db") if (defined($CACH)); +} diff --git a/usr.bin/global/systags/Makefile b/usr.bin/global/systags/Makefile new file mode 100644 index 0000000..49c9806 --- /dev/null +++ b/usr.bin/global/systags/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 1.0 (Berkeley) 4/21/96 + +beforeinstall: + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${.CURDIR}/systags.sh ${DESTDIR}/usr/bin/systags + +.include <bsd.prog.mk> diff --git a/usr.bin/global/systags/systags.sh b/usr.bin/global/systags/systags.sh new file mode 100755 index 0000000..e6e85bf --- /dev/null +++ b/usr.bin/global/systags/systags.sh @@ -0,0 +1,83 @@ +#!/bin/sh +# +# Copyright (c) 1997 Shigio Yamaguchi. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Shigio Yamaguchi. +# 4. Neither the name of the author nor the names of any co-contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# systags.sh 17-Feb-97 +# +# script to make hypertext of kernel source. +# supporting FreeBSD and Linux. +# +case $1 in +-n) nflag=1; shift;; +esac +case $1 in +"") dir=.;; +*) dir=$1;; +esac +# +# get release number from source tree. +# +if [ -f conf/newvers.sh ]; then + os=FreeBSD + release=`awk -F= '/^RELEASE=/ {print $2}' < conf/newvers.sh` +elif [ -f Makefile ] && grep '^vmlinux:' Makefile >/dev/null; then + os=Linux + version=`awk -F= '/^VERSION *=/ {print $2}' < Makefile` + patchlevel=`awk -F= '/^PATCHLEVEL *=/ {print $2}' < Makefile` + sublevel=`awk -F= '/^SUBLEVEL *=/ {print $2}' < Makefile` + release=`echo "$version.$patchlevel.$sublevel" | tr -d ' '` +fi +# +# remove old files +# +case $nflag in +1) echo "rm -rf $dir/htags.log $dir/GTAGS $dir/GRTAGS $dir/HTML";; +*) rm -rf $dir/htags.log $dir/GTAGS $dir/GRTAGS $dir/HTML;; +esac +# +# make global database(GTAGS, GRTAGS). +# +case $nflag in +1) echo "gtags -se $dir";; +*) gtags -se $dir;; +esac +# +# make hypertext. +# (please replace this title with a suitable one.) +# +case $os$release in +"") program=`/bin/pwd | sed 's/.*\///'` + title="Welcome to $program source tour!";; +*) title="Welcome to $os $release kernel source tour!";; +esac +case $nflag in +1) echo "htags -vwat '$title' -d $dir $dir > $dir/htags.log 2>&1";; +*) htags -vwat "$title" -d $dir $dir> $dir/htags.log 2>&1;; +esac |