Difference between revisions of "Little Helpers"

From Apache OpenOffice Wiki
Jump to: navigation, search
(Emacs)
(mkd: enable parallel dmake)
 
(48 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 
Here are some '''Little Helpers''' for the enthusiastic developer, such as
 
Here are some '''Little Helpers''' for the enthusiastic developer, such as
editor configurations and small scripts that help to tame the OOo code base.
+
small scripts that help to tame the OOo code base.
  
  
Line 15: Line 15:
 
[http://jroller.com/page/erAck?entry=gnu_id_utils this blog entry].
 
[http://jroller.com/page/erAck?entry=gnu_id_utils this blog entry].
  
The ID-utils come with an<br>
+
The ID-utils come with an <br>
'';;; id-utils.el -- emacs interface to `lid -R grep', a.k.a. `gid' ''<br>
+
'';;; id-utils.el -- emacs interface to `lid -R grep', a.k.a. `gid' '' <br>
For how to interface with the ''vim'' editor see [[#Vim_and_the_GNU_ID-utils | below]].
+
For how to interface with the ''vim'' editor see the
 +
[[Editor_Vim#Vim_and_the_GNU_ID-utils | Vim editor's GNU ID-utils]] section.
 
Generally, the editor invoking functionality of ID-utils uses the shell
 
Generally, the editor invoking functionality of ID-utils uses the shell
 
variables ''VISUAL'' or ''EDITOR'', ''EIDARG'', ''EIDLDEL'' and ''EIDRDEL'', so
 
variables ''VISUAL'' or ''EDITOR'', ''EIDARG'', ''EIDLDEL'' and ''EIDRDEL'', so
Line 55: Line 56:
 
# Treat OOo/SO resource header files as C files
 
# Treat OOo/SO resource header files as C files
 
*.hrc          C
 
*.hrc          C
 +
# Treat OOo/SO header files generated from *.idl as C++ files
 +
*.hdl          C++
 +
# Treat OOo IDL files as C++ files, not exactly a header file, but ...
 +
*.idl          C++
 
# Treat OOo/SO resource files as C files
 
# Treat OOo/SO resource files as C files
 
*.src          C
 
*.src          C
Line 66: Line 71:
 
Then the script below may be invoked either
 
Then the script below may be invoked either
 
* In a module's directory without parameters, creating an ID database for just the single module.
 
* In a module's directory without parameters, creating an ID database for just the single module.
* In the ''$SRC_ROOT'' directory for all modules: <code>mkid-script '*'</code><br> Note the literal '*' asterisk that is not to be expanded by the shell. Also note that the positive list has to be maintained whenever a module introduces an unforseen directory structure, which fortunately happens very rarely.
+
* In the ''$SRC_ROOT'' directory for all modules: <code>mkid-script '*'</code> <br> Note the literal '*' asterisk that is not to be expanded by the shell. <br> The file size of the generated ''ID'' file using this method currently (m223) is 31MB.
* In the ''$SRC_ROOT'' directory for specified modules: <code>mkid-script '{module1,module2,solver}'</code><br> Again, note the literal argument enclosed in single quotes for the file name expansion, which is done by the script. If the argument was not passed literally, only the first module would be included, and other strange things may happen.. Wildcards may be used as usual.<br> It is a good idea to include the ''solver'' module to gather identifiers from delivered header files.<br> Ignore messages like<br> ''mkid: can't lstat `unxlngi4.pro' from `.../SRC680/src.m180/solver' '' or<br> ''mkid: can't lstat `build' from `.../SRC680/src.m180/module1/unxlngi4.pro/misc' ''<br> They result from the INPATH relevant arguments passed for each module and don't harm.
+
* In the ''$SRC_ROOT'' directory for specified modules: <br> <code>mkid-script '{module1,module2,solver}'</code> <br> Again, note the literal argument enclosed in single quotes for the file name expansion, which is done by the script. If the argument was not passed literally, only the first module would be included, and other strange things may happen.. Wildcards may be used as usual. <br> It is a good idea to include the ''solver'' module to gather identifiers from delivered header files. <br> Ignore messages like <br> ''mkid: can't lstat `unxlngi4.pro' from `.../SRC680/src.m180/solver' '' or <br> ''mkid: can't lstat `build' from `.../SRC680/src.m180/module1/unxlngi4.pro/misc' '' <br> They result from the INPATH relevant arguments passed for each module and don't harm.
  
 
You may also manually invoke ''mkid'' in the ''$SRC_ROOT'' directory for all
 
You may also manually invoke ''mkid'' in the ''$SRC_ROOT'' directory for all
 
modules, this is a safe bet but may include more than you want if you have
 
modules, this is a safe bet but may include more than you want if you have
 
output directories for multiple platforms, all identifiers present there will
 
output directories for multiple platforms, all identifiers present there will
get duplicated, triplicated, ... the command line for this is<br>
+
get duplicated, triplicated, ... the command line for this is <br>
 
<code>mkid --lang-map=$HOME/devbase/id-lang.map --statistics</code>
 
<code>mkid --lang-map=$HOME/devbase/id-lang.map --statistics</code>
 +
 +
==== mkid-script ====
  
 
The module-wise script, suggested name: <tt>$HOME/devbase/mkid-script</tt>
 
The module-wise script, suggested name: <tt>$HOME/devbase/mkid-script</tt>
Line 83: Line 90:
 
# specified as literal '*' unexpanded. Will be expanded here.
 
# specified as literal '*' unexpanded. Will be expanded here.
 
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
 
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
 +
# Output directories except $INPATH/inc and $INPATH/misc/build are skipped in
 +
# these cases.
 +
# A simple ALL generator, not ignoring any directory, is the parameter 'all'.
 +
# Warning, that may create a huge database and massively duplicated entries if
 +
# more than one platform's output directory exists.
  
 
if ( { ( which mkid >> /dev/null ) } ) then
 
if ( { ( which mkid >> /dev/null ) } ) then
 
     echo generating IDs
 
     echo generating IDs
 +
    if ( "$1" == "-o" ) then
 +
        set output="--output=$2"
 +
        shift
 +
        shift
 +
    else
 +
        set output=""
 +
    endif
 
     if ( "$1" == "" ) then
 
     if ( "$1" == "" ) then
 
         set module="."
 
         set module="."
 
         #set exclude=./{common,unxlngi6,unxsols4,wntmsci10}{,.pro}
 
         #set exclude=./{common,unxlngi6,unxsols4,wntmsci10}{,.pro}
         # wildcards not only make updates unnecessary but also suppress "no match" messages
+
         # Wildcards not only make updates unnecessary but also suppress "no
         set exclude=./{common*,unxlng*,unxsol*,wntmsc*}
+
        # match" error messages. The CVS* and .svn* directories are included
     else if ( "$1" == "*" ) then
+
        # for the case of a freshly checked out source that does not have any
 +
        # output directories yet. Otherwise that would still lead to a "no
 +
        # match" error if no wildcarded names matched.
 +
         set exclude=./{CVS*,.svn*,common*,*unxlng*,*unxsol*,*unxmac*,*wntmsc*}
 +
     else if ( "`basename '$1'`" == "*" ) then
 
         set module="$1"
 
         set module="$1"
 
         echo module: $module
 
         echo module: $module
 
         # prevent command line overflow with a full exclude
 
         # prevent command line overflow with a full exclude
 
         set exclude="x"
 
         set exclude="x"
 +
        echo exclude: $exclude
 +
    else if ( "$1" == "all" ) then
 +
        set module="$1"
 +
        echo module: $module
 +
        set exclude="nothing"
 
         echo exclude: $exclude
 
         echo exclude: $exclude
 
     else
 
     else
 
         set module="$1"
 
         set module="$1"
 
         echo module: $module
 
         echo module: $module
         set exclude=$1/{common*,unxlng*,unxsol*,wntmsc*}
+
         set exclude=$1/{CVS*,.svn*,common*,*unxlng*,*unxsol*,*unxmac*,*wntmsc*}
 
         echo exclude: $exclude
 
         echo exclude: $exclude
 
     endif
 
     endif
  
     if ( "$1" == "*" ) then
+
     if ( "`basename '$1'`" == "*" ) then
         # only positive list
+
         # test for ls overrun
         set dirs="$module/inc $module/unx $module/mow $module/win{,32} $module/mac{,osx} $module/$INPATH/inc $module/$INPATH/misc/build $module/source $module/src $module/osl $module/rtl $module/systools $module/textenc"
+
         set dcommand="ls -d $module/*"
 +
        if ( ! { ( $dcommand >> /dev/null ) } ) then
 +
            echo "$0 : ls overrun, trying find $module -mindepth 1 -maxdepth 1"
 +
            # test for find mindepth/maxdepth availability
 +
            set dcommand="find $module -mindepth 1 -maxdepth 1"
 +
            if ( ! { ( $dcommand >> /dev/null ) } ) then
 +
                echo "$0 : find doesn't know options -mindepth -maxdepth"
 +
                echo "$0 : too bad, giving up."
 +
                exit 1
 +
            endif
 +
        endif
 +
        # Only positive list of module subdirectories and files,
 +
        # excluding output directories except $INPATH/{inc,misc/build}
 +
        set dirs="$module/$INPATH/inc $module/$INPATH/misc/build `$dcommand | sed -e '/\(\/\(CVS\|common\|.*unxlng\|.*unxsol\|.*unxmac\|.*wntmsc\|Jamfile\|cscope\.\|tags\|ID\)\)\|^solver\//d'`"
 
         echo dirs: $dirs
 
         echo dirs: $dirs
         mkid --lang-map=$HOME/devbase/id-lang.map --statistics $dirs
+
        echo Creating output: $output
 +
         mkid --lang-map=$HOME/devbase/id-lang.map --include='C C++ asm perl java make' $output --statistics $dirs
 +
    else if ( "$1" == "all" ) then
 +
        echo Creating output: $output
 +
        mkid --lang-map=$HOME/devbase/id-lang.map --include='C C++ asm perl java make' $output --statistics
 
     else
 
     else
 
         # all but negative list plus INPATH relevants
 
         # all but negative list plus INPATH relevants
         mkid --lang-map=$HOME/devbase/id-lang.map --statistics --prune="$exclude" $module $module/$INPATH/inc $module/$INPATH/misc/build
+
        echo Creating output: $output
 +
         mkid --lang-map=$HOME/devbase/id-lang.map --include='C C++ asm perl java make' $output --statistics --prune="$exclude" $module $module/$INPATH/inc $module/$INPATH/misc/build
 
     endif
 
     endif
 
    # all, for copy&paste
 
    # mkid --lang-map=$HOME/devbase/id-lang.map --statistics
 
  
 
else
 
else
Line 132: Line 175:
 
added a patch needed for the ''vim 7.0 omni-completion'' feature. Ctags creates
 
added a patch needed for the ''vim 7.0 omni-completion'' feature. Ctags creates
 
a file ''tags'' in the current directory, if not told otherwise.
 
a file ''tags'' in the current directory, if not told otherwise.
 +
 +
As creating a tags file over all modules and directories exceeded the 2GB file
 +
size limit, a positive directory list was used to go along with a '*'
 +
parameter, identical to the one used in the ''mkid-script'' above. The file
 +
size of the ''tags'' file generated for '*' currently (m182) is 398MB.
 +
 +
==== ctags-script ====
  
 
For use with the OOo code base a script with a syntax similar to the ID-utils
 
For use with the OOo code base a script with a syntax similar to the ID-utils
Line 142: Line 192:
 
# specified as literal '*' unexpanded. Will be expanded here.
 
# specified as literal '*' unexpanded. Will be expanded here.
 
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
 
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
# NOTE: ctags on '*' exceeds 2GB file size limit if for _all_ OOo modules.
+
# NOTE: ctags on '*' exceeded 2GB file size limit if for _all_ OOo modules and
 +
# no positive dirs list was used.
 +
 
 +
if ( "$?MYCTAGS" == "0" ) then
 +
    set MYCTAGS="ctags"
 +
endif
  
if ( { ( which ctags >> /dev/null ) } ) then
+
if ( { ( which "$MYCTAGS" >> /dev/null ) } ) then
 
     echo generating ctags
 
     echo generating ctags
 
     # Options necessary for the Vim OmniCppComplete plugin,
 
     # Options necessary for the Vim OmniCppComplete plugin,
Line 156: Line 211:
 
     if ( "$1" == "--global" ) then
 
     if ( "$1" == "--global" ) then
 
         if ( ! $?UPDMINOREXT ) set UPDMINOREXT=""
 
         if ( ! $?UPDMINOREXT ) set UPDMINOREXT=""
         ctags -h "+.hdl.hrc" --langmap=c:+.hdl.hrc.src $omnicppoptions -R $SOLARVERSION/$INPATH/inc$UPDMINOREXT
+
         "$MYCTAGS" -h "+.hdl.hrc" --langmap=c:+.hdl.hrc.src $omnicppoptions -R $SOLARVERSION/$INPATH/inc$UPDMINOREXT
 
     else
 
     else
 
         if ( "$1" == "" ) then
 
         if ( "$1" == "" ) then
Line 164: Line 219:
 
             echo module: $module
 
             echo module: $module
 
         endif
 
         endif
         set dirs="$module/inc $module/unx $module/mow $module/win{,32} $module/mac{,osx} $module/$INPATH/inc $module/$INPATH/misc/build $module/source $module/src $module/osl $module/rtl $module/systools $module/textenc"
+
        # test for ls overrun
         ctags -h "+.hdl.hrc" --langmap=c:+.hdl.hrc.src $omnicppoptions -R $dirs
+
         set dcommand="ls -d $module/*"
 +
        if ( ! { ( $dcommand >> /dev/null ) } ) then
 +
            echo "$0 : ls overrun, trying find $module -mindepth 1 -maxdepth 1"
 +
            # test for find mindepth/maxdepth availability
 +
            set dcommand="find $module -mindepth 1 -maxdepth 1"
 +
            if ( ! { ( $dcommand >> /dev/null ) } ) then
 +
                echo "$0 : find doesn't know options -mindepth -maxdepth"
 +
                echo "$0 : too bad, giving up."
 +
                exit 1
 +
            endif
 +
        endif
 +
        # Only positive list of module subdirectories and files,
 +
        # excluding output directories except $INPATH/{inc,misc/build}
 +
        set dirs="$module/$INPATH/inc $module/$INPATH/misc/build `$dcommand | sed -e '/\(\/\(CVS\|\.svn\|common\|.*unxlng\|.*unxsol\|.*unxmac\|.*wntmsc\|Jamfile\|cscope\.\|tags\|ID\)\)\|^solver\//d'`"
 +
         echo dirs: $dirs
 +
        "$MYCTAGS" -h "+.hdl.hrc" --langmap=c:+.hdl.hrc.src $omnicppoptions -R $dirs
 
     endif
 
     endif
 
else
 
else
Line 173: Line 243:
  
 
Ignore messages like<br>
 
Ignore messages like<br>
''ctags: Warning: cannot open source file "./win32" : No such file or directory''<br>
+
''ctags: Warning: cannot open source file "./unxlngi6.pro/misc/build" : No such file or directory''<br>
 
or consider them purely informational.
 
or consider them purely informational.
  
Line 185: Line 255:
 
script without parameters, then <code>cd $SRC_ROOT</code> and invoke
 
script without parameters, then <code>cd $SRC_ROOT</code> and invoke
 
<code>scriptname --global</code> to produce a tags file for the ''solver''.
 
<code>scriptname --global</code> to produce a tags file for the ''solver''.
 +
 +
A final <tt>ctags</tt> note: In some cases, you might have more than one version of <tt>ctags</tt> on your system.  E.g., there is a version that ships with Emacs (and is often in <tt>/usr/local/bin</tt>) that doesn't support the same arguments as Exhuberant <tt>ctags</tt>; if this is the case (you'll see an error message from the script like "<tt>unrecognized option `--langmap=c:+.hdl.hrc.src'</tt>") then you can set the MYCTAGS variable, e.g., from a <tt>bash</tt> shell:
 +
<pre>
 +
MYCTAGS=/usr/bin/ctags $HOME/devbase/ctags-script --global
 +
MYCTAGS=/usr/bin/ctags CTAGS=-e $HOME/devbase/ctags-script --global # generate TAGS for Emacs
 +
</pre>
 +
If all you have is the Emacs version, you will want to rewrite the script (or provide a better solution here).
  
 
=== Cscope ===
 
=== Cscope ===
Line 190: Line 267:
 
Cscope is another utility to query a database for code elements. It comes with
 
Cscope is another utility to query a database for code elements. It comes with
 
a cumbersome screen-oriented interactive tool to browse source files, but also
 
a cumbersome screen-oriented interactive tool to browse source files, but also
interfaces nicely with Vim and Emacs. This script may be used to generate a
+
interfaces nicely with Vim and Emacs. Unfortunately it is not able to cope with
''cscope.out'' database file, suggested name:
+
the entire OOo source base it seems, so for '*' even when called with a list of
 +
files to work on, at the end it displayed
 +
''Input string too long, limit 50251''
 +
and no output was generated. Didn't investigate yet what exactly is the
 +
problem. However, using it on a subset of several modules is possible.
 +
 
 +
==== cscope-script ====
 +
 
 +
This script may be used to generate a ''cscope.out'' database file, same
 +
parameter syntax as the mkid-script and ctags-script above. Suggested name:
 
<tt>$HOME/devbase/cscope-script</tt>
 
<tt>$HOME/devbase/cscope-script</tt>
  
Line 200: Line 286:
 
# specified as literal '*' unexpanded. Will be expanded here.
 
# specified as literal '*' unexpanded. Will be expanded here.
 
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
 
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
# NOTE: cscope on '*' hangs if for _all_ OOo modules.
+
# NOTE: cscope on '*' hanged if for _all_ OOo modules and no positive dirs list
 +
# was used. Even with the generated cscope.files it still refuses to complete
 +
# its work.
  
 
if ( { ( which cscope >> /dev/null ) } ) then
 
if ( { ( which cscope >> /dev/null ) } ) then
Line 210: Line 298:
 
         echo module: $module
 
         echo module: $module
 
     endif
 
     endif
     set dirs="$module/inc $module/unx $module/mow $module/win{,32} $module/mac{,osx} $module/$INPATH/inc $module/$INPATH/misc/build $module/source $module/src $module/osl $module/rtl $module/systools $module/textenc"
+
    # test for ls overrun
 +
     set dcommand="ls -d $module/*"
 +
    if ( ! { ( $dcommand >> /dev/null ) } ) then
 +
        echo "$0 : ls overrun, trying find $module -mindepth 1 -maxdepth 1"
 +
        # test for find mindepth/maxdepth availability
 +
        set dcommand="find $module -mindepth 1 -maxdepth 1"
 +
        if ( ! { ( $dcommand >> /dev/null ) } ) then
 +
            echo "$0 : find doesn't know options -mindepth -maxdepth"
 +
            echo "$0 : too bad, giving up."
 +
            exit 1
 +
        endif
 +
    endif
 +
    # Only positive list of module subdirectories and files,
 +
    # excluding output directories except $INPATH/{inc,misc/build}
 +
    set dirs="$module/$INPATH/inc $module/$INPATH/misc/build `$dcommand | sed -e '/\(\/\(CVS\|\.svn\|common\|.*unxlng\|.*unxsol\|.*unxmac\|.*wntmsc\|Jamfile\|cscope\.\|tags\|ID\)\)\|^solver\//d'`"
 +
    echo dirs: $dirs
 
     ( find $dirs -name '*.[hc]' -o -name '*.[hc]xx' -o -name '*.[hc]pp' -o -name '*.[hs]rc' >cscope.files ) >>& /dev/null
 
     ( find $dirs -name '*.[hc]' -o -name '*.[hc]xx' -o -name '*.[hc]pp' -o -name '*.[hs]rc' >cscope.files ) >>& /dev/null
 
     if ( `uname` == "SunOS" ) then
 
     if ( `uname` == "SunOS" ) then
Line 223: Line 326:
  
 
Note that the ''find'' command is executed in a subshell with stderr redirected
 
Note that the ''find'' command is executed in a subshell with stderr redirected
to /dev/null to suppress all the ''find: ./win32: No such file or directory''
+
to /dev/null to suppress all the ''find: ./unxlngi6.pro/misc/build: No such file or directory''
 
and the like warning messages. Remove the parentheses and the redirection in
 
and the like warning messages. Remove the parentheses and the redirection in
 
case you suspect errors in your environment.
 
case you suspect errors in your environment.
Line 253: Line 356:
 
databases for that single module.
 
databases for that single module.
  
 +
== Build selected source code files with debug ==
  
== Vim ==
+
Sometimes only a few files need to be build with debug instead of an entire
 +
module, which significantly saves time. Change into the directory and invoke
 +
the following script with the files of interest passed as arguments, for
 +
example, in <tt>sc/source/core/tool</tt>
  
There exist only two real editors in the programmer's world ;-)  One is Vim,
+
<source lang="bash">
and the other is the ''eier-legende-woll-milch-sau'' (sorry for that German
+
mkd token.cxx compiler.cxx interpr*.cxx
phrase being a modified translation of
+
</source>
''allrounder - all-in-one device suitable for every purpose'',
+
couldn't resist ;-) (X)Emacs. So here we go for Vim.
+
  
 +
To also link the library in the module's ''util'' directory pass the ''--link''
 +
or ''-l'' option:
  
=== General Vim settings ===
+
<source lang="bash">
 +
mkd -l token.cxx compiler.cxx interpr*.cxx
 +
</source>
  
In ''.vimrc'' have the following settings. For the tabstops=4 setting it may
+
=== mkd ===
not be desired to have this globally effective, you may want to restrict it to
+
an OOo/SO environment by evaluating the $SOLARENV environment variable,
+
<code>if $SOLARENV != ""</code>
+
  
<pre>
+
<source lang="bash">
set ts=4                " tabstops are 4 (for all code)
+
#!/bin/bash
set sw=4                " shiftwidth is 4
+
set expandtab          " expand tabs to spaces
+
set showmatch          " briefly jump to matching brackets
+
set showmode            " the mode we're in
+
if version >= 600
+
    filetype on            " enable file type detection
+
    filetype plugin on      " enable file type plugins
+
    filetype indent on      " enable file type indents
+
endif
+
  
" previous and next compiler error (quickfix)
+
# Compile source files (in current directory!) passed as arguments with debug.
map <C-P> :cp<CR>
+
# Option --link or -l also links the library in the module's util directory.
map <C-N> :cn<CR>
+
  
" Only do this part when compiled with support for autocommands.
+
# Do parallel build, set to empty if not wanted.
if has("autocmd")
+
PARALLEL="-P4"
  
     " In text files, always limit the width of text to 78 characters, tabs are 8
+
if [ -z "$INPATH" ]; then
     autocmd BufRead *.txt,*.doc,*.dok setlocal tw=78 ts=8 sw=8 fo+=rn1
+
     echo "No \$INPATH, source environment!"
 +
     exit 1
 +
fi
 +
UTIL=""
 +
if [ "$1" == "--link" -o "$1" == "-l" ]; then
 +
    UTIL="Yes"
 +
    shift
 +
fi
  
    " mail bodies have a textwidth of 72 characters, activate numbering
+
# Determine the current hierarchy depth by looking upwards for the prj/d.lst
     " formatting, reset comments to default, no indenting
+
# file, but no more than MAX levels up.
     autocmd FileType mail setlocal tw=72 fo+=rn1 comments& nocindent
+
DLST="prj/d.lst"
 +
SUBS=""
 +
MAX=5
 +
for (( LEVEL=0 ; LEVEL < MAX ; ++LEVEL )); do
 +
     if [ -f "${SUBS}${DLST}" ]; then
 +
        break
 +
     fi
 +
    SUBS="../$SUBS"
 +
done
 +
OUTP="${SUBS}${INPATH}/slo"
 +
if [ $LEVEL == $MAX ]; then
 +
    echo "No ${SUBS}${DLST} found! (LEVEL $LEVEL)"
 +
    exit 1
 +
fi
  
    " AutoDoc comments in C/C++ files without '*' middle part
+
ERR=0
    autocmd FileType c,cpp setlocal comments^=s:/**,mb:\ ,e:*/
+
# Force compilation of files passed as arguments.
 
+
for x in "$@"; do
    " AutoDoc comments in IDL files have a textwidth of 72 characters
+
    FILE="${x//*\//}"
    autocmd FileType idl setlocal comments^=s:/**,mb:\ ,e:*/ tw=72
+
     BASE="${FILE%.*}"
 
+
     FULL="${OUTP}/${BASE}.obj"
    " OOo .xcu configuration files and the like
+
     rm "$FULL"
    autocmd FileType xml setlocal sw=2
+
    if [ -z "$PARALLEL" ]; then
 
+
        dmake debug=t "$FULL"
    " HTML files
+
     fi
    autocmd FileType html,css setlocal sw=2
+
     ERR=$?
 
+
     if [ $ERR != 0 ]; then
endif
+
         break
</pre>
+
     fi
 
+
done
 
+
# If no error, compile yet uncompiled files and create archive, if any.
=== Vim and the GNU ID-utils ===
+
if [ $ERR == 0 ]; then
 
+
    dmake $PARALLEL debug=t
As mentioned [[#GNU_ID-utils | above]], the ''eid'' command makes use of some
+
    ERR=$?
environment variables when invoking the editor:
+
fi
 
+
# Some modules, such as Writer, have an extra archiving step one level up, e.g.
<pre>
+
# in sw/source/core/ if files in sw/source/core/layout/ were compiled.
setenv VISUAL  vim
+
# Do this only if deeper than in module level.
setenv EIDARG  '+/%s/'
+
if (( LEVEL > 1 )); then
setenv EIDLDEL  '\<'
+
    if [ $ERR == 0 -a -f ../makefile.mk ]; then
setenv EIDRDEL  '\>'
+
         pushd ..
</pre>
+
         dmake debug=t
 
+
         ERR=$?
To be able to invoke the ''lid'' utility from within Vim we need a key mapping
+
         popd
and function call, you may place this section into your ''.vimrc'' file:
+
    fi
 
+
fi
<pre>
+
# If no error, link library if requested.
" GNU id-utils, taken from :h ident-search
+
if [ $ERR == 0 -a -n "$UTIL" ]; then
" Generate the ID file in the current directory or in .. or ../.. or ../../..
+
    UTIL="${SUBS}util"
" To use it, place the cursor on a word, type "_u" and vim will load the file
+
     if [ ! -d "$UTIL" ]; then
" that contains the word.  Search for the next occurrence of the word in the
+
        echo "No $UTIL directory, no linking."
" same file with "n".  Go to the next file with "_n".
+
        exit
map _u :call ID_search()<Bar>execute "/\\<" . g:word . "\\>"<CR>
+
     fi
map _n :n<Bar>execute "/\\<" . g:word . "\\>"<CR>
+
     cd "$UTIL"
function ID_search()
+
     dmake debug=t
     let g:word = expand("<cword>")
+
     ERR=$?
     let x = system("lid --key=none ". g:word)
+
fi
    let x = substitute(x, "\n", " ", "g")
+
exit $ERR
     execute "next " . x
+
</source>
endfun
+
</pre>
+
 
+
 
+
=== Vim and Ctags ===
+
 
+
That's easy, as vim has builtin support for ctags, see '':h tagsrch.txt'', in
+
''.vimrc'' just tell it where to search for the ''tags'' files:
+
 
+
<pre>
+
" Tags files are searched first relative to the current file, then relative to
+
" the current working directory, and last in the $HOME directory.
+
set tags=./tags,./../tags,./../../tags,./../../../tags,./../../../../tags,./../../../../../tags,tags,../tags,../../tags,../../../tags,../../../../tags,../../../../../tags,~/tags
+
</pre>
+
 
+
 
+
=== Vim and Cscope ===
+
 
+
Vim has also builtin (well, if compiled in) support for cscope, see
+
'':h cscope''. In ''.vimrc'' you may want to setup some things, but this is
+
also a matter of work habits. Consider the following an example and consult the
+
fine manual.
+
 
+
<pre>
+
" Cscope settings
+
if has("cscope")
+
    " quickfix window usage
+
    set cscopequickfix=s-,c-,d-,i-,t-,e-
+
    " :tag and the like use :cstag
+
     set cscopetag
+
     " first search cscope, than tags file
+
    set cscopetagorder=0
+
    set nocsverb
+
    " add any database in current directory
+
     if filereadable("cscope.out")
+
        cs add cscope.out
+
        " else add database pointed to by environment
+
    elseif $CSCOPE_DB != ""
+
         cs add $CSCOPE_DB
+
     endif
+
    set csverb
+
endif
+
</pre>
+
 
+
=== Include file searches in Vim ===
+
 
+
Set the ''path'' variable in ''.vimrc'':
+
 
+
<pre>
+
" Where to look for files in gf and ^Wf and similar commands,
+
" and for include files for i_^X^I and i_^X^D commands.
+
" To use VIM_INC in OOo/SO environment define
+
" alias solvim 'if ( ! $?UPDMINOREXT ) setenv UPDMINOREXT "" ; setenv VIM_INC ./${INPATH}/inc,../${INPATH}/inc,../../${INPATH}/inc,../../../${INPATH}/inc,`echo $SOLARINC|sed -e "s/^-I//" -e "s/  *-I/,/g"`,${SOLARVERSION}/${INPATH}/inc${UPDMINOREXT}/offuh'
+
" Note the two space characters in the second substitute, and execute the alias after a setsolar.
+
" Under 4NT you need some rubbish like (note this isn't updated since ages)
+
" alias solvim=set _uq_%0=%@unique[%tmp%] && echos VIM_INC=>>_uq_%0 && echo %SOLARINC|sed -e "s/^-I//" -e "s/ \+-I/,/g">>_uq_%0 && set /r _uq_%0 && del /q _uq_%0
+
set path=.,./inc,./../inc,./../../inc,./../../../inc,./../../../../inc,$VIM_INC,,/usr/local/include,/usr/include
+
</pre>
+
 
+
In case you missed it in the comments above: you need to invoke a shell alias
+
after having sourced the environment:
+
 
+
<pre>
+
tcsh
+
alias solvim 'if ( ! $?UPDMINOREXT ) setenv UPDMINOREXT "" ; setenv VIM_INC ./${INPATH}/inc,../${INPATH}/inc,../../${INPATH}/inc,../../../${INPATH}/inc,`echo $SOLARINC|sed -e "s/^-I//" -e "s/  *-I/,/g"`,${SOLARVERSION}/${INPATH}/inc${UPDMINOREXT}/offuh'
+
source LinuxIntelEnv.Set
+
solvim
+
</pre>
+
 
+
See also: in Vim '':h include-search''
+
 
+
 
+
=== Compiling a source from within Vim ===
+
 
+
Compiling the source from within the editor is of course desired, as warnings
+
and errors generated by the compiler let you directly jump to the line in
+
question. There are some quirks to be solved for the OOo/SO environment, but no
+
real problem, just examine the working ''.vimrc'' sections below. It assumes
+
you invoked Vim from within the directory where the source file resides, you
+
may check with the Vim command <code>:pwd</code>. If this is not the case,
+
change to its directory by issuing the command <code>:lcd %:h</code> prior to
+
invoking the <code>:make</code> command, which changes the directory locally
+
for the current window.
+
 
+
For the quickfix window to pull its content from the compiler output we need to
+
have a valid error file setting, and as there's always the hassle with DOS
+
based systems, we also need to take care of that:
+
 
+
<pre>
+
" This uses the TMP environment variable, be sure to have it set!
+
if $COMSPEC =~ "\\"
+
    " seems like we're having any DOS
+
    set makeef=$TMP\\vim##.err  " :make errorfile
+
else
+
    set makeef=$TMP/vim##.err  " :make errorfile
+
endif
+
if $TMP =~ "\\" && ($COMSPEC =~ "4" || $SHELL =~ "4")
+
    " seems like we're having some DOS assumed to be 4DOS compatible
+
    set shellpipe=\|&\ tee
+
endif
+
</pre>
+
 
+
Now the ''makeprg'' setting:
+
 
+
<pre>
+
" Only in OpenOffice.org/StarOffice environment
+
if $SOLARENV != "" && filereadable( "makefile.mk" )
+
    " For a detached gvim we need to source the environment, assuming the
+
    " current working directory being source/core/tool/ or similar, and having a
+
    " copy of the setsolar -file environment file as ../../../ENV.$INPATH or
+
    " in $SRC_ROOT set a  ln -s LinuxIntelEnv.Set ENV.$INPATH
+
    " For terminal vim re-sourcing the environment isn't necessary.
+
    if has("gui_running")
+
        if filereadable( "./prj/d.lst" )
+
            set makeprg=source\ ./ENV.$INPATH\ \&\&\ dmake\ wall=t\ debug=t\ ./$INPATH/slo/%:t:r.obj
+
        elseif filereadable( "../prj/d.lst" )
+
            set makeprg=source\ ../ENV.$INPATH\ \&\&\ dmake\ wall=t\ debug=t\ ../$INPATH/slo/%:t:r.obj
+
         elseif filereadable( "../../prj/d.lst" )
+
            set makeprg=source\ ../../ENV.$INPATH\ \&\&\ dmake\ wall=t\ debug=t\ ../../$INPATH/slo/%:t:r.obj
+
         elseif filereadable( "../../../prj/d.lst" )
+
            set makeprg=source\ ../../../ENV.$INPATH\ \&\&\ dmake\ wall=t\ debug=t\ ../../../$INPATH/slo/%:t:r.obj
+
         elseif filereadable( "../../../../prj/d.lst" )
+
            set makeprg=source\ ../../../../ENV.$INPATH\ \&\&\ dmake\ wall=t\ debug=t\ ../../../../$INPATH/slo/%:t:r.obj
+
         else
+
            set makeprg=source\ ./ENV.$INPATH\ \&\&\ dmake\ wall=t\ debug=t
+
        endif
+
    else
+
        if filereadable( "./prj/d.lst" )
+
            set makeprg=dmake\ wall=t\ debug=t\ ./$INPATH/slo/%:t:r.obj
+
        elseif filereadable( "../prj/d.lst" )
+
            set makeprg=dmake\ wall=t\ debug=t\ ../$INPATH/slo/%:t:r.obj
+
        elseif filereadable( "../../prj/d.lst" )
+
            set makeprg=dmake\ wall=t\ debug=t\ ../../$INPATH/slo/%:t:r.obj
+
        elseif filereadable( "../../../prj/d.lst" )
+
            set makeprg=dmake\ wall=t\ debug=t\ ../../../$INPATH/slo/%:t:r.obj
+
        elseif filereadable( "../../../../prj/d.lst" )
+
            set makeprg=dmake\ wall=t\ debug=t\ ../../../../$INPATH/slo/%:t:r.obj
+
        else
+
            set makeprg=dmake\ wall=t\ debug=t
+
        endif
+
    endif
+
 
+
    " Just some copy&paste versions:
+
     "set makeprg=dmake\ debug=t\ wall=t
+
    "set makeprg=source\ ../../../ENV.$INPATH\ \&\&\ dmake\ wall=t\ debug=t
+
    " Entire module, edit ENV.... and set BUILD_COMMAND to content of build alias
+
    "set makeprg=source\ ../../../ENV.$INPATH\ \&\&\ $BUILD_COMMAND
+
    "set makeprg=source\ ../../../ENV.$INPATH\ \&\&\ dmake\ ../../../$INPATH/slo/%:t:r.obj
+
    "set makeprg=dmake\ product=full
+
    "set makeprg=dmake
+
    " temporary override, no wall, no debug
+
    "if filereadable( "./prj/d.lst" )
+
    "    set makeprg=dmake\ ./$INPATH/slo/%:t:r.obj
+
     "elseif filereadable( "../prj/d.lst" )
+
     "   set makeprg=dmake\ ../$INPATH/slo/%:t:r.obj
+
    "elseif filereadable( "../../prj/d.lst" )
+
     "    set makeprg=dmake\ ../../$INPATH/slo/%:t:r.obj
+
     "elseif filereadable( "../../../prj/d.lst" )
+
    "    set makeprg=dmake\ ../../../$INPATH/slo/%:t:r.obj
+
    "elseif filereadable( "../../../../prj/d.lst" )
+
    "    set makeprg=dmake\ ../../../../$INPATH/slo/%:t:r.obj
+
    "else
+
    "    set makeprg=dmake
+
    "endif
+
endif
+
</pre>
+
 
+
 
+
=== Emacs and Cscope ===
+
 
+
Emacs has a premade file for cscope, generally packaged with cscope.
+
So adding
+
 
+
<pre>
+
;;cscope integration
+
(require 'xcscope)
+
</pre>
+
 
+
is enough to activate it. Major shortcut are :
+
* Find-symbol : C-c s s
+
* Find-global-definition : C-c s g
+
* Next-symbol : C-c s n
+
See the documentation for more
+
 
+
== A note for developers on WIN/DOS ==
+
 
+
Please don't complicate life for developers on other platforms by interspersing
+
sources with CarriageReturn characters before linefeeds, which especially is
+
extremely nasty in patches contributed. As you probably can't patch your
+
kernel's IO to simply not automatically write CrLf instead of Lf in text files,
+
when using Vim use this setting:
+
 
+
<pre>
+
"set fileformats=dos,unix  " Vim's default on DOS/WIN/OS2
+
set fileformats=unix,dos  " Vim's default on UNX, also use it on DOS
+
</pre>
+
  
  
[[Category:Development]]
+
[[Category:Developer Tools]]

Latest revision as of 20:48, 8 September 2010

Here are some Little Helpers for the enthusiastic developer, such as small scripts that help to tame the OOo code base.


Tools for maintaining identifier databases

GNU ID-utils

The GNU ID-utils are a powerful set of utilities to generate and query a database of file names and identifiers, invoke your favourite editor with the resulting set of files, or accomplish any other task with the resultset. Be sure to not use the original version 3.2, use the Debian package instead, or maybe some other distribution's package. For details why and how to patch a self-compiled version 3.2d see this blog entry.

The ID-utils come with an
;;; id-utils.el -- emacs interface to `lid -R grep', a.k.a. `gid'
For how to interface with the vim editor see the Vim editor's GNU ID-utils section. Generally, the editor invoking functionality of ID-utils uses the shell variables VISUAL or EDITOR, EIDARG, EIDLDEL and EIDRDEL, so it should be possible to invoke any capable editor. Citing from the documentation:

   `eid' invokes the editor defined by the environment variable
`VISUAL'.  If `VISUAL' is undefined, it uses the environment variable
`EDITOR' instead.  If `EDITOR' is undefined, it defaults to `vi'.  It
is possible for `eid' to pass the editor an initial search pattern so
that your cursor will immediately alight on the token of interest.
This feature is controlled by the following environment variables:
`EIDARG'
     A printf(3) format string for the editor argument to search for the
     matching token.  For `vi', this should be `+/%s/'.

`EIDLDEL'
     The regular-expression meta-character(s) for delimiting the
     beginning of a word (the ``eid' Left DELimiter').  `eid' inserts
     this in front of the matching token when a word-search is desired.
     For `vi', this should be `\<'.

`EIDRDEL'
     The regular-expression meta-character(s) for delimiting the end of
     a word (the ``eid' Right DELimiter').  `eid' inserts this in end
     of the matching token when a word-search is desired.  For `vi',
     this should be `\>'.

The ID-utils use an extension → language mapping file id-lang.map. Either edit the system-wide file of your installation or a local copy thereof. Here we're assuming a local copy as $HOME/devbase/id-lang.map, add the following entries:

# Treat OOo/SO resource header files as C files
*.hrc           C
# Treat OOo/SO header files generated from *.idl as C++ files
*.hdl           C++
# Treat OOo IDL files as C++ files, not exactly a header file, but ...
*.idl           C++
# Treat OOo/SO resource files as C files
*.src           C
# Treat OOo/SO *.mk files as makefiles
*.mk            make

Note: The *.mk make entry doesn't seem to work, the makefile.mk's IDs are not added to the database, didn't investigate yet why.

Then the script below may be invoked either

  • In a module's directory without parameters, creating an ID database for just the single module.
  • In the $SRC_ROOT directory for all modules: mkid-script '*'
    Note the literal '*' asterisk that is not to be expanded by the shell.
    The file size of the generated ID file using this method currently (m223) is 31MB.
  • In the $SRC_ROOT directory for specified modules:
    mkid-script '{module1,module2,solver}'
    Again, note the literal argument enclosed in single quotes for the file name expansion, which is done by the script. If the argument was not passed literally, only the first module would be included, and other strange things may happen.. Wildcards may be used as usual.
    It is a good idea to include the solver module to gather identifiers from delivered header files.
    Ignore messages like
    mkid: can't lstat `unxlngi4.pro' from `.../SRC680/src.m180/solver' or
    mkid: can't lstat `build' from `.../SRC680/src.m180/module1/unxlngi4.pro/misc'
    They result from the INPATH relevant arguments passed for each module and don't harm.

You may also manually invoke mkid in the $SRC_ROOT directory for all modules, this is a safe bet but may include more than you want if you have output directories for multiple platforms, all identifiers present there will get duplicated, triplicated, ... the command line for this is
mkid --lang-map=$HOME/devbase/id-lang.map --statistics

mkid-script

The module-wise script, suggested name: $HOME/devbase/mkid-script

#!/bin/tcsh

# Either the current module, or all modules can be ID'ed if $1 is
# specified as literal '*' unexpanded. Will be expanded here.
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
# Output directories except $INPATH/inc and $INPATH/misc/build are skipped in
# these cases.
# A simple ALL generator, not ignoring any directory, is the parameter 'all'.
# Warning, that may create a huge database and massively duplicated entries if
# more than one platform's output directory exists.

if ( { ( which mkid >> /dev/null ) } ) then
    echo generating IDs
    if ( "$1" == "-o" ) then
        set output="--output=$2"
        shift
        shift
    else
        set output=""
    endif
    if ( "$1" == "" ) then
        set module="."
        #set exclude=./{common,unxlngi6,unxsols4,wntmsci10}{,.pro}
        # Wildcards not only make updates unnecessary but also suppress "no
        # match" error messages. The CVS* and .svn* directories are included
        # for the case of a freshly checked out source that does not have any
        # output directories yet. Otherwise that would still lead to a "no
        # match" error if no wildcarded names matched.
        set exclude=./{CVS*,.svn*,common*,*unxlng*,*unxsol*,*unxmac*,*wntmsc*}
    else if ( "`basename '$1'`" == "*" ) then
        set module="$1"
        echo module: $module
        # prevent command line overflow with a full exclude
        set exclude="x"
        echo exclude: $exclude
    else if ( "$1" == "all" ) then
        set module="$1"
        echo module: $module
        set exclude="nothing"
        echo exclude: $exclude
    else
        set module="$1"
        echo module: $module
        set exclude=$1/{CVS*,.svn*,common*,*unxlng*,*unxsol*,*unxmac*,*wntmsc*}
        echo exclude: $exclude
    endif

    if ( "`basename '$1'`" == "*" ) then
        # test for ls overrun
        set dcommand="ls -d $module/*"
        if ( ! { ( $dcommand >> /dev/null ) } ) then
            echo "$0 : ls overrun, trying find $module -mindepth 1 -maxdepth 1"
            # test for find mindepth/maxdepth availability
            set dcommand="find $module -mindepth 1 -maxdepth 1"
            if ( ! { ( $dcommand >> /dev/null ) } ) then
                echo "$0 : find doesn't know options -mindepth -maxdepth"
                echo "$0 : too bad, giving up."
                exit 1
            endif
        endif
        # Only positive list of module subdirectories and files,
        # excluding output directories except $INPATH/{inc,misc/build}
        set dirs="$module/$INPATH/inc $module/$INPATH/misc/build `$dcommand | sed -e '/\(\/\(CVS\|common\|.*unxlng\|.*unxsol\|.*unxmac\|.*wntmsc\|Jamfile\|cscope\.\|tags\|ID\)\)\|^solver\//d'`"
        echo dirs: $dirs
        echo Creating output: $output
        mkid --lang-map=$HOME/devbase/id-lang.map --include='C C++ asm perl java make' $output --statistics $dirs
    else if ( "$1" == "all" ) then
        echo Creating output: $output
        mkid --lang-map=$HOME/devbase/id-lang.map --include='C C++ asm perl java make' $output --statistics
    else
        # all but negative list plus INPATH relevants
        echo Creating output: $output
        mkid --lang-map=$HOME/devbase/id-lang.map --include='C C++ asm perl java make' $output --statistics --prune="$exclude" $module $module/$INPATH/inc $module/$INPATH/misc/build
    endif

else
    echo no ID-utils
endif

Exuberant Ctags

The Exuberant Ctags utility interfaces nicely with Emacs and Vim and enables quick lookup for declarations and definitions of macros, typedefs, constants, enums, variables, structs and classes and their methods and implementation. You should get the latest version available at http://ctags.sourceforge.net/, which currently (2006-08-27) is v5.6, older versions included by distributions for example don't automatically recognize .mk files as makefiles, and v5.6 also added a patch needed for the vim 7.0 omni-completion feature. Ctags creates a file tags in the current directory, if not told otherwise.

As creating a tags file over all modules and directories exceeded the 2GB file size limit, a positive directory list was used to go along with a '*' parameter, identical to the one used in the mkid-script above. The file size of the tags file generated for '*' currently (m182) is 398MB.

ctags-script

For use with the OOo code base a script with a syntax similar to the ID-utils script above comes handy, suggested name: $HOME/devbase/ctags-script

#!/bin/tcsh

# Either the current module, or all modules can be ctag'ed if $1 is
# specified as literal '*' unexpanded. Will be expanded here.
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
# NOTE: ctags on '*' exceeded 2GB file size limit if for _all_ OOo modules and
# no positive dirs list was used.

if ( "$?MYCTAGS" == "0" ) then
    set MYCTAGS="ctags"
endif

if ( { ( which "$MYCTAGS" >> /dev/null ) } ) then
    echo generating ctags
    # Options necessary for the Vim OmniCppComplete plugin,
    # http://www.vim.org/scripts/script.php?script_id=1520
    # --c++-kinds=+p  : Adds prototypes in the database for C++ files.
    # --fields=+iaS   : Adds inheritance (i), access (a) and function 
    #                   signatures (S) informations.
    # --extra=+q      : Adds context to the tag name. Note: Without this
    #                   option, the script cannot get class members.
    set omnicppoptions="--c++-kinds=+p --fields=+iaS --extra=+q"
    if ( "$1" == "--global" ) then
        if ( ! $?UPDMINOREXT ) set UPDMINOREXT=""
        "$MYCTAGS" -h "+.hdl.hrc" --langmap=c:+.hdl.hrc.src $omnicppoptions -R $SOLARVERSION/$INPATH/inc$UPDMINOREXT
    else
        if ( "$1" == "" ) then
            set module="."
        else
            set module="$1"
            echo module: $module
        endif
        # test for ls overrun
        set dcommand="ls -d $module/*"
        if ( ! { ( $dcommand >> /dev/null ) } ) then
            echo "$0 : ls overrun, trying find $module -mindepth 1 -maxdepth 1"
            # test for find mindepth/maxdepth availability
            set dcommand="find $module -mindepth 1 -maxdepth 1"
            if ( ! { ( $dcommand >> /dev/null ) } ) then
                echo "$0 : find doesn't know options -mindepth -maxdepth"
                echo "$0 : too bad, giving up."
                exit 1
            endif
        endif
        # Only positive list of module subdirectories and files,
        # excluding output directories except $INPATH/{inc,misc/build}
        set dirs="$module/$INPATH/inc $module/$INPATH/misc/build `$dcommand | sed -e '/\(\/\(CVS\|\.svn\|common\|.*unxlng\|.*unxsol\|.*unxmac\|.*wntmsc\|Jamfile\|cscope\.\|tags\|ID\)\)\|^solver\//d'`"
        echo dirs: $dirs
        "$MYCTAGS" -h "+.hdl.hrc" --langmap=c:+.hdl.hrc.src $omnicppoptions -R $dirs
    endif
else
    echo no ctags
endif

Ignore messages like
ctags: Warning: cannot open source file "./unxlngi6.pro/misc/build" : No such file or directory
or consider them purely informational.

Note that also here, if more than one module is to be specified, the shell filename glob-patterns and metanotations have to be passed in single quotes. Though tagging an entire OOo code base would result in a "file overflow" with more than 2GB this isn't a problem in practice, at least with Vim, don't know about other editors, since it may search the tags files going up the directory hierarchy if a tag is not found in the current directory's tags file. So generate the tags file in the modules you are interested in, using the script without parameters, then cd $SRC_ROOT and invoke scriptname --global to produce a tags file for the solver.

A final ctags note: In some cases, you might have more than one version of ctags on your system. E.g., there is a version that ships with Emacs (and is often in /usr/local/bin) that doesn't support the same arguments as Exhuberant ctags; if this is the case (you'll see an error message from the script like "unrecognized option `--langmap=c:+.hdl.hrc.src'") then you can set the MYCTAGS variable, e.g., from a bash shell:

MYCTAGS=/usr/bin/ctags $HOME/devbase/ctags-script --global
MYCTAGS=/usr/bin/ctags CTAGS=-e $HOME/devbase/ctags-script --global # generate TAGS for Emacs

If all you have is the Emacs version, you will want to rewrite the script (or provide a better solution here).

Cscope

Cscope is another utility to query a database for code elements. It comes with a cumbersome screen-oriented interactive tool to browse source files, but also interfaces nicely with Vim and Emacs. Unfortunately it is not able to cope with the entire OOo source base it seems, so for '*' even when called with a list of files to work on, at the end it displayed Input string too long, limit 50251 and no output was generated. Didn't investigate yet what exactly is the problem. However, using it on a subset of several modules is possible.

cscope-script

This script may be used to generate a cscope.out database file, same parameter syntax as the mkid-script and ctags-script above. Suggested name: $HOME/devbase/cscope-script

#!/bin/tcsh

# Either the current module, or all modules can be tagID'ed if $1 is
# specified as literal '*' unexpanded. Will be expanded here.
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
# NOTE: cscope on '*' hanged if for _all_ OOo modules and no positive dirs list
# was used. Even with the generated cscope.files it still refuses to complete
# its work.

if ( { ( which cscope >> /dev/null ) } ) then
    echo generating cscope
    if ( "$1" == "" ) then
        set module="."
    else
        set module="$1"
        echo module: $module
    endif
    # test for ls overrun
    set dcommand="ls -d $module/*"
    if ( ! { ( $dcommand >> /dev/null ) } ) then
        echo "$0 : ls overrun, trying find $module -mindepth 1 -maxdepth 1"
        # test for find mindepth/maxdepth availability
        set dcommand="find $module -mindepth 1 -maxdepth 1"
        if ( ! { ( $dcommand >> /dev/null ) } ) then
            echo "$0 : find doesn't know options -mindepth -maxdepth"
            echo "$0 : too bad, giving up."
            exit 1
        endif
    endif
    # Only positive list of module subdirectories and files,
    # excluding output directories except $INPATH/{inc,misc/build}
    set dirs="$module/$INPATH/inc $module/$INPATH/misc/build `$dcommand | sed -e '/\(\/\(CVS\|\.svn\|common\|.*unxlng\|.*unxsol\|.*unxmac\|.*wntmsc\|Jamfile\|cscope\.\|tags\|ID\)\)\|^solver\//d'`"
    echo dirs: $dirs
    ( find $dirs -name '*.[hc]' -o -name '*.[hc]xx' -o -name '*.[hc]pp' -o -name '*.[hs]rc' >cscope.files ) >>& /dev/null
    if ( `uname` == "SunOS" ) then
        cscope -b -c
    else
        cscope -b -c -q
    endif
else
    echo no cscope
endif

Note that the find command is executed in a subshell with stderr redirected to /dev/null to suppress all the find: ./unxlngi6.pro/misc/build: No such file or directory and the like warning messages. Remove the parentheses and the redirection in case you suspect errors in your environment.

All together now

Surely we don't want to invoke all these scripts separately all the times, so here's a small wrapper just to prove that the suggested names actually make sense ;-) let's call it $HOME/devbase/tagsID

#!/bin/tcsh

# Either the current module, or all modules can be tagID'ed if $1 is
# specified as literal '*' unexpanded. Will be expanded here.
# Instead of '*' _any_ shell wildcard should be possible, e.g. '{.,bf_*}'.
# NOTE: ctags on '*' exceeds 2GB file size limit if for _all_ OOo modules.
# NOTE: cscope on '*' hangs if for _all_ OOo modules.
# Which actually is the reason we invoke it last just in case we forgot..

${0:h}/ctags-script "$1"
${0:h}/mkid-script "$1"
${0:h}/cscope-script "$1"

The same syntax as with the other scripts applies: filename glob-patterns and metanotations have to be passed as literals, enquoted with single quotes. Invoking it in a module's directory without passing an argument creates databases for that single module.

Build selected source code files with debug

Sometimes only a few files need to be build with debug instead of an entire module, which significantly saves time. Change into the directory and invoke the following script with the files of interest passed as arguments, for example, in sc/source/core/tool

mkd token.cxx compiler.cxx interpr*.cxx

To also link the library in the module's util directory pass the --link or -l option:

mkd -l token.cxx compiler.cxx interpr*.cxx

mkd

#!/bin/bash
 
# Compile source files (in current directory!) passed as arguments with debug.
# Option --link or -l also links the library in the module's util directory.
 
# Do parallel build, set to empty if not wanted.
PARALLEL="-P4"
 
if [ -z "$INPATH" ]; then
    echo "No \$INPATH, source environment!"
    exit 1
fi
UTIL=""
if [ "$1" == "--link" -o "$1" == "-l" ]; then
    UTIL="Yes"
    shift
fi
 
# Determine the current hierarchy depth by looking upwards for the prj/d.lst
# file, but no more than MAX levels up.
DLST="prj/d.lst"
SUBS=""
MAX=5
for (( LEVEL=0 ; LEVEL < MAX ; ++LEVEL )); do
    if [ -f "${SUBS}${DLST}" ]; then
        break
    fi
    SUBS="../$SUBS"
done
OUTP="${SUBS}${INPATH}/slo"
if [ $LEVEL == $MAX ]; then
    echo "No ${SUBS}${DLST} found! (LEVEL $LEVEL)"
    exit 1
fi
 
ERR=0
# Force compilation of files passed as arguments.
for x in "$@"; do
    FILE="${x//*\//}"
    BASE="${FILE%.*}"
    FULL="${OUTP}/${BASE}.obj"
    rm "$FULL"
    if [ -z "$PARALLEL" ]; then
        dmake debug=t "$FULL"
    fi
    ERR=$?
    if [ $ERR != 0 ]; then
        break
    fi
done
# If no error, compile yet uncompiled files and create archive, if any.
if [ $ERR == 0 ]; then
    dmake $PARALLEL debug=t
    ERR=$?
fi
# Some modules, such as Writer, have an extra archiving step one level up, e.g.
# in sw/source/core/ if files in sw/source/core/layout/ were compiled.
# Do this only if deeper than in module level.
if (( LEVEL > 1 )); then
    if [ $ERR == 0 -a -f ../makefile.mk ]; then
        pushd ..
        dmake debug=t
        ERR=$?
        popd
    fi
fi
# If no error, link library if requested.
if [ $ERR == 0 -a -n "$UTIL" ]; then
    UTIL="${SUBS}util"
    if [ ! -d "$UTIL" ]; then
        echo "No $UTIL directory, no linking."
        exit
    fi
    cd "$UTIL"
    dmake debug=t
    ERR=$?
fi
exit $ERR
Personal tools