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