bk
This commit is contained in:
commit
a56c9e6818
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
obj/*.o
|
||||
obj/*.gch
|
||||
csope
|
||||
**/*.out
|
||||
src/lex.yy.c
|
38
Makefile
Normal file
38
Makefile
Normal file
@ -0,0 +1,38 @@
|
||||
CC=gcc
|
||||
CCFLAGS:=-ggdb #-D PRODUCTION
|
||||
LDLIBS=-I ${CHDRD} $$(pkg-config --libs ncurses)
|
||||
LEX:=flex
|
||||
|
||||
LEXD:=src/
|
||||
LEXF:=$(shell find ${LEXD} -iname '*.l')
|
||||
GENLEX:=$(subst .l,.c,${LEXF})
|
||||
|
||||
SRCD:=src/
|
||||
OBJD:=obj/
|
||||
SRC:=$(shell find ${SRCD} -iname '*.c') ${GENLEX}
|
||||
OBJ:=$(subst .c,.o,$(subst ${SRCD},${OBJD},${SRC}))
|
||||
|
||||
HDRD:=${SRCD}
|
||||
CHDRD:=${OBJD}
|
||||
HDR:=$(shell find ${HDRD} -iname '*.h')
|
||||
CHDR:=$(addsuffix .gch,$(subst ${HDRD},${CHDRD},${HDR}))
|
||||
|
||||
OUTPUT:=csope
|
||||
|
||||
main: ${CHDR} ${OBJ}
|
||||
${LINK.c} ${LDLIBS} ${OBJ} -o ${OUTPUT}
|
||||
|
||||
obj/%.o: src/%.c
|
||||
${COMPILE.c} $< -o $@
|
||||
|
||||
src/%.c: src/%.l
|
||||
${LEX} -o $@ $<
|
||||
|
||||
obj/%.h.gch: src/%.h
|
||||
${CC} $< -o $@
|
||||
|
||||
clean:
|
||||
-rm ${CHDR}
|
||||
-rm ${GENLEX}
|
||||
-rm ${OBJ}
|
||||
-rm ${OUTPUT}
|
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Csope
|
||||
Fork of Cscope, with various improvements, because cscope is good and shall not be forgotten.
|
||||
|
||||
# Improvements/Changes
|
||||
## User side
|
||||
+ improved gui /*pending*/
|
||||
+ GNU Readline integration (ie. VI/EMACS mode, command history) /*pending*/
|
||||
## To the code
|
||||
+ nuked autoconf, replaced with single Makefile
|
||||
+ removed
|
||||
+ encapsulated changes to the TUI into display.c
|
||||
+ removed macros hell put in place to allow compiling on a dead badger
|
7
TODO
Normal file
7
TODO
Normal file
@ -0,0 +1,7 @@
|
||||
# BUGS
|
||||
+ Changing text double frees:
|
||||
free(): double free detected in tcache 2
|
||||
Aborted
|
||||
+ Normalize tabs and spaces
|
||||
+ Ordering function declarations in global.h by alpha order is not smart
|
||||
+ Handle unused parameters gracefully (#define UNUSED(x) (void)(x))
|
99
ass/emacs.e
Normal file
99
ass/emacs.e
Normal file
@ -0,0 +1,99 @@
|
||||
/ ========================================================================= /
|
||||
/ Copyright (c) 1998-2000, The Santa Cruz Operation /
|
||||
/ All rights reserved./
|
||||
/ /
|
||||
/ Redistribution and use in source and binary forms, with or without/
|
||||
/ modification, are permitted provided that the following conditions are met:/
|
||||
//
|
||||
/ *Redistributions of source code must retain the above copyright notice,/
|
||||
/ this list of conditions and the following disclaimer./
|
||||
//
|
||||
/ *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./
|
||||
//
|
||||
/ *Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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. /
|
||||
/ ========================================================================= /
|
||||
|
||||
/ emacs menu for cscope /
|
||||
((X) cscope (find current word [MACRO])
|
||||
(extern symbol-character)
|
||||
|
||||
/ if this character is not part of a symbol /
|
||||
(cond ((not symbol-character)
|
||||
|
||||
/ if the previous character is not part of a symbol, go to
|
||||
the next word /
|
||||
back
|
||||
(cond ((not symbol-character) forward-word back-word))
|
||||
))
|
||||
/ get the current symbol (leave cursor at beginning of symbol) /
|
||||
(while symbol-character forward) / go past last symbol character /
|
||||
mark / mark this point /
|
||||
back / back to last symbol character /
|
||||
(while (cond (symbol-character (return back)))) / back fails at BOF /
|
||||
(cond ((not symbol-character) forward)) / forward if not at BOF /
|
||||
pickup-region / get the symbol /
|
||||
(local-string symbol)
|
||||
symbol=
|
||||
|
||||
/ if arg > 0 then display the menu /
|
||||
(cond ((> arg 0) (display-menu
|
||||
(format symbol "5 Find functions calling %l()")
|
||||
(format symbol "4 Find functions called by %l()")
|
||||
(format symbol "3 Find global definition of %l")
|
||||
(format symbol "2 Find symbol %l")
|
||||
"1 Call cscope"
|
||||
5)
|
||||
))
|
||||
/ get the selection /
|
||||
(local selection)
|
||||
(selection= (read-character "Selection?"))
|
||||
|
||||
/ if the selection is in range /
|
||||
(cond ((&& (>= selection '1') (<= selection '5'))
|
||||
|
||||
/ if the selection requests finding the symbol /
|
||||
(local-string findsymbol)
|
||||
(findsymbol= "")
|
||||
(cond ((>= selection '2')
|
||||
(findsymbol= (format (char-to-string (- selection 2)) symbol "-%l '%l'"))))
|
||||
|
||||
/ if arg > 1 or < 0 then don't update the cross-reference database /
|
||||
(local-string doption)
|
||||
(doption= "")
|
||||
(cond ((|| (> arg 1) (< arg 0)) (doption= "-d")))
|
||||
|
||||
/ call cscope with usilent mode off /
|
||||
(local oldmode) / save old usilent mode /
|
||||
(oldmode= (set-mode "usilent" 0)) / turn off usilent mode /
|
||||
(run-command (format doption findsymbol "cscope %l %l"))
|
||||
(set-mode "usilent" oldmode) / restore usilent mode /
|
||||
))
|
||||
)
|
||||
/ see if the current character is part of a symbol /
|
||||
(symbol-character ()
|
||||
(local c)
|
||||
(c= current-character)
|
||||
(return (cond ((&& (>= c 'a') (<= c 'z')))
|
||||
((&& (>= c 'A') (<= c 'Z')))
|
||||
((&& (>= c '0') (<= c '9')))
|
||||
((== c '_'))
|
||||
)
|
||||
)
|
||||
)
|
63
ass/gmacs.ml
Normal file
63
ass/gmacs.ml
Normal file
@ -0,0 +1,63 @@
|
||||
; ===========================================================================
|
||||
; Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
; All rights reserved.
|
||||
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions are met:
|
||||
|
||||
; *Redistributions of source code must retain the above copyright notice,
|
||||
; this list of conditions and the following disclaimer.
|
||||
|
||||
; *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.
|
||||
|
||||
; *Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
; =========================================================================
|
||||
|
||||
; cscope.ml (s.cscope.ml) - 1.4 (2/21/84 14:53:58)
|
||||
;
|
||||
; Macro to handle invocation of gmacs by cscope from the
|
||||
; experimental tools. Cscope invokes gmacs with two arguments:
|
||||
;
|
||||
; gmacs +line file
|
||||
;
|
||||
; This macro gobbles the line number, visits the specified file,
|
||||
; and moves to the specified line number.
|
||||
|
||||
(progn
|
||||
args
|
||||
pluses
|
||||
(setq pluses 0)
|
||||
(setq args (argc))
|
||||
(if (> args 1)
|
||||
(progn
|
||||
(if (= (string-to-char "+") (string-to-char (argv 1)))
|
||||
(setq pluses 1)
|
||||
)
|
||||
(setq args (- args 1))
|
||||
(while (> args pluses)
|
||||
(visit-file (argv args))
|
||||
(setq args (- args 1))
|
||||
)
|
||||
(if (= (> (argc) 2) (> pluses 0))
|
||||
(goto-line (argv 1))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
247
ass/ylwrap
Executable file
247
ass/ylwrap
Executable file
@ -0,0 +1,247 @@
|
||||
#! /bin/sh
|
||||
# ylwrap - wrapper for lex/yacc invocations.
|
||||
|
||||
scriptversion=2016-01-11.22; # UTC
|
||||
|
||||
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||||
#
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
get_dirname ()
|
||||
{
|
||||
case $1 in
|
||||
*/*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
|
||||
# Otherwise, we want the empty string (not ".").
|
||||
esac
|
||||
}
|
||||
|
||||
# guard FILE
|
||||
# ----------
|
||||
# The CPP macro used to guard inclusion of FILE.
|
||||
guard ()
|
||||
{
|
||||
printf '%s\n' "$1" \
|
||||
| sed \
|
||||
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
|
||||
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \
|
||||
-e 's/__*/_/g'
|
||||
}
|
||||
|
||||
# quote_for_sed [STRING]
|
||||
# ----------------------
|
||||
# Return STRING (or stdin) quoted to be used as a sed pattern.
|
||||
quote_for_sed ()
|
||||
{
|
||||
case $# in
|
||||
0) cat;;
|
||||
1) printf '%s\n' "$1";;
|
||||
esac \
|
||||
| sed -e 's|[][\\.*]|\\&|g'
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'')
|
||||
echo "$0: No files given. Try '$0 --help' for more information." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
--basedir)
|
||||
basedir=$2
|
||||
shift 2
|
||||
;;
|
||||
-h|--h*)
|
||||
cat <<\EOF
|
||||
Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
|
||||
|
||||
Wrapper for lex/yacc invocations, renaming files as desired.
|
||||
|
||||
INPUT is the input file
|
||||
OUTPUT is one file PROG generates
|
||||
DESIRED is the file we actually want instead of OUTPUT
|
||||
PROGRAM is program to run
|
||||
ARGS are passed to PROG
|
||||
|
||||
Any number of OUTPUT,DESIRED pairs may be used.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v|--v*)
|
||||
echo "ylwrap $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# The input.
|
||||
input=$1
|
||||
shift
|
||||
# We'll later need for a correct munging of "#line" directives.
|
||||
input_sub_rx=`get_dirname "$input" | quote_for_sed`
|
||||
case $input in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
# Absolute path; do nothing.
|
||||
;;
|
||||
*)
|
||||
# Relative path. Make it absolute.
|
||||
input=`pwd`/$input
|
||||
;;
|
||||
esac
|
||||
input_rx=`get_dirname "$input" | quote_for_sed`
|
||||
|
||||
# Since DOS filename conventions don't allow two dots,
|
||||
# the DOS version of Bison writes out y_tab.c instead of y.tab.c
|
||||
# and y_tab.h instead of y.tab.h. Test to see if this is the case.
|
||||
y_tab_nodot=false
|
||||
if test -f y_tab.c || test -f y_tab.h; then
|
||||
y_tab_nodot=true
|
||||
fi
|
||||
|
||||
# The parser itself, the first file, is the destination of the .y.c
|
||||
# rule in the Makefile.
|
||||
parser=$1
|
||||
|
||||
# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
|
||||
# instance, we rename #include "y.tab.h" into #include "parse.h"
|
||||
# during the conversion from y.tab.c to parse.c.
|
||||
sed_fix_filenames=
|
||||
|
||||
# Also rename header guards, as Bison 2.7 for instance uses its header
|
||||
# guard in its implementation file.
|
||||
sed_fix_header_guards=
|
||||
|
||||
while test $# -ne 0; do
|
||||
if test x"$1" = x"--"; then
|
||||
shift
|
||||
break
|
||||
fi
|
||||
from=$1
|
||||
# Handle y_tab.c and y_tab.h output by DOS
|
||||
if $y_tab_nodot; then
|
||||
case $from in
|
||||
"y.tab.c") from=y_tab.c;;
|
||||
"y.tab.h") from=y_tab.h;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
to=$1
|
||||
shift
|
||||
sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
|
||||
sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
|
||||
done
|
||||
|
||||
# The program to run.
|
||||
prog=$1
|
||||
shift
|
||||
# Make any relative path in $prog absolute.
|
||||
case $prog in
|
||||
[\\/]* | ?:[\\/]*) ;;
|
||||
*[\\/]*) prog=`pwd`/$prog ;;
|
||||
esac
|
||||
|
||||
dirname=ylwrap$$
|
||||
do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
mkdir $dirname || exit 1
|
||||
|
||||
cd $dirname
|
||||
|
||||
case $# in
|
||||
0) "$prog" "$input" ;;
|
||||
*) "$prog" "$@" "$input" ;;
|
||||
esac
|
||||
ret=$?
|
||||
|
||||
if test $ret -eq 0; then
|
||||
for from in *
|
||||
do
|
||||
to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
|
||||
if test -f "$from"; then
|
||||
# If $2 is an absolute path name, then just use that,
|
||||
# otherwise prepend '../'.
|
||||
case $to in
|
||||
[\\/]* | ?:[\\/]*) target=$to;;
|
||||
*) target=../$to;;
|
||||
esac
|
||||
|
||||
# Do not overwrite unchanged header files to avoid useless
|
||||
# recompilations. Always update the parser itself: it is the
|
||||
# destination of the .y.c rule in the Makefile. Divert the
|
||||
# output of all other files to a temporary file so we can
|
||||
# compare them to existing versions.
|
||||
if test $from != $parser; then
|
||||
realtarget=$target
|
||||
target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
|
||||
fi
|
||||
|
||||
# Munge "#line" or "#" directives. Don't let the resulting
|
||||
# debug information point at an absolute srcdir. Use the real
|
||||
# output file name, not yy.lex.c for instance. Adjust the
|
||||
# include guards too.
|
||||
sed -e "/^#/!b" \
|
||||
-e "s|$input_rx|$input_sub_rx|" \
|
||||
-e "$sed_fix_filenames" \
|
||||
-e "$sed_fix_header_guards" \
|
||||
"$from" >"$target" || ret=$?
|
||||
|
||||
# Check whether files must be updated.
|
||||
if test "$from" != "$parser"; then
|
||||
if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
|
||||
echo "$to is unchanged"
|
||||
rm -f "$target"
|
||||
else
|
||||
echo "updating $to"
|
||||
mv -f "$target" "$realtarget"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# A missing file is only an error for the parser. This is a
|
||||
# blatant hack to let us support using "yacc -d". If -d is not
|
||||
# specified, don't fail when the header file is "missing".
|
||||
if test "$from" = "$parser"; then
|
||||
ret=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Remove the directory.
|
||||
cd ..
|
||||
rm -rf $dirname
|
||||
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
0
obj/.placeholder
Normal file
0
obj/.placeholder
Normal file
46
src/basename.c
Normal file
46
src/basename.c
Normal file
@ -0,0 +1,46 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* get a file's base name from its path name */
|
||||
|
||||
#include "global.h"
|
||||
|
||||
char *
|
||||
basename(char *path)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if ((s = strrchr(path, '/')) != 0) {
|
||||
return(s + 1);
|
||||
}
|
||||
return(path);
|
||||
}
|
738
src/build.c
Normal file
738
src/build.c
Normal file
@ -0,0 +1,738 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* main functions
|
||||
*/
|
||||
|
||||
#include "build.h"
|
||||
|
||||
#include "global.h" /* FIXME: get rid of this! */
|
||||
|
||||
#include "library.h"
|
||||
|
||||
#include "scanner.h"
|
||||
#include "version.h" /* for FILEVERSION */
|
||||
#include "vp.h"
|
||||
|
||||
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
|
||||
#include <ncurses.h>
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
|
||||
/* Exported variables: */
|
||||
|
||||
BOOL buildonly = NO; /* only build the database */
|
||||
BOOL unconditional = NO; /* unconditionally build database */
|
||||
BOOL fileschanged; /* assume some files changed */
|
||||
|
||||
/* variable copies of the master strings... */
|
||||
char invname_buf[] = INVNAME;
|
||||
char invpost_buf[] = INVPOST;
|
||||
char reffile_buf[] = REFFILE;
|
||||
char *invname = invname_buf; /* inverted index to the database */
|
||||
char *invpost = invpost_buf; /* inverted index postings */
|
||||
char *reffile = reffile_buf; /* cross-reference file path name */
|
||||
|
||||
char *newreffile; /* new cross-reference file name */
|
||||
FILE *newrefs; /* new cross-reference */
|
||||
FILE *postings; /* new inverted index postings */
|
||||
int symrefs = -1; /* cross-reference file */
|
||||
|
||||
INVCONTROL invcontrol; /* inverted file control structure */
|
||||
|
||||
|
||||
/* Local variables: */
|
||||
static char *newinvname; /* new inverted index file name */
|
||||
static char *newinvpost; /* new inverted index postings file name */
|
||||
static long traileroffset; /* file trailer offset */
|
||||
|
||||
|
||||
/* Internal prototypes: */
|
||||
static void cannotindex(void);
|
||||
static int compare(const void *s1, const void *s2);
|
||||
static void copydata(void);
|
||||
static void copyinverted(void);
|
||||
static char *getoldfile(void);
|
||||
static void movefile(char *new, char *old);
|
||||
static void putheader(char *dir);
|
||||
static void fetch_include_from_dbase(char *, size_t);
|
||||
static void putlist(char **names, int count);
|
||||
static BOOL samelist(FILE *oldrefs, char **names, int count);
|
||||
|
||||
|
||||
/* Error handling routine if inverted index creation fails */
|
||||
static void
|
||||
cannotindex(void)
|
||||
{
|
||||
fprintf(stderr, "\
|
||||
cscope: cannot create inverted index; ignoring -q option\n");
|
||||
invertedindex = NO;
|
||||
errorsfound = YES;
|
||||
fprintf(stderr, "\
|
||||
cscope: removed files %s and %s\n",
|
||||
newinvname, newinvpost);
|
||||
unlink(newinvname);
|
||||
unlink(newinvpost);
|
||||
}
|
||||
|
||||
|
||||
/* see if the name list is the same in the cross-reference file */
|
||||
static BOOL
|
||||
samelist(FILE *oldrefs, char **names, int count)
|
||||
{
|
||||
char oldname[PATHLEN + 1]; /* name in old cross-reference */
|
||||
int oldcount;
|
||||
int i;
|
||||
|
||||
/* see if the number of names is the same */
|
||||
if (fscanf(oldrefs, "%d", &oldcount) != 1 ||
|
||||
oldcount != count) {
|
||||
return(NO);
|
||||
}
|
||||
/* see if the name list is the same */
|
||||
for (i = 0; i < count; ++i) {
|
||||
if ((1 != fscanf(oldrefs," %[^\n]",oldname)) ||
|
||||
strnotequal(oldname, names[i])) {
|
||||
return(NO);
|
||||
}
|
||||
}
|
||||
return(YES);
|
||||
}
|
||||
|
||||
|
||||
/* create the file name(s) used for a new cross-referene */
|
||||
|
||||
void setup_build_filenames(char *reffile)
|
||||
{
|
||||
char *path; /* file pathname */
|
||||
char *s; /* pointer to basename in path */
|
||||
|
||||
path = malloc(strlen(reffile) + 10u);
|
||||
strcpy(path, reffile);
|
||||
s = basename(path);
|
||||
*s = '\0';
|
||||
strcat(path, "n");
|
||||
++s;
|
||||
strcpy(s, basename(reffile));
|
||||
newreffile = strdup(path);
|
||||
strcpy(s, basename(invname));
|
||||
newinvname = strdup(path);
|
||||
strcpy(s, basename(invpost));
|
||||
newinvpost = strdup(path);
|
||||
free(path);
|
||||
}
|
||||
|
||||
/* open the database */
|
||||
|
||||
void
|
||||
opendatabase(void)
|
||||
{
|
||||
if ((symrefs = vpopen(reffile, O_BINARY | O_RDONLY)) == -1) {
|
||||
cannotopen(reffile);
|
||||
myexit(1);
|
||||
}
|
||||
blocknumber = -1; /* force next seek to read the first block */
|
||||
|
||||
/* open any inverted index */
|
||||
if (invertedindex == YES &&
|
||||
invopen(&invcontrol, invname, invpost, INVAVAIL) == -1) {
|
||||
askforreturn(); /* so user sees message */
|
||||
invertedindex = NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* rebuild the database */
|
||||
void
|
||||
rebuild(void)
|
||||
{
|
||||
close(symrefs);
|
||||
if (invertedindex == YES) {
|
||||
invclose(&invcontrol);
|
||||
nsrcoffset = 0;
|
||||
npostings = 0;
|
||||
}
|
||||
build();
|
||||
opendatabase();
|
||||
|
||||
/* revert to the initial display */
|
||||
if (refsfound != NULL) {
|
||||
fclose(refsfound);
|
||||
refsfound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* build the cross-reference */
|
||||
void
|
||||
build(void)
|
||||
{
|
||||
unsigned long i;
|
||||
FILE *oldrefs; /* old cross-reference file */
|
||||
time_t reftime; /* old crossref modification time */
|
||||
char *file; /* current file */
|
||||
char *oldfile; /* file in old cross-reference */
|
||||
char newdir[PATHLEN + 1]; /* directory in new cross-reference */
|
||||
char olddir[PATHLEN + 1]; /* directory in old cross-reference */
|
||||
char oldname[PATHLEN + 1]; /* name in old cross-reference */
|
||||
unsigned long oldnum; /* number in old cross-ref */
|
||||
struct stat statstruct; /* file status */
|
||||
unsigned long firstfile; /* first source file in pass */
|
||||
unsigned long lastfile; /* last source file in pass */
|
||||
int built = 0; /* built crossref for these files */
|
||||
int copied = 0; /* copied crossref for these files */
|
||||
unsigned long fileindex; /* source file name index */
|
||||
BOOL interactive = YES; /* output progress messages */
|
||||
|
||||
/* normalize the current directory relative to the home directory so
|
||||
the cross-reference is not rebuilt when the user's login is moved */
|
||||
strcpy(newdir, currentdir);
|
||||
if (strcmp(currentdir, home) == 0) {
|
||||
strcpy(newdir, "$HOME");
|
||||
} else if (strncmp(currentdir, home, strlen(home)) == 0) {
|
||||
snprintf(newdir, sizeof(newdir), "$HOME%s", currentdir + strlen(home));
|
||||
}
|
||||
/* sort the source file names (needed for rebuilding) */
|
||||
qsort(srcfiles, nsrcfiles, sizeof(*srcfiles), compare);
|
||||
|
||||
/* if there is an old cross-reference and its current directory matches */
|
||||
/* or this is an unconditional build */
|
||||
if ((oldrefs = vpfopen(reffile, "rb")) != NULL
|
||||
&& unconditional == NO
|
||||
&& fscanf(oldrefs, "cscope %d %" PATHLEN_STR "s", &fileversion, olddir) == 2
|
||||
&& (strcmp(olddir, currentdir) == 0 /* remain compatible */
|
||||
|| strcmp(olddir, newdir) == 0)) {
|
||||
/* get the cross-reference file's modification time */
|
||||
fstat(fileno(oldrefs), &statstruct);
|
||||
reftime = statstruct.st_mtime;
|
||||
if (fileversion >= 8) {
|
||||
BOOL oldcompress = YES;
|
||||
BOOL oldinvertedindex = NO;
|
||||
BOOL oldtruncate = NO;
|
||||
int c;
|
||||
|
||||
/* see if there are options in the database */
|
||||
for (;;) {
|
||||
while((c = getc(oldrefs)) == ' ')
|
||||
; /* do nothing */
|
||||
if (c != '-') {
|
||||
ungetc(c, oldrefs);
|
||||
break;
|
||||
}
|
||||
switch (getc(oldrefs)) {
|
||||
case 'c': /* ASCII characters only */
|
||||
oldcompress = NO;
|
||||
break;
|
||||
case 'q': /* quick search */
|
||||
oldinvertedindex = YES;
|
||||
fscanf(oldrefs, "%ld", &totalterms);
|
||||
break;
|
||||
case 'T': /* truncate symbols to 8 characters */
|
||||
oldtruncate = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* check the old and new option settings */
|
||||
if (oldcompress != compress || oldtruncate != trun_syms) {
|
||||
posterr("\
|
||||
cscope: -c or -T option mismatch between command line and old symbol database\n");
|
||||
goto force;
|
||||
}
|
||||
if (oldinvertedindex != invertedindex) {
|
||||
posterr("\
|
||||
cscope: -q option mismatch between command line and old symbol database\n");
|
||||
if (invertedindex == NO) {
|
||||
posterr("cscope: removed files %s and %s\n",
|
||||
invname, invpost);
|
||||
unlink(invname);
|
||||
unlink(invpost);
|
||||
}
|
||||
goto outofdate;
|
||||
}
|
||||
/* seek to the trailer */
|
||||
if (fscanf(oldrefs, "%ld", &traileroffset) != 1 ||
|
||||
fseek(oldrefs, traileroffset, SEEK_SET) == -1) {
|
||||
posterr("cscope: incorrect symbol database file format\n");
|
||||
goto force;
|
||||
}
|
||||
}
|
||||
/* if assuming that some files have changed */
|
||||
if (fileschanged == YES) {
|
||||
goto outofdate;
|
||||
}
|
||||
/* see if the directory lists are the same */
|
||||
if (samelist(oldrefs, srcdirs, nsrcdirs) == NO
|
||||
|| samelist(oldrefs, incdirs, nincdirs) == NO
|
||||
/* get the old number of files */
|
||||
|| fscanf(oldrefs, "%lu", &oldnum) != 1
|
||||
/* skip the string space size */
|
||||
|| (fileversion >= 9 && fscanf(oldrefs, "%*s") != 0)) {
|
||||
goto outofdate;
|
||||
}
|
||||
/* see if the list of source files is the same and
|
||||
none have been changed up to the included files */
|
||||
for (i = 0; i < nsrcfiles; ++i) {
|
||||
if ((1 != fscanf(oldrefs," %[^\n]",oldname))
|
||||
|| strnotequal(oldname, srcfiles[i])
|
||||
|| (lstat(srcfiles[i], &statstruct) != 0)
|
||||
|| (statstruct.st_mtime > reftime)
|
||||
) {
|
||||
goto outofdate;
|
||||
}
|
||||
}
|
||||
/* the old cross-reference is up-to-date */
|
||||
/* so get the list of included files */
|
||||
while (i++ < oldnum && fgets(oldname, sizeof(oldname), oldrefs)) {
|
||||
addsrcfile(oldname);
|
||||
}
|
||||
fclose(oldrefs);
|
||||
return;
|
||||
|
||||
outofdate:
|
||||
/* if the database format has changed, rebuild it all */
|
||||
if (fileversion != FILEVERSION) {
|
||||
fprintf(stderr, "\
|
||||
cscope: converting to new symbol database file format\n");
|
||||
goto force;
|
||||
}
|
||||
/* reopen the old cross-reference file for fast scanning */
|
||||
if ((symrefs = vpopen(reffile, O_BINARY | O_RDONLY)) == -1) {
|
||||
postfatal("cscope: cannot open file %s\n", reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/* get the first file name in the old cross-reference */
|
||||
blocknumber = -1;
|
||||
read_block(); /* read the first cross-ref block */
|
||||
scanpast('\t'); /* skip the header */
|
||||
oldfile = getoldfile();
|
||||
} else { /* force cross-referencing of all the source files */
|
||||
force:
|
||||
reftime = 0;
|
||||
oldfile = NULL;
|
||||
}
|
||||
/* open the new cross-reference file */
|
||||
if ((newrefs = myfopen(newreffile, "wb")) == NULL) {
|
||||
postfatal("cscope: cannot open file %s\n", reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
if (invertedindex == YES && (postings = myfopen(temp1, "wb")) == NULL) {
|
||||
cannotwrite(temp1);
|
||||
cannotindex();
|
||||
}
|
||||
putheader(newdir);
|
||||
fileversion = FILEVERSION;
|
||||
if (buildonly == YES && verbosemode != YES && !isatty(0)) {
|
||||
interactive = NO;
|
||||
} else {
|
||||
searchcount = 0;
|
||||
}
|
||||
/* output the leading tab expected by crossref() */
|
||||
dbputc('\t');
|
||||
|
||||
/* make passes through the source file list until the last level of
|
||||
included files is processed */
|
||||
firstfile = 0;
|
||||
lastfile = nsrcfiles;
|
||||
if (invertedindex == YES) {
|
||||
srcoffset = malloc((nsrcfiles + 1u) * sizeof(*srcoffset));
|
||||
}
|
||||
for (;;) {
|
||||
progress("Building symbol database", (long)built,
|
||||
(long)lastfile);
|
||||
if (linemode == NO)
|
||||
refresh();
|
||||
|
||||
/* get the next source file name */
|
||||
for (fileindex = firstfile; fileindex < lastfile; ++fileindex) {
|
||||
|
||||
/* display the progress about every three seconds */
|
||||
if (interactive == YES && fileindex % 10 == 0) {
|
||||
progress("Building symbol database", fileindex, lastfile);
|
||||
}
|
||||
/* if the old file has been deleted get the next one */
|
||||
file = srcfiles[fileindex];
|
||||
while (oldfile != NULL && strcmp(file, oldfile) > 0) {
|
||||
oldfile = getoldfile();
|
||||
}
|
||||
/* if there isn't an old database or this is a new file */
|
||||
if (oldfile == NULL || strcmp(file, oldfile) < 0) {
|
||||
crossref(file);
|
||||
++built;
|
||||
} else if (lstat(file, &statstruct) == 0
|
||||
&& statstruct.st_mtime > reftime) {
|
||||
/* if this file was modified */
|
||||
crossref(file);
|
||||
++built;
|
||||
|
||||
/* skip its old crossref so modifying the last source
|
||||
* file does not cause all included files to be built.
|
||||
* Unfortunately a new file that is alphabetically
|
||||
* last will cause all included files to be build, but
|
||||
* this is less likely */
|
||||
oldfile = getoldfile();
|
||||
} else {
|
||||
/* copy its cross-reference */
|
||||
putfilename(file);
|
||||
if (invertedindex == YES) {
|
||||
copyinverted();
|
||||
} else {
|
||||
copydata();
|
||||
}
|
||||
++copied;
|
||||
oldfile = getoldfile();
|
||||
}
|
||||
}
|
||||
/* see if any included files were found */
|
||||
if (lastfile == nsrcfiles) {
|
||||
break;
|
||||
}
|
||||
firstfile = lastfile;
|
||||
lastfile = nsrcfiles;
|
||||
if (invertedindex == YES) {
|
||||
srcoffset = realloc(srcoffset, (nsrcfiles + 1) * sizeof(*srcoffset));
|
||||
}
|
||||
/* sort the included file names */
|
||||
qsort(srcfiles + firstfile, lastfile - firstfile, sizeof(*srcfiles), compare);
|
||||
}
|
||||
/* add a null file name to the trailing tab */
|
||||
putfilename("");
|
||||
dbputc('\n');
|
||||
|
||||
/* get the file trailer offset */
|
||||
traileroffset = dboffset;
|
||||
|
||||
/* output the source and include directory and file lists */
|
||||
putlist(srcdirs, nsrcdirs);
|
||||
putlist(incdirs, nincdirs);
|
||||
putlist(srcfiles, nsrcfiles);
|
||||
if (fflush(newrefs) == EOF) {
|
||||
/* rewind doesn't check for write failure */
|
||||
cannotwrite(newreffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* create the inverted index if requested */
|
||||
if (invertedindex == YES) {
|
||||
char sortcommand[PATHLEN + 1];
|
||||
|
||||
if (fflush(postings) == EOF) {
|
||||
cannotwrite(temp1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
fstat(fileno(postings), &statstruct);
|
||||
fclose(postings);
|
||||
snprintf(sortcommand, sizeof(sortcommand), "env LC_ALL=C sort -T %s %s", tmpdir, temp1);
|
||||
if ((postings = mypopen(sortcommand, "r")) == NULL) {
|
||||
fprintf(stderr, "cscope: cannot open pipe to sort command\n");
|
||||
cannotindex();
|
||||
} else {
|
||||
if ((totalterms = invmake(newinvname, newinvpost, postings)) > 0) {
|
||||
movefile(newinvname, invname);
|
||||
movefile(newinvpost, invpost);
|
||||
} else {
|
||||
cannotindex();
|
||||
}
|
||||
mypclose(postings);
|
||||
}
|
||||
unlink(temp1);
|
||||
free(srcoffset);
|
||||
}
|
||||
/* rewrite the header with the trailer offset and final option list */
|
||||
rewind(newrefs);
|
||||
putheader(newdir);
|
||||
fclose(newrefs);
|
||||
|
||||
/* close the old database file */
|
||||
if (symrefs >= 0) {
|
||||
close(symrefs);
|
||||
}
|
||||
if (oldrefs != NULL) {
|
||||
fclose(oldrefs);
|
||||
}
|
||||
/* replace it with the new database file */
|
||||
movefile(newreffile, reffile);
|
||||
}
|
||||
|
||||
|
||||
/* string comparison function for qsort */
|
||||
static int
|
||||
compare(const void *arg_s1, const void *arg_s2)
|
||||
{
|
||||
const char **s1 = (const char **) arg_s1;
|
||||
const char **s2 = (const char **) arg_s2;
|
||||
|
||||
return(strcmp(*s1, *s2));
|
||||
}
|
||||
|
||||
|
||||
/* seek to the trailer, in a given file */
|
||||
void
|
||||
seek_to_trailer(FILE *f)
|
||||
{
|
||||
if (fscanf(f, "%ld", &traileroffset) != 1) {
|
||||
postfatal("cscope: cannot read trailer offset from file %s\n", reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
if (fseek(f, traileroffset, SEEK_SET) == -1) {
|
||||
postfatal("cscope: cannot seek to trailer in file %s\n", reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* get the next file name in the old cross-reference */
|
||||
static char *
|
||||
getoldfile(void)
|
||||
{
|
||||
static char file[PATHLEN + 1]; /* file name in old crossref */
|
||||
|
||||
if (blockp != NULL) {
|
||||
do {
|
||||
if (*blockp == NEWFILE) {
|
||||
skiprefchar();
|
||||
fetch_string_from_dbase(file, sizeof(file));
|
||||
if (file[0] != '\0') { /* if not end-of-crossref */
|
||||
return(file);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
} while (scanpast('\t') != NULL);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Free all storage allocated for filenames: */
|
||||
void free_newbuildfiles(void)
|
||||
{
|
||||
free(newinvname);
|
||||
free(newinvpost);
|
||||
free(newreffile);
|
||||
}
|
||||
|
||||
|
||||
/* output the cscope version, current directory, database format options, and
|
||||
the database trailer offset */
|
||||
static void
|
||||
putheader(char *dir)
|
||||
{
|
||||
dboffset = fprintf(newrefs, "cscope %d %s", FILEVERSION, dir);
|
||||
if (compress == NO) {
|
||||
dboffset += fprintf(newrefs, " -c");
|
||||
}
|
||||
if (invertedindex == YES) {
|
||||
dboffset += fprintf(newrefs, " -q %.10ld", totalterms);
|
||||
} else {
|
||||
/* leave space so if the header is overwritten without -q
|
||||
* because writing the inverted index failed, the header
|
||||
* is the same length */
|
||||
dboffset += fprintf(newrefs, " ");
|
||||
}
|
||||
if (trun_syms == YES) {
|
||||
dboffset += fprintf(newrefs, " -T");
|
||||
}
|
||||
|
||||
dboffset += fprintf(newrefs, " %.10ld\n", traileroffset);
|
||||
#ifdef PRINTF_RETVAL_BROKEN
|
||||
dboffset = ftell(newrefs);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* put the name list into the cross-reference file */
|
||||
static void
|
||||
putlist(char **names, int count)
|
||||
{
|
||||
int i, size = 0;
|
||||
|
||||
fprintf(newrefs, "%d\n", count);
|
||||
if (names == srcfiles) {
|
||||
|
||||
/* calculate the string space needed */
|
||||
for (i = 0; i < count; ++i) {
|
||||
size += strlen(names[i]) + 1;
|
||||
}
|
||||
fprintf(newrefs, "%d\n", size);
|
||||
}
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (fputs(names[i], newrefs) == EOF ||
|
||||
putc('\n', newrefs) == EOF) {
|
||||
cannotwrite(newreffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* copy this file's symbol data */
|
||||
static void
|
||||
copydata(void)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
setmark('\t');
|
||||
cp = blockp;
|
||||
for (;;) {
|
||||
/* copy up to the next \t */
|
||||
do { /* innermost loop optimized to only one test */
|
||||
while (*cp != '\t') {
|
||||
dbputc(*cp++);
|
||||
}
|
||||
} while (*++cp == '\0' && (cp = read_block()) != NULL);
|
||||
dbputc('\t'); /* copy the tab */
|
||||
|
||||
/* get the next character */
|
||||
/* HBB 2010-08-21: potential problem if above loop was left
|
||||
* with cp==NULL */
|
||||
if (cp && (*(cp + 1) == '\0')) {
|
||||
cp = read_block();
|
||||
}
|
||||
/* exit if at the end of this file's data */
|
||||
if (cp == NULL || *cp == NEWFILE) {
|
||||
break;
|
||||
}
|
||||
/* look for an #included file */
|
||||
if (*cp == INCLUDE) {
|
||||
char symbol[PATLEN + 1];
|
||||
blockp = cp;
|
||||
fetch_include_from_dbase(symbol, sizeof(symbol));
|
||||
writestring(symbol);
|
||||
setmark('\t');
|
||||
cp = blockp;
|
||||
}
|
||||
}
|
||||
blockp = cp;
|
||||
}
|
||||
|
||||
/* copy this file's symbol data and output the inverted index postings */
|
||||
|
||||
static void
|
||||
copyinverted(void)
|
||||
{
|
||||
char *cp;
|
||||
char c;
|
||||
int type; /* reference type (mark character) */
|
||||
char symbol[PATLEN + 1];
|
||||
|
||||
/* note: this code was expanded in-line for speed */
|
||||
/* while (scanpast('\n') != NULL) { */
|
||||
/* other macros were replaced by code using cp instead of blockp */
|
||||
cp = blockp;
|
||||
for (;;) {
|
||||
setmark('\n');
|
||||
do { /* innermost loop optimized to only one test */
|
||||
while (*cp != '\n') {
|
||||
dbputc(*cp++);
|
||||
}
|
||||
} while (*++cp == '\0' && (cp = read_block()) != NULL);
|
||||
dbputc('\n'); /* copy the newline */
|
||||
|
||||
/* get the next character */
|
||||
/* HBB 2010-08-21: potential problem if above loop was left
|
||||
* with cp==NULL */
|
||||
if (cp && (*(cp + 1) == '\0')) {
|
||||
cp = read_block();
|
||||
}
|
||||
/* exit if at the end of this file's data */
|
||||
if (cp == NULL) {
|
||||
break;
|
||||
}
|
||||
switch (*cp) {
|
||||
case '\n':
|
||||
lineoffset = dboffset + 1;
|
||||
continue;
|
||||
case '\t':
|
||||
dbputc('\t');
|
||||
blockp = cp;
|
||||
type = getrefchar();
|
||||
switch (type) {
|
||||
case NEWFILE: /* file name */
|
||||
return;
|
||||
case INCLUDE: /* #included file */
|
||||
fetch_include_from_dbase(symbol, sizeof(symbol));
|
||||
goto output;
|
||||
}
|
||||
dbputc(type);
|
||||
skiprefchar();
|
||||
fetch_string_from_dbase(symbol, sizeof(symbol));
|
||||
goto output;
|
||||
}
|
||||
c = *cp;
|
||||
if (c & 0200) { /* digraph char? */
|
||||
c = dichar1[(c & 0177) / 8];
|
||||
}
|
||||
/* if this is a symbol */
|
||||
if (isalpha((unsigned char)c) || c == '_') {
|
||||
blockp = cp;
|
||||
fetch_string_from_dbase(symbol, sizeof(symbol));
|
||||
type = ' ';
|
||||
output:
|
||||
putposting(symbol, type);
|
||||
writestring(symbol);
|
||||
if (blockp == NULL) {
|
||||
return;
|
||||
}
|
||||
cp = blockp;
|
||||
}
|
||||
}
|
||||
blockp = cp;
|
||||
}
|
||||
|
||||
|
||||
/* replace the old file with the new file */
|
||||
static void
|
||||
movefile(char *new, char *old)
|
||||
{
|
||||
unlink(old);
|
||||
if (rename(new, old) == -1) {
|
||||
myperror("cscope");
|
||||
postfatal("cscope: cannot rename file %s to file %s\n",
|
||||
new, old);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* process the #included file in the old database */
|
||||
static void
|
||||
fetch_include_from_dbase(char *s, size_t length)
|
||||
{
|
||||
dbputc(INCLUDE);
|
||||
skiprefchar();
|
||||
fetch_string_from_dbase(s, length);
|
||||
incfile(s + 1, s);
|
||||
}
|
||||
|
70
src/build.h
Normal file
70
src/build.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 2001, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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 CSCOPE_BUILD_H
|
||||
#define CSCOPE_BUILD_H
|
||||
|
||||
#include "global.h" /* FIXME: temp. only */
|
||||
#include "invlib.h"
|
||||
|
||||
/* types and macros of build.c to be used by other modules */
|
||||
|
||||
/* database output macros that update its offset */
|
||||
#define dbputc(c) (++dboffset, (void) putc(c, newrefs))
|
||||
#define dbfputs(s) (dboffset += strlen(s), fputs(s, newrefs))
|
||||
|
||||
/* declarations for globals defined in build.c */
|
||||
|
||||
extern BOOL buildonly; /* only build the database */
|
||||
extern BOOL unconditional; /* unconditionally build database */
|
||||
extern BOOL fileschanged; /* assume some files changed */
|
||||
|
||||
extern char *reffile; /* cross-reference file path name */
|
||||
extern char *invname; /* inverted index to the database */
|
||||
extern char *invpost; /* inverted index postings */
|
||||
extern char *newreffile; /* new cross-reference file name */
|
||||
extern FILE *newrefs; /* new cross-reference */
|
||||
extern FILE *postings; /* new inverted index postings */
|
||||
extern int symrefs; /* cross-reference file */
|
||||
|
||||
extern INVCONTROL invcontrol; /* inverted file control structure */
|
||||
|
||||
/* Prototypes of external functions defined by build.c */
|
||||
|
||||
void build(void);
|
||||
void free_newbuildfiles(void);
|
||||
void opendatabase(void);
|
||||
void rebuild(void);
|
||||
void setup_build_filenames(char *reffile);
|
||||
void seek_to_trailer(FILE *f);
|
||||
|
||||
#endif /* CSCOPE_BUILD_H */
|
934
src/command.c
Normal file
934
src/command.c
Normal file
@ -0,0 +1,934 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol or text cross-reference
|
||||
*
|
||||
* command functions
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "build.h" /* for rebuild() */
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
|
||||
#include <ncurses.h>
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
int selecting; /* whether the (upper) symbol list is being browsed */
|
||||
unsigned int curdispline = 0;
|
||||
|
||||
BOOL caseless; /* ignore letter case when searching */
|
||||
BOOL *change; /* change this line */
|
||||
BOOL changing; /* changing text */
|
||||
char newpat[PATLEN + 1]; /* new pattern */
|
||||
/* HBB 20040430: renamed to avoid lots of clashes with function arguments
|
||||
* also named 'pattern' */
|
||||
char Pattern[PATLEN + 1]; /* symbol or text pattern */
|
||||
|
||||
/* HBB FIXME 20060419: these should almost certainly be const */
|
||||
static char appendprompt[] = "Append to file: ";
|
||||
static char pipeprompt[] = "Pipe to shell command: ";
|
||||
static char readprompt[] = "Read from file: ";
|
||||
static char toprompt[] = "To: ";
|
||||
|
||||
|
||||
/* Internal prototypes: */
|
||||
static BOOL changestring(void);
|
||||
static void clearprompt(void);
|
||||
static void mark(unsigned int i);
|
||||
static void scrollbar(MOUSE *p);
|
||||
|
||||
|
||||
/* execute the command */
|
||||
BOOL
|
||||
command(int commandc)
|
||||
{
|
||||
char filename[PATHLEN + 1]; /* file path name */
|
||||
MOUSE *p; /* mouse data */
|
||||
int c, i;
|
||||
FILE *file;
|
||||
struct cmd *curritem, *item; /* command history */
|
||||
char *s;
|
||||
|
||||
switch (commandc) {
|
||||
case ctrl('C'): /* toggle caseless mode */
|
||||
if (caseless == NO) {
|
||||
caseless = YES;
|
||||
postmsg2("Caseless mode is now ON");
|
||||
} else {
|
||||
caseless = NO;
|
||||
postmsg2("Caseless mode is now OFF");
|
||||
}
|
||||
egrepcaseless(caseless); /* turn on/off -i flag */
|
||||
return(NO);
|
||||
|
||||
case ctrl('R'): /* rebuild the cross reference */
|
||||
if (isuptodate == YES) {
|
||||
postmsg("The -d option prevents rebuilding the symbol database");
|
||||
return(NO);
|
||||
}
|
||||
exitcurses();
|
||||
freefilelist(); /* remake the source file list */
|
||||
makefilelist();
|
||||
rebuild();
|
||||
if (errorsfound == YES) {
|
||||
errorsfound = NO;
|
||||
askforreturn();
|
||||
}
|
||||
entercurses();
|
||||
clearmsg(); /* clear any previous message */
|
||||
totallines = 0;
|
||||
disprefs = 0;
|
||||
topline = nextline = 1;
|
||||
selecting = 0;
|
||||
break;
|
||||
|
||||
#if UNIXPC
|
||||
case ESC: /* possible unixpc mouse selection */
|
||||
#endif
|
||||
case ctrl('X'): /* mouse selection */
|
||||
if ((p = getmouseaction(DUMMYCHAR)) == NULL) {
|
||||
return(NO); /* unknown control sequence */
|
||||
}
|
||||
/* if the button number is a scrollbar tag */
|
||||
if (p->button == '0') {
|
||||
scrollbar(p);
|
||||
break;
|
||||
}
|
||||
/* ignore a sweep */
|
||||
if (p->x2 >= 0) {
|
||||
return(NO);
|
||||
}
|
||||
/* if this is a line selection */
|
||||
if (p->y1 < FLDLINE) {
|
||||
|
||||
/* find the selected line */
|
||||
/* note: the selection is forced into range */
|
||||
for (i = disprefs - 1; i > 0; --i) {
|
||||
if (p->y1 >= displine[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* display it in the file with the editor */
|
||||
editref(i);
|
||||
} else { /* this is an input field selection */
|
||||
field = p->y1 - FLDLINE;
|
||||
/* force it into range */
|
||||
if (field >= FIELDS) {
|
||||
field = FIELDS - 1;
|
||||
}
|
||||
setfield();
|
||||
resetcmd();
|
||||
return(NO);
|
||||
}
|
||||
break;
|
||||
|
||||
case '\t': /* go to next input field */
|
||||
if (disprefs) {
|
||||
selecting = !selecting;
|
||||
if (selecting) {
|
||||
move(displine[curdispline], 0);
|
||||
refresh();
|
||||
} else {
|
||||
atfield();
|
||||
resetcmd();
|
||||
}
|
||||
}
|
||||
return(NO);
|
||||
|
||||
#ifdef KEY_ENTER
|
||||
case KEY_ENTER:
|
||||
#endif
|
||||
case '\r':
|
||||
case '\n': /* go to reference */
|
||||
if (selecting) {
|
||||
editref(curdispline);
|
||||
return(YES);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case ctrl('N'):
|
||||
#ifdef KEY_DOWN
|
||||
case KEY_DOWN:
|
||||
#endif
|
||||
#ifdef KEY_RIGHT
|
||||
case KEY_RIGHT:
|
||||
#endif
|
||||
if (selecting) {
|
||||
if ((curdispline + 1) < disprefs) {
|
||||
move(displine[++curdispline], 0);
|
||||
refresh();
|
||||
}
|
||||
} else {
|
||||
field = (field + 1) % FIELDS;
|
||||
setfield();
|
||||
atfield();
|
||||
resetcmd();
|
||||
}
|
||||
return(NO);
|
||||
|
||||
case ctrl('P'): /* go to previous input field */
|
||||
#ifdef KEY_UP
|
||||
case KEY_UP:
|
||||
#endif
|
||||
#ifdef KEY_LEFT
|
||||
case KEY_LEFT:
|
||||
#endif
|
||||
if (selecting) {
|
||||
if (curdispline) {
|
||||
move(displine[--curdispline], 0);
|
||||
refresh();
|
||||
}
|
||||
} else {
|
||||
field = (field + (FIELDS - 1)) % FIELDS;
|
||||
setfield();
|
||||
atfield();
|
||||
resetcmd();
|
||||
}
|
||||
return(NO);
|
||||
#ifdef KEY_HOME
|
||||
case KEY_HOME: /* go to first input field */
|
||||
if (selecting) {
|
||||
curdispline = 0;
|
||||
move(REFLINE, 0);
|
||||
refresh();
|
||||
} else {
|
||||
field = 0;
|
||||
setfield();
|
||||
atfield();
|
||||
resetcmd();
|
||||
}
|
||||
return(NO);
|
||||
#endif
|
||||
|
||||
#ifdef KEY_LL
|
||||
case KEY_LL: /* go to last input field */
|
||||
if (selecting) {
|
||||
move(displine[disprefs - 1], 0);
|
||||
refresh();
|
||||
} else {
|
||||
field = FIELDS - 1;
|
||||
setfield();
|
||||
atfield();
|
||||
resetcmd();
|
||||
}
|
||||
return(NO);
|
||||
#endif /* def(KEY_LL) */
|
||||
|
||||
case ' ': /* display next page */
|
||||
case '+':
|
||||
case ctrl('V'):
|
||||
#ifdef KEY_NPAGE
|
||||
case KEY_NPAGE:
|
||||
#endif
|
||||
/* don't redisplay if there are no lines */
|
||||
if (totallines == 0) {
|
||||
return(NO);
|
||||
}
|
||||
/* note: seekline() is not used to move to the next
|
||||
* page because display() leaves the file pointer at
|
||||
* the next page to optimize paging forward
|
||||
*/
|
||||
curdispline = 0;
|
||||
break;
|
||||
|
||||
case ctrl('H'):
|
||||
case '-': /* display previous page */
|
||||
#ifdef KEY_PPAGE
|
||||
case KEY_PPAGE:
|
||||
#endif
|
||||
/* don't redisplay if there are no lines */
|
||||
if (totallines == 0) {
|
||||
return(NO);
|
||||
}
|
||||
|
||||
curdispline = 0;
|
||||
|
||||
/* if there are only two pages, just go to the other one */
|
||||
if (totallines <= 2 * mdisprefs) {
|
||||
break;
|
||||
}
|
||||
/* if on first page but not at beginning, go to beginning */
|
||||
nextline -= mdisprefs; /* already at next page */
|
||||
if (nextline > 1 && nextline <= mdisprefs) {
|
||||
nextline = 1;
|
||||
} else {
|
||||
nextline -= mdisprefs;
|
||||
if (nextline < 1) {
|
||||
nextline = totallines - mdisprefs + 1;
|
||||
if (nextline < 1) {
|
||||
nextline = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
seekline(nextline);
|
||||
break;
|
||||
|
||||
case '>': /* write or append the lines to a file */
|
||||
if (totallines == 0) {
|
||||
postmsg("There are no lines to write to a file");
|
||||
} else { /* get the file name */
|
||||
move(PRLINE, 0);
|
||||
addstr("Write to file: ");
|
||||
s = "w";
|
||||
if ((c = mygetch()) == '>') {
|
||||
move(PRLINE, 0);
|
||||
addstr(appendprompt);
|
||||
c = '\0';
|
||||
s = "a";
|
||||
}
|
||||
if (c != '\r' &&
|
||||
mygetline("", newpat, COLS - sizeof(appendprompt), c, NO) > 0) {
|
||||
shellpath(filename, sizeof(filename), newpat);
|
||||
if ((file = myfopen(filename, s)) == NULL) {
|
||||
cannotopen(filename);
|
||||
} else {
|
||||
seekline(1);
|
||||
while ((c = getc(refsfound)) != EOF) {
|
||||
putc(c, file);
|
||||
}
|
||||
seekline(topline);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
clearprompt();
|
||||
}
|
||||
return(NO); /* return to the previous field */
|
||||
|
||||
case '<': /* read lines from a file */
|
||||
move(PRLINE, 0);
|
||||
addstr(readprompt);
|
||||
if (mygetline("", newpat, COLS - sizeof(readprompt), '\0', NO) > 0) {
|
||||
clearprompt();
|
||||
shellpath(filename, sizeof(filename), newpat);
|
||||
if (readrefs(filename) == NO) {
|
||||
postmsg2("Ignoring an empty file");
|
||||
return(NO);
|
||||
}
|
||||
return(YES);
|
||||
}
|
||||
clearprompt();
|
||||
return(NO);
|
||||
|
||||
case '^': /* pipe the lines through a shell command */
|
||||
case '|': /* pipe the lines to a shell command */
|
||||
if (totallines == 0) {
|
||||
postmsg("There are no lines to pipe to a shell command");
|
||||
return(NO);
|
||||
}
|
||||
/* get the shell command */
|
||||
move(PRLINE, 0);
|
||||
addstr(pipeprompt);
|
||||
if (mygetline("", newpat, COLS - sizeof(pipeprompt), '\0', NO) == 0) {
|
||||
clearprompt();
|
||||
return(NO);
|
||||
}
|
||||
/* if the ^ command, redirect output to a temp file */
|
||||
if (commandc == '^') {
|
||||
strcat(strcat(newpat, " >"), temp2);
|
||||
/* HBB 20020708: somebody might have even
|
||||
* their non-interactive default shells
|
||||
* complain about clobbering
|
||||
* redirections... --> delete before
|
||||
* overwriting */
|
||||
remove(temp2);
|
||||
}
|
||||
exitcurses();
|
||||
if ((file = mypopen(newpat, "w")) == NULL) {
|
||||
fprintf(stderr, "\
|
||||
cscope: cannot open pipe to shell command: %s\n", newpat);
|
||||
} else {
|
||||
seekline(1);
|
||||
while ((c = getc(refsfound)) != EOF) {
|
||||
putc(c, file);
|
||||
}
|
||||
seekline(topline);
|
||||
mypclose(file);
|
||||
}
|
||||
if (commandc == '^') {
|
||||
if (readrefs(temp2) == NO) {
|
||||
postmsg("Ignoring empty output of ^ command");
|
||||
}
|
||||
}
|
||||
askforreturn();
|
||||
entercurses();
|
||||
break;
|
||||
#if defined(KEY_RESIZE) && !defined(__DJGPP__)
|
||||
case KEY_RESIZE:
|
||||
/* XXX: fill in*/
|
||||
break;
|
||||
#endif
|
||||
case ctrl('L'): /* redraw screen */
|
||||
#ifdef KEY_CLEAR
|
||||
case KEY_CLEAR:
|
||||
#endif
|
||||
clearmsg2();
|
||||
clearok(curscr, TRUE);
|
||||
wrefresh(curscr);
|
||||
drawscrollbar(topline, bottomline);
|
||||
return(NO);
|
||||
|
||||
case '!': /* shell escape */
|
||||
execute(shell, shell, NULL);
|
||||
seekline(topline);
|
||||
break;
|
||||
|
||||
case '?': /* help */
|
||||
clear();
|
||||
help();
|
||||
clear();
|
||||
seekline(topline);
|
||||
break;
|
||||
|
||||
case ctrl('E'): /* edit all lines */
|
||||
editall();
|
||||
break;
|
||||
|
||||
case ctrl('A'): /* HBB 20050428: added alt. keymapping */
|
||||
case ctrl('Y'): /* repeat last pattern */
|
||||
if (*Pattern != '\0') {
|
||||
addstr(Pattern);
|
||||
goto repeat;
|
||||
}
|
||||
break;
|
||||
|
||||
case ctrl('B'): /* cmd history back */
|
||||
case ctrl('F'): /* cmd history fwd */
|
||||
if (selecting) {
|
||||
selecting = 0;
|
||||
}
|
||||
|
||||
curritem = currentcmd();
|
||||
item = (commandc == ctrl('F')) ? nextcmd() : prevcmd();
|
||||
clearmsg2();
|
||||
if (curritem == item) { /* inform user that we're at history end */
|
||||
postmsg2("End of input field and search pattern history");
|
||||
}
|
||||
if (item) {
|
||||
field = item->field;
|
||||
setfield();
|
||||
atfield();
|
||||
addstr(item->text);
|
||||
strcpy(Pattern, item->text);
|
||||
switch (c = mygetch()) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
goto repeat;
|
||||
case ctrl('F'):
|
||||
case ctrl('B'):
|
||||
myungetch(c);
|
||||
atfield();
|
||||
clrtoeol(); /* clear current field */
|
||||
break;
|
||||
default:
|
||||
myungetch(c);
|
||||
if (mygetline(Pattern, newpat, COLS - fldcolumn - 1, '\0', caseless )) {
|
||||
strcpy (Pattern, newpat);
|
||||
resetcmd();
|
||||
}
|
||||
goto repeat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(NO);
|
||||
|
||||
case '\\': /* next character is not a command */
|
||||
addch('\\'); /* display the quote character */
|
||||
|
||||
/* get a character from the terminal */
|
||||
if ((commandc = mygetch()) == EOF) {
|
||||
return(NO); /* quit */
|
||||
}
|
||||
addstr("\b \b"); /* erase the quote character */
|
||||
goto ispat;
|
||||
|
||||
case '.':
|
||||
postmsg("The . command has been replaced by ^Y");
|
||||
atfield(); /* move back to the input field */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (selecting && !mouse) {
|
||||
char *c;
|
||||
|
||||
if ((c = strchr(dispchars, commandc)))
|
||||
editref(c - dispchars);
|
||||
|
||||
/* if this is the start of a pattern */
|
||||
} else if (isprint(commandc)) {
|
||||
ispat:
|
||||
if (mygetline("", newpat, COLS - fldcolumn - 1,
|
||||
commandc, caseless) > 0) {
|
||||
strcpy(Pattern, newpat);
|
||||
resetcmd(); /* reset command history */
|
||||
repeat:
|
||||
addcmd(field, Pattern); /* add to command history */
|
||||
if (field == CHANGE) {
|
||||
/* prompt for the new text */
|
||||
move(PRLINE, 0);
|
||||
addstr(toprompt);
|
||||
mygetline("", newpat,
|
||||
COLS - sizeof(toprompt),
|
||||
'\0', NO);
|
||||
}
|
||||
/* search for the pattern */
|
||||
if (search() == YES) {
|
||||
curdispline = 0;
|
||||
++selecting;
|
||||
|
||||
switch (field) {
|
||||
case DEFINITION:
|
||||
case FILENAME:
|
||||
if (totallines > 1) {
|
||||
break;
|
||||
}
|
||||
topline = 1;
|
||||
editref(0);
|
||||
break;
|
||||
case CHANGE:
|
||||
return(changestring());
|
||||
}
|
||||
|
||||
} else if (field == FILENAME &&
|
||||
access(newpat, READ) == 0) {
|
||||
/* try to edit the file anyway */
|
||||
edit(newpat, "1");
|
||||
}
|
||||
} else { /* no pattern--the input was erased */
|
||||
return(NO);
|
||||
}
|
||||
} else { /* control character */
|
||||
return(NO);
|
||||
}
|
||||
} /* switch(commandc) */
|
||||
return(YES);
|
||||
}
|
||||
|
||||
/* clear the prompt line */
|
||||
|
||||
static void
|
||||
clearprompt(void)
|
||||
{
|
||||
move(PRLINE, 0);
|
||||
clrtoeol();
|
||||
}
|
||||
|
||||
/* read references from a file */
|
||||
|
||||
BOOL
|
||||
readrefs(char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
int c;
|
||||
|
||||
if ((file = myfopen(filename, "rb")) == NULL) {
|
||||
cannotopen(filename);
|
||||
return(NO);
|
||||
}
|
||||
if ((c = getc(file)) == EOF) { /* if file is empty */
|
||||
fclose(file);
|
||||
return(NO);
|
||||
}
|
||||
totallines = 0;
|
||||
disprefs = 0;
|
||||
nextline = 1;
|
||||
if (writerefsfound() == YES) {
|
||||
putc(c, refsfound);
|
||||
while ((c = getc(file)) != EOF) {
|
||||
putc(c, refsfound);
|
||||
}
|
||||
fclose(file);
|
||||
fclose(refsfound);
|
||||
if ( (refsfound = myfopen(temp1, "rb")) == NULL) {
|
||||
cannotopen(temp1);
|
||||
return(NO);
|
||||
}
|
||||
countrefs();
|
||||
} else
|
||||
fclose(file);
|
||||
return(YES);
|
||||
}
|
||||
|
||||
/* change one text string to another */
|
||||
|
||||
static BOOL
|
||||
changestring(void)
|
||||
{
|
||||
char newfile[PATHLEN + 1]; /* new file name */
|
||||
char oldfile[PATHLEN + 1]; /* old file name */
|
||||
char linenum[NUMLEN + 1]; /* file line number */
|
||||
char msg[MSGLEN + 1]; /* message */
|
||||
FILE *script; /* shell script file */
|
||||
BOOL anymarked = NO; /* any line marked */
|
||||
MOUSE *p; /* mouse data */
|
||||
int c;
|
||||
unsigned int i;
|
||||
char *s;
|
||||
|
||||
/* open the temporary file */
|
||||
if ((script = myfopen(temp2, "w")) == NULL) {
|
||||
cannotopen(temp2);
|
||||
return(NO);
|
||||
}
|
||||
/* create the line change indicators */
|
||||
change = calloc(totallines, sizeof(*change));
|
||||
changing = YES;
|
||||
mousemenu();
|
||||
|
||||
/* until the quit command is entered */
|
||||
for (;;) {
|
||||
/* display the current page of lines */
|
||||
display();
|
||||
same:
|
||||
atchange();
|
||||
|
||||
/* get a character from the terminal */
|
||||
if ((c = mygetch()) == EOF || c == ctrl('D')) {
|
||||
break; /* change lines */
|
||||
}
|
||||
if (c == ctrl('Z')) {
|
||||
#ifdef SIGTSTP
|
||||
kill(0, SIGTSTP);
|
||||
goto same;
|
||||
#else
|
||||
break; /* change lines */
|
||||
#endif
|
||||
}
|
||||
/* see if the input character is a command */
|
||||
switch (c) {
|
||||
case ' ': /* display next page */
|
||||
case '+':
|
||||
case ctrl('V'):
|
||||
#ifdef KEY_NPAGE
|
||||
case KEY_NPAGE:
|
||||
#endif
|
||||
case '-': /* display previous page */
|
||||
#ifdef KEY_PPAGE
|
||||
case KEY_PPAGE:
|
||||
#endif
|
||||
case '!': /* shell escape */
|
||||
case '?': /* help */
|
||||
command(c);
|
||||
break;
|
||||
|
||||
case ctrl('L'): /* redraw screen */
|
||||
#ifdef KEY_CLEAR
|
||||
case KEY_CLEAR:
|
||||
#endif
|
||||
command(c);
|
||||
goto same;
|
||||
|
||||
case ESC: /* don't change lines */
|
||||
#if UNIXPC
|
||||
if((p = getmouseaction(DUMMYCHAR)) == NULL) {
|
||||
goto nochange; /* unknown escape sequence */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case ctrl('G'):
|
||||
goto nochange;
|
||||
|
||||
case '*': /* mark/unmark all displayed lines */
|
||||
for (i = 0; topline + i < nextline; ++i) {
|
||||
mark(i);
|
||||
}
|
||||
goto same;
|
||||
|
||||
case ctrl('A'): /* mark/unmark all lines */
|
||||
for (i = 0; i < totallines; ++i) {
|
||||
if (change[i] == NO) {
|
||||
change[i] = YES;
|
||||
} else {
|
||||
change[i] = NO;
|
||||
}
|
||||
}
|
||||
/* show that all have been marked */
|
||||
seekline(totallines);
|
||||
break;
|
||||
|
||||
case ctrl('X'): /* mouse selection */
|
||||
if ((p = getmouseaction(DUMMYCHAR)) == NULL) {
|
||||
goto same; /* unknown control sequence */
|
||||
}
|
||||
/* if the button number is a scrollbar tag */
|
||||
if (p->button == '0') {
|
||||
scrollbar(p);
|
||||
break;
|
||||
}
|
||||
/* find the selected line */
|
||||
/* note: the selection is forced into range */
|
||||
for (i = disprefs - 1; i > 0; --i) {
|
||||
if (p->y1 >= displine[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
mark(i);
|
||||
goto same;
|
||||
|
||||
default:
|
||||
{
|
||||
/* if a line was selected */
|
||||
char *cc;
|
||||
|
||||
if ((cc = strchr(dispchars, c)))
|
||||
mark(cc - dispchars);
|
||||
|
||||
goto same;
|
||||
} /* default case */
|
||||
} /* switch(change code character) */
|
||||
} /* for(ever) */
|
||||
|
||||
/* for each line containing the old text */
|
||||
fprintf(script, "ed - <<\\!\n");
|
||||
*oldfile = '\0';
|
||||
seekline(1);
|
||||
for (i = 0;
|
||||
fscanf(refsfound, "%" PATHLEN_STR "s%*s%" NUMLEN_STR "s%*[^\n]", newfile, linenum) == 2;
|
||||
++i) {
|
||||
/* see if the line is to be changed */
|
||||
if (change[i] == YES) {
|
||||
anymarked = YES;
|
||||
|
||||
/* if this is a new file */
|
||||
if (strcmp(newfile, oldfile) != 0) {
|
||||
|
||||
/* make sure it can be changed */
|
||||
if (access(newfile, WRITE) != 0) {
|
||||
snprintf(msg, sizeof(msg), "Cannot write to file %s", newfile);
|
||||
postmsg(msg);
|
||||
anymarked = NO;
|
||||
break;
|
||||
}
|
||||
/* if there was an old file */
|
||||
if (*oldfile != '\0') {
|
||||
fprintf(script, "w\n"); /* save it */
|
||||
}
|
||||
/* edit the new file */
|
||||
strcpy(oldfile, newfile);
|
||||
fprintf(script, "e %s\n", oldfile);
|
||||
}
|
||||
/* output substitute command */
|
||||
fprintf(script, "%ss/", linenum); /* change */
|
||||
for (s = Pattern; *s != '\0'; ++s) {
|
||||
/* old text */
|
||||
if (strchr("/\\[.^*", *s) != NULL) {
|
||||
putc('\\', script);
|
||||
}
|
||||
if (caseless == YES && isalpha((unsigned char)*s)) {
|
||||
putc('[', script);
|
||||
if(islower((unsigned char)*s)) {
|
||||
putc(toupper((unsigned char)*s), script);
|
||||
putc(*s, script);
|
||||
} else {
|
||||
putc(*s, script);
|
||||
putc(tolower((unsigned char)*s), script);
|
||||
}
|
||||
putc(']', script);
|
||||
} else
|
||||
putc(*s, script);
|
||||
}
|
||||
putc('/', script); /* to */
|
||||
for (s = newpat; *s != '\0'; ++s) { /* new text */
|
||||
if (strchr("/\\&", *s) != NULL) {
|
||||
putc('\\', script);
|
||||
}
|
||||
putc(*s, script);
|
||||
}
|
||||
fprintf(script, "/gp\n"); /* and print */
|
||||
}
|
||||
}
|
||||
fprintf(script, "w\nq\n!\n"); /* write and quit */
|
||||
fclose(script);
|
||||
|
||||
/* if any line was marked */
|
||||
if (anymarked == YES) {
|
||||
|
||||
/* edit the files */
|
||||
clearprompt();
|
||||
refresh();
|
||||
fprintf(stderr, "Changed lines:\n\r");
|
||||
execute("sh", "sh", temp2, NULL);
|
||||
askforreturn();
|
||||
seekline(1);
|
||||
} else {
|
||||
nochange:
|
||||
clearprompt();
|
||||
}
|
||||
changing = NO;
|
||||
mousemenu();
|
||||
fclose(script);
|
||||
free(change);
|
||||
return(anymarked);
|
||||
}
|
||||
|
||||
|
||||
/* mark/unmark this displayed line to be changed */
|
||||
static void
|
||||
mark(unsigned int i)
|
||||
{
|
||||
unsigned int j;
|
||||
|
||||
j = i + topline - 1;
|
||||
if (j < totallines) {
|
||||
move(displine[i], 1);
|
||||
|
||||
if (change[j] == NO) {
|
||||
change[j] = YES;
|
||||
addch('>');
|
||||
} else {
|
||||
change[j] = NO;
|
||||
addch(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* scrollbar actions */
|
||||
static void
|
||||
scrollbar(MOUSE *p)
|
||||
{
|
||||
/* reposition list if it makes sense */
|
||||
if (totallines == 0) {
|
||||
return;
|
||||
}
|
||||
switch (p->percent) {
|
||||
|
||||
case 101: /* scroll down one page */
|
||||
if (nextline + mdisprefs > totallines) {
|
||||
nextline = totallines - mdisprefs + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 102: /* scroll up one page */
|
||||
nextline = topline - mdisprefs;
|
||||
if (nextline < 1) {
|
||||
nextline = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 103: /* scroll down one line */
|
||||
nextline = topline + 1;
|
||||
break;
|
||||
|
||||
case 104: /* scroll up one line */
|
||||
if (topline > 1) {
|
||||
nextline = topline - 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
nextline = p->percent * totallines / 100;
|
||||
}
|
||||
seekline(nextline);
|
||||
}
|
||||
|
||||
|
||||
/* count the references found */
|
||||
void
|
||||
countrefs(void)
|
||||
{
|
||||
char *subsystem; /* OGS subsystem name */
|
||||
char *book; /* OGS book name */
|
||||
char file[PATHLEN + 1]; /* file name */
|
||||
char function[PATLEN + 1]; /* function name */
|
||||
char linenum[NUMLEN + 1]; /* line number */
|
||||
int i;
|
||||
|
||||
/* count the references found and find the length of the file,
|
||||
function, and line number display fields */
|
||||
subsystemlen = 9; /* strlen("Subsystem") */
|
||||
booklen = 4; /* strlen("Book") */
|
||||
filelen = 4; /* strlen("File") */
|
||||
fcnlen = 8; /* strlen("Function") */
|
||||
numlen = 0;
|
||||
/* HBB NOTE 2012-04-07: it may look like we shouldn't assing tempstring here,
|
||||
* since it's not used. But it has to be assigned just so the return value
|
||||
* of fscanf will actually reach 4. */
|
||||
while (EOF != (i = fscanf(refsfound,
|
||||
"%" PATHLEN_STR "s%" PATLEN_STR "s%" NUMLEN_STR "s %" TEMPSTRING_LEN_STR "[^\n]",
|
||||
file, function, linenum, tempstring
|
||||
)
|
||||
)
|
||||
) {
|
||||
if ( (i != 4)
|
||||
|| !isgraph((unsigned char) *file)
|
||||
|| !isgraph((unsigned char) *function)
|
||||
|| !isdigit((unsigned char) *linenum)
|
||||
) {
|
||||
postmsg("File does not have expected format");
|
||||
totallines = 0;
|
||||
disprefs = 0;
|
||||
return;
|
||||
}
|
||||
if ((i = strlen(pathcomponents(file, dispcomponents))) > filelen) {
|
||||
filelen = i;
|
||||
}
|
||||
if (ogs == YES) {
|
||||
ogsnames(file, &subsystem, &book);
|
||||
if ((i = strlen(subsystem)) > subsystemlen) {
|
||||
subsystemlen = i;
|
||||
}
|
||||
if ((i = strlen(book)) > booklen) {
|
||||
booklen = i;
|
||||
}
|
||||
}
|
||||
if ((i = strlen(function)) > fcnlen) {
|
||||
fcnlen = i;
|
||||
}
|
||||
if ((i = strlen(linenum)) > numlen) {
|
||||
numlen = i;
|
||||
}
|
||||
++totallines;
|
||||
}
|
||||
rewind(refsfound);
|
||||
|
||||
/* restrict the width of displayed columns */
|
||||
/* HBB FIXME 20060419: magic number alert! */
|
||||
i = (COLS - 5) / 3;
|
||||
if (ogs == YES) {
|
||||
i = (COLS - 7) / 5;
|
||||
}
|
||||
if (filelen > i && i > 4) {
|
||||
filelen = i;
|
||||
}
|
||||
if (subsystemlen > i && i > 9) {
|
||||
subsystemlen = i;
|
||||
}
|
||||
if (booklen > i && i > 4) {
|
||||
booklen = i;
|
||||
}
|
||||
if (fcnlen > i && i > 8) {
|
||||
fcnlen = i;
|
||||
}
|
||||
}
|
211
src/compath.c
Normal file
211
src/compath.c
Normal file
@ -0,0 +1,211 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/*
|
||||
* compath(pathname)
|
||||
*
|
||||
* This compresses pathnames. All strings of multiple slashes are
|
||||
* changed to a single slash. All occurrences of "./" are removed.
|
||||
* Whenever possible, strings of "/.." are removed together with
|
||||
* the directory names that they follow.
|
||||
*
|
||||
* WARNING: since pathname is altered by this function, it should
|
||||
* be located in a temporary buffer. This avoids the problem
|
||||
* of accidently changing strings obtained from makefiles
|
||||
* and stored in global structures.
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
char *
|
||||
compath(char *pathname) /*FDEF*/
|
||||
{
|
||||
char *nextchar;
|
||||
char *lastchar;
|
||||
char *sofar;
|
||||
char *pnend;
|
||||
|
||||
int pnlen;
|
||||
|
||||
/*
|
||||
* do not change the path if it has no "/"
|
||||
*/
|
||||
|
||||
if (strchr(pathname, '/') == NULL)
|
||||
return(pathname);
|
||||
|
||||
/*
|
||||
* find all strings consisting of more than one '/'
|
||||
*/
|
||||
|
||||
for (lastchar = pathname + 1; *lastchar != '\0'; lastchar++)
|
||||
if ((*lastchar == '/') && (*(lastchar - 1) == '/'))
|
||||
{
|
||||
|
||||
/*
|
||||
* find the character after the last slash
|
||||
*/
|
||||
|
||||
nextchar = lastchar;
|
||||
while (*++lastchar == '/')
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* eliminate the extra slashes by copying
|
||||
* everything after the slashes over the slashes
|
||||
*/
|
||||
|
||||
sofar = nextchar;
|
||||
while ((*nextchar++ = *lastchar++) != '\0')
|
||||
;
|
||||
lastchar = sofar;
|
||||
}
|
||||
|
||||
/*
|
||||
* find all strings of "./"
|
||||
*/
|
||||
|
||||
for (lastchar = pathname + 1; *lastchar != '\0'; lastchar++)
|
||||
if ((*lastchar == '/') && (*(lastchar - 1) == '.') &&
|
||||
((lastchar - 1 == pathname) || (*(lastchar - 2) == '/')))
|
||||
{
|
||||
|
||||
/*
|
||||
* copy everything after the "./" over the "./"
|
||||
*/
|
||||
|
||||
nextchar = lastchar - 1;
|
||||
sofar = nextchar;
|
||||
while ((*nextchar++ = *++lastchar) != '\0')
|
||||
;
|
||||
lastchar = sofar;
|
||||
}
|
||||
|
||||
/*
|
||||
* find each occurrence of "/.."
|
||||
*/
|
||||
|
||||
for (lastchar = pathname + 1; *lastchar != '\0'; lastchar++)
|
||||
if ((lastchar != pathname) && (*lastchar == '/') &&
|
||||
(*(lastchar + 1) == '.') && (*(lastchar + 2) == '.') &&
|
||||
((*(lastchar + 3) == '/') || (*(lastchar + 3) == '\0')))
|
||||
{
|
||||
|
||||
/*
|
||||
* find the directory name preceding the "/.."
|
||||
*/
|
||||
|
||||
nextchar = lastchar - 1;
|
||||
while ((nextchar != pathname) &&
|
||||
(*(nextchar - 1) != '/'))
|
||||
--nextchar;
|
||||
|
||||
/*
|
||||
* make sure the preceding directory's name
|
||||
* is not "." or ".."
|
||||
*/
|
||||
|
||||
if ((*nextchar == '.') &&
|
||||
((*(nextchar + 1) == '/') ||
|
||||
((*(nextchar + 1) == '.') && (*(nextchar + 2) == '/'))))
|
||||
/* EMPTY */;
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* prepare to eliminate either
|
||||
* "dir_name/../" or "dir_name/.."
|
||||
*/
|
||||
|
||||
if (*(lastchar + 3) == '/')
|
||||
lastchar += 4;
|
||||
else
|
||||
lastchar += 3;
|
||||
|
||||
/*
|
||||
* copy everything after the "/.." to
|
||||
* before the preceding directory name
|
||||
*/
|
||||
|
||||
sofar = nextchar - 1;
|
||||
while ((*nextchar++ = *lastchar++) != '\0');
|
||||
|
||||
lastchar = sofar;
|
||||
|
||||
/*
|
||||
* if the character before what was taken
|
||||
* out is '/', set up to check if the
|
||||
* slash is part of "/.."
|
||||
*/
|
||||
|
||||
if ((sofar + 1 != pathname) && (*sofar == '/'))
|
||||
--lastchar;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if the string is more than a character long and ends
|
||||
* in '/', eliminate the '/'.
|
||||
*/
|
||||
|
||||
pnlen = strlen(pathname);
|
||||
pnend = strchr(pathname, '\0') - 1;
|
||||
|
||||
if ((pnlen > 1) && (*pnend == '/'))
|
||||
{
|
||||
*pnend-- = '\0';
|
||||
pnlen--;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the string has more than two characters and ends in
|
||||
* "/.", remove the "/.".
|
||||
*/
|
||||
|
||||
if ((pnlen > 2) && (*(pnend - 1) == '/') && (*pnend == '.'))
|
||||
*--pnend = '\0';
|
||||
|
||||
/*
|
||||
* if all characters were deleted, return ".";
|
||||
* otherwise return pathname
|
||||
*/
|
||||
|
||||
if (*pathname == '\0')
|
||||
(void) strcpy(pathname, ".");
|
||||
|
||||
return(pathname);
|
||||
}
|
133
src/constants.h
Normal file
133
src/constants.h
Normal file
@ -0,0 +1,133 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* preprocessor macro and constant definitions
|
||||
*/
|
||||
|
||||
#ifndef CSCOPE_CONSTANTS_H
|
||||
#define CSCOPE_CONSTANTS_H
|
||||
|
||||
#define ctrl(x) (x & 037) /* control character macro */
|
||||
|
||||
/* fast string equality tests (avoids most strcmp() calls) */
|
||||
#define strequal(s1, s2) (*(s1) == *(s2) && strcmp(s1, s2) == 0)
|
||||
#define strnotequal(s1, s2) (*(s1) != *(s2) || strcmp(s1, s2) != 0)
|
||||
|
||||
/* set the mark character for searching the cross-reference file */
|
||||
#define setmark(c) (blockmark = c, block[blocklen] = blockmark)
|
||||
|
||||
/* get the next character in the cross-reference */
|
||||
/* note that blockp is assumed not to be null */
|
||||
#define getrefchar() (*(++blockp + 1) != '\0' ? *blockp : \
|
||||
(read_block() != NULL ? *blockp : '\0'))
|
||||
|
||||
/* skip the next character in the cross-reference */
|
||||
/* note that blockp is assumed not to be null and that
|
||||
this macro will always be in a statement by itself */
|
||||
#define skiprefchar() if (*(++blockp + 1) == '\0') (void) read_block()
|
||||
|
||||
#define ESC '\033' /* escape character */
|
||||
#define DEL '\177' /* delete character */
|
||||
#define DUMMYCHAR ' ' /* use space as a dummy character */
|
||||
#define MSGLEN ((PATLEN) + 80) /* displayed message length */
|
||||
#define NUMLEN 10 /* line number length */
|
||||
#define PATHLEN 250 /* file pathname length */
|
||||
#define PATLEN 250 /* symbol pattern length */
|
||||
#define TEMPSTRING_LEN 8191 /* max strlen() of the global temp string */
|
||||
#define REFFILE "cscope.out" /* cross-reference output file */
|
||||
#define NAMEFILE "cscope.files" /* default list-of-files file */
|
||||
#define INVNAME "cscope.in.out" /* inverted index to the database */
|
||||
#define INVPOST "cscope.po.out" /* inverted index postings */
|
||||
#define INVNAME2 "cscope.out.in"/* follows correct naming convention */
|
||||
#define INVPOST2 "cscope.out.po"/* follows correct naming convention */
|
||||
|
||||
#define STMTMAX 10000 /* maximum source statement length */
|
||||
|
||||
#define STR2(x) #x
|
||||
#define STRINGIZE(x) STR2(x)
|
||||
#define PATLEN_STR STRINGIZE(PATLEN)
|
||||
#define PATHLEN_STR STRINGIZE(PATHLEN)
|
||||
#define NUMLEN_STR STRINGIZE(NUMLEN)
|
||||
#define TEMPSTRING_LEN_STR STRINGIZE(TEMPSTRING_LEN)
|
||||
|
||||
/* screen lines */
|
||||
#define FLDLINE (LINES - FIELDS - 1 - 1) /* first input field line */
|
||||
#define MSGLINE 0 /* message line */
|
||||
#define PRLINE (LINES - 1) /* input prompt line */
|
||||
#define REFLINE 3 /* first displayed reference line */
|
||||
|
||||
/* input fields (value matches field order on screen) */
|
||||
#define SYMBOL 0
|
||||
#define DEFINITION 1
|
||||
#define CALLEDBY 2
|
||||
#define CALLING 3
|
||||
#define STRING 4
|
||||
#define CHANGE 5
|
||||
#define REGEXP 6
|
||||
#define FILENAME 7
|
||||
#define INCLUDES 8
|
||||
#define FIELDS 10
|
||||
|
||||
#if (BSD || V9) && !__NetBSD__ && !__FreeBSD__ && !__APPLE__
|
||||
# define TERMINFO 0 /* no terminfo curses */
|
||||
#else
|
||||
# define TERMINFO 1
|
||||
#endif
|
||||
|
||||
|
||||
#if !TERMINFO
|
||||
# ifndef KEY_BREAK
|
||||
# define KEY_BREAK 0400 /* easier to define than to add #if around the use */
|
||||
# endif
|
||||
# ifndef KEY_ENTER
|
||||
# define KEY_ENTER 0401
|
||||
# endif
|
||||
# ifndef KEY_BACKSPACE
|
||||
# define KEY_BACKSPACE 0402
|
||||
# endif
|
||||
|
||||
# if !sun
|
||||
# define cbreak() crmode() /* name change */
|
||||
# endif
|
||||
|
||||
# if UNIXPC
|
||||
# define erasechar() (_tty.c_cc[VERASE]) /* equivalent */
|
||||
# define killchar() (_tty.c_cc[VKILL]) /* equivalent */
|
||||
# else
|
||||
# define erasechar() (_tty.sg_erase) /* equivalent */
|
||||
# define killchar() (_tty.sg_kill) /* equivalent */
|
||||
# endif /* if UNIXPC */
|
||||
#endif /* if !TERMINFO */
|
||||
|
||||
#endif /* CSCOPE_CONSTANTS_H */
|
492
src/crossref.c
Normal file
492
src/crossref.c
Normal file
@ -0,0 +1,492 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* build cross-reference file
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "build.h"
|
||||
#include "scanner.h"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* convert long to a string in base BASE notation */
|
||||
#define ltobase(value) \
|
||||
do { \
|
||||
n = (value); \
|
||||
s = buf + (sizeof(buf) - 1); \
|
||||
*s = '\0'; \
|
||||
digits = 1; \
|
||||
while (n >= BASE) { \
|
||||
++digits; \
|
||||
i = n; \
|
||||
n /= BASE; \
|
||||
*--s = i - n * BASE + '!'; \
|
||||
} \
|
||||
*--s = n + '!'; \
|
||||
} while (0)
|
||||
|
||||
#define SYMBOLINC 20 /* symbol list size increment */
|
||||
|
||||
long dboffset; /* new database offset */
|
||||
BOOL errorsfound; /* prompt before clearing messages */
|
||||
long lineoffset; /* source line database offset */
|
||||
long npostings; /* number of postings */
|
||||
int nsrcoffset; /* number of file name database offsets */
|
||||
long *srcoffset; /* source file name database offsets */
|
||||
unsigned long symbols; /* number of symbols */
|
||||
|
||||
static char *filename; /* file name for warning messages */
|
||||
static long fcnoffset; /* function name database offset */
|
||||
static long macrooffset; /* macro name database offset */
|
||||
static unsigned long msymbols = SYMBOLINC; /* maximum number of symbols */
|
||||
|
||||
struct symbol { /* symbol data */
|
||||
int type; /* type */
|
||||
unsigned int first; /* index of first character in text */
|
||||
unsigned int last; /* index of last+1 character in text */
|
||||
unsigned int length; /* symbol length */
|
||||
unsigned int fcn_level; /* function level of the symbol */
|
||||
};
|
||||
static struct symbol *symbol;
|
||||
|
||||
static void putcrossref(void);
|
||||
static void savesymbol(int token, int num);
|
||||
|
||||
void
|
||||
crossref(char *srcfile)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int length; /* symbol length */
|
||||
unsigned int entry_no; /* function level of the symbol */
|
||||
int token; /* current token */
|
||||
struct stat st;
|
||||
|
||||
if (! ((stat(srcfile, &st) == 0)
|
||||
&& S_ISREG(st.st_mode))) {
|
||||
cannotopen(srcfile);
|
||||
errorsfound = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
entry_no = 0;
|
||||
/* open the source file */
|
||||
if ((yyin = myfopen(srcfile, "r")) == NULL) {
|
||||
cannotopen(srcfile);
|
||||
errorsfound = YES;
|
||||
return;
|
||||
}
|
||||
filename = srcfile; /* save the file name for warning messages */
|
||||
putfilename(srcfile); /* output the file name */
|
||||
dbputc('\n');
|
||||
dbputc('\n');
|
||||
|
||||
/* read the source file */
|
||||
initscanner(srcfile);
|
||||
fcnoffset = macrooffset = 0;
|
||||
symbols = 0;
|
||||
if (symbol == NULL) {
|
||||
symbol = malloc(msymbols * sizeof(*symbol));
|
||||
}
|
||||
for (;;) {
|
||||
|
||||
/* get the next token */
|
||||
switch (token = yylex()) {
|
||||
default:
|
||||
/* if requested, truncate C symbols */
|
||||
length = last - first;
|
||||
if (trun_syms == YES && length > 8 &&
|
||||
token != INCLUDE && token != NEWFILE) {
|
||||
length = 8;
|
||||
last = first + 8;
|
||||
}
|
||||
/* see if the token has a symbol */
|
||||
if (length == 0) {
|
||||
savesymbol(token, entry_no);
|
||||
break;
|
||||
}
|
||||
/* update entry_no if see function entry */
|
||||
if (token == FCNDEF) {
|
||||
entry_no++;
|
||||
}
|
||||
/* see if the symbol is already in the list */
|
||||
for (i = 0; i < symbols; ++i) {
|
||||
if (length == symbol[i].length
|
||||
&& strncmp(my_yytext + first,
|
||||
my_yytext + symbol[i].first,
|
||||
length) == 0
|
||||
&& entry_no == symbol[i].fcn_level
|
||||
&& token == symbol[i].type
|
||||
) { /* could be a::a() */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == symbols) { /* if not already in list */
|
||||
savesymbol(token, entry_no);
|
||||
}
|
||||
break;
|
||||
|
||||
case NEWLINE: /* end of line containing symbols */
|
||||
entry_no = 0; /* reset entry_no for each line */
|
||||
#ifdef USING_LEX
|
||||
--yyleng; /* remove the newline */
|
||||
#endif
|
||||
putcrossref(); /* output the symbols and source line */
|
||||
lineno = myylineno; /* save the symbol line number */
|
||||
#ifndef USING_LEX
|
||||
/* HBB 20010425: replaced yyleng-- by this chunk: */
|
||||
if (my_yytext)
|
||||
*my_yytext = '\0';
|
||||
my_yyleng = 0;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LEXERR: /* Lexer error, abort further parsing of this file */
|
||||
case LEXEOF: /* end of file; last line may not have \n */
|
||||
|
||||
/* if there were symbols, output them and the source line */
|
||||
if (symbols > 0) {
|
||||
putcrossref();
|
||||
}
|
||||
(void) fclose(yyin); /* close the source file */
|
||||
|
||||
/* output the leading tab expected by the next call */
|
||||
dbputc('\t');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* save the symbol in the list */
|
||||
|
||||
static void
|
||||
savesymbol(int token, int num)
|
||||
{
|
||||
/* make sure there is room for the symbol */
|
||||
if (symbols == msymbols) {
|
||||
msymbols += SYMBOLINC;
|
||||
symbol = realloc(symbol, msymbols * sizeof(*symbol));
|
||||
}
|
||||
/* save the symbol */
|
||||
symbol[symbols].type = token;
|
||||
symbol[symbols].first = first;
|
||||
symbol[symbols].last = last;
|
||||
symbol[symbols].length = last - first;
|
||||
symbol[symbols].fcn_level = num;
|
||||
++symbols;
|
||||
}
|
||||
|
||||
/* output the file name */
|
||||
|
||||
void
|
||||
putfilename(char *srcfile)
|
||||
{
|
||||
/* check for file system out of space */
|
||||
/* note: dbputc is not used to avoid lint complaint */
|
||||
if (putc(NEWFILE, newrefs) == EOF) {
|
||||
cannotwrite(newreffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
++dboffset;
|
||||
if (invertedindex == YES) {
|
||||
srcoffset[nsrcoffset++] = dboffset;
|
||||
}
|
||||
dbfputs(srcfile);
|
||||
fcnoffset = macrooffset = 0;
|
||||
}
|
||||
|
||||
/* output the symbols and source line */
|
||||
|
||||
static void
|
||||
putcrossref(void)
|
||||
{
|
||||
unsigned int i, j;
|
||||
unsigned char c;
|
||||
BOOL blank; /* blank indicator */
|
||||
unsigned int symput = 0; /* symbols output */
|
||||
int type;
|
||||
|
||||
/* output the source line */
|
||||
lineoffset = dboffset;
|
||||
dboffset += fprintf(newrefs, "%d ", lineno);
|
||||
#ifdef PRINTF_RETVAL_BROKEN
|
||||
dboffset = ftell(newrefs); /* fprintf doesn't return chars written */
|
||||
#endif
|
||||
|
||||
/* HBB 20010425: added this line: */
|
||||
my_yytext[my_yyleng] = '\0';
|
||||
|
||||
blank = NO;
|
||||
for (i = 0; i < my_yyleng; ++i) {
|
||||
|
||||
/* change a tab to a blank and compress blanks */
|
||||
if ((c = my_yytext[i]) == ' ' || c == '\t') {
|
||||
blank = YES;
|
||||
} else if (symput < symbols && i == symbol[symput].first) {
|
||||
/* look for the start of a symbol */
|
||||
|
||||
/* check for compressed blanks */
|
||||
if (blank == YES) {
|
||||
blank = NO;
|
||||
dbputc(' ');
|
||||
}
|
||||
dbputc('\n'); /* symbols start on a new line */
|
||||
|
||||
/* output any symbol type */
|
||||
if ((type = symbol[symput].type) != IDENT) {
|
||||
dbputc('\t');
|
||||
dbputc(type);
|
||||
} else {
|
||||
type = ' ';
|
||||
}
|
||||
/* output the symbol */
|
||||
j = symbol[symput].last;
|
||||
c = my_yytext[j];
|
||||
my_yytext[j] = '\0';
|
||||
if (invertedindex == YES) {
|
||||
putposting(my_yytext + i, type);
|
||||
}
|
||||
writestring(my_yytext + i);
|
||||
dbputc('\n');
|
||||
my_yytext[j] = c;
|
||||
i = j - 1;
|
||||
++symput;
|
||||
} else {
|
||||
/* HBB: try to save some time by early-out handling of
|
||||
* non-compressed mode */
|
||||
if (compress == NO) {
|
||||
if (blank == YES) {
|
||||
dbputc(' ');
|
||||
blank = NO;
|
||||
}
|
||||
j = i + strcspn(my_yytext+i, "\t ");
|
||||
if (symput < symbols
|
||||
&& j >= symbol[symput].first)
|
||||
j = symbol[symput].first;
|
||||
c = my_yytext[j];
|
||||
my_yytext[j] = '\0';
|
||||
writestring(my_yytext + i);
|
||||
my_yytext[j] = c;
|
||||
i = j - 1;
|
||||
/* finished this 'i', continue with the blank */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for compressed blanks */
|
||||
if (blank == YES) {
|
||||
if (dicode2[c]) {
|
||||
c = DICODE_COMPRESS(' ', c);
|
||||
} else {
|
||||
dbputc(' ');
|
||||
}
|
||||
} else if (IS_A_DICODE(c, my_yytext[i + 1])
|
||||
&& symput < symbols
|
||||
&& i + 1 != symbol[symput].first) {
|
||||
/* compress digraphs */
|
||||
c = DICODE_COMPRESS(c, my_yytext[i + 1]);
|
||||
++i;
|
||||
}
|
||||
dbputc((int) c);
|
||||
blank = NO;
|
||||
|
||||
/* skip compressed characters */
|
||||
if (c < ' ') {
|
||||
++i;
|
||||
|
||||
/* skip blanks before a preprocesor keyword */
|
||||
/* note: don't use isspace() because \f and \v
|
||||
are used for keywords */
|
||||
while ((j = my_yytext[i]) == ' ' || j == '\t') {
|
||||
++i;
|
||||
}
|
||||
/* skip the rest of the keyword */
|
||||
while (isalpha((unsigned char)my_yytext[i])) {
|
||||
++i;
|
||||
}
|
||||
/* skip space after certain keywords */
|
||||
if (keyword[c].delim != '\0') {
|
||||
while ((j = my_yytext[i]) == ' ' || j == '\t') {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
/* skip a '(' after certain keywords */
|
||||
if (keyword[c].delim == '('
|
||||
&& my_yytext[i] == '(') {
|
||||
++i;
|
||||
}
|
||||
--i; /* compensate for ++i in for() */
|
||||
} /* if compressed char */
|
||||
} /* else: not a symbol */
|
||||
} /* for(i) */
|
||||
|
||||
/* ignore trailing blanks */
|
||||
dbputc('\n');
|
||||
dbputc('\n');
|
||||
|
||||
/* output any #define end marker */
|
||||
/* note: must not be part of #define so putsource() doesn't discard it
|
||||
so findcalledbysub() can find it and return */
|
||||
if (symput < symbols && symbol[symput].type == DEFINEEND) {
|
||||
dbputc('\t');
|
||||
dbputc(DEFINEEND);
|
||||
dbputc('\n');
|
||||
dbputc('\n'); /* mark beginning of next source line */
|
||||
macrooffset = 0;
|
||||
}
|
||||
symbols = 0;
|
||||
}
|
||||
|
||||
/* HBB 20000421: new function, for avoiding memory leaks */
|
||||
/* free the cross reference symbol table */
|
||||
void
|
||||
freecrossref()
|
||||
{
|
||||
if (symbol)
|
||||
free(symbol);
|
||||
symbol = NULL;
|
||||
symbols = 0;
|
||||
}
|
||||
|
||||
/* output the inverted index posting */
|
||||
|
||||
void
|
||||
putposting(char *term, int type)
|
||||
{
|
||||
long i, n;
|
||||
char *s;
|
||||
int digits; /* digits output */
|
||||
long offset; /* function/macro database offset */
|
||||
char buf[11]; /* number buffer */
|
||||
|
||||
/* get the function or macro name offset */
|
||||
offset = fcnoffset;
|
||||
if (macrooffset != 0) {
|
||||
offset = macrooffset;
|
||||
}
|
||||
/* then update them to avoid negative relative name offset */
|
||||
switch (type) {
|
||||
case DEFINE:
|
||||
macrooffset = dboffset;
|
||||
break;
|
||||
case DEFINEEND:
|
||||
macrooffset = 0;
|
||||
return; /* null term */
|
||||
case FCNDEF:
|
||||
fcnoffset = dboffset;
|
||||
break;
|
||||
case FCNEND:
|
||||
fcnoffset = 0;
|
||||
return; /* null term */
|
||||
}
|
||||
/* ignore a null term caused by a enum/struct/union without a tag */
|
||||
if (*term == '\0') {
|
||||
return;
|
||||
}
|
||||
/* skip any #include secondary type char (< or ") */
|
||||
if (type == INCLUDE) {
|
||||
++term;
|
||||
}
|
||||
/* output the posting, which should be as small as possible to reduce
|
||||
the temp file size and sort time */
|
||||
(void) fputs(term, postings);
|
||||
(void) putc(' ', postings);
|
||||
|
||||
/* the line offset is padded so postings for the same term will sort
|
||||
in ascending line offset order to order the references as they
|
||||
appear withing a source file */
|
||||
ltobase(lineoffset);
|
||||
for (i = PRECISION - digits; i > 0; --i) {
|
||||
(void) putc('!', postings);
|
||||
}
|
||||
do {
|
||||
(void) putc(*s, postings);
|
||||
} while (*++s != '\0');
|
||||
|
||||
/* postings are also sorted by type */
|
||||
(void) putc(type, postings);
|
||||
|
||||
/* function or macro name offset */
|
||||
if (offset > 0) {
|
||||
(void) putc(' ', postings);
|
||||
ltobase(offset);
|
||||
do {
|
||||
(void) putc(*s, postings);
|
||||
} while (*++s != '\0');
|
||||
}
|
||||
if (putc('\n', postings) == EOF) {
|
||||
cannotwrite(temp1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
++npostings;
|
||||
}
|
||||
|
||||
/* put the string into the new database */
|
||||
|
||||
void
|
||||
writestring(char *s)
|
||||
{
|
||||
unsigned char c;
|
||||
int i;
|
||||
|
||||
if (compress == NO) {
|
||||
/* Save some I/O overhead by using puts() instead of putc(): */
|
||||
dbfputs(s);
|
||||
return;
|
||||
}
|
||||
/* compress digraphs */
|
||||
for (i = 0; (c = s[i]) != '\0'; ++i) {
|
||||
if (/* dicode1[c] && dicode2[(unsigned char) s[i + 1]] */
|
||||
IS_A_DICODE(c, s[i + 1])) {
|
||||
/* c = (0200 - 2) + dicode1[c] + dicode2[(unsigned char) s[i + 1]]; */
|
||||
c = DICODE_COMPRESS(c, s[i + 1]);
|
||||
++i;
|
||||
}
|
||||
dbputc(c);
|
||||
}
|
||||
}
|
||||
|
||||
/* print a warning message with the file name and line number */
|
||||
|
||||
void
|
||||
warning(char *text)
|
||||
{
|
||||
|
||||
(void) fprintf(stderr, "cscope: \"%s\", line %d: warning: %s\n", filename,
|
||||
myylineno, text);
|
||||
errorsfound = YES;
|
||||
}
|
747
src/dir.c
Normal file
747
src/dir.c
Normal file
@ -0,0 +1,747 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* directory searching functions
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "vp.h" /* vpdirs and vpndirs */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h> /* needed by stat.h and dirent.h */
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h> /* stat */
|
||||
#include <assert.h>
|
||||
|
||||
#define DIRSEPS " ,:" /* directory list separators */
|
||||
#define DIRINC 10 /* directory list size increment */
|
||||
#define HASHMOD 2003 /* must be a prime number */
|
||||
#define SRCINC HASHMOD /* source file list size increment */
|
||||
/* largest known database had 22049 files */
|
||||
|
||||
char currentdir[PATHLEN + 1];/* current directory */
|
||||
char **incdirs; /* #include directories */
|
||||
char **srcdirs; /* source directories */
|
||||
char **srcfiles; /* source files */
|
||||
unsigned long nincdirs; /* number of #include directories */
|
||||
unsigned long nsrcdirs; /* number of source directories */
|
||||
unsigned long nsrcfiles; /* number of source files */
|
||||
unsigned long msrcfiles = SRCINC; /* maximum number of source files */
|
||||
|
||||
static char **incnames; /* #include directory names without view pathing */
|
||||
static unsigned long mincdirs = DIRINC; /* maximum number of #include directories */
|
||||
static unsigned long msrcdirs; /* maximum number of source directories */
|
||||
static unsigned long nvpsrcdirs; /* number of view path source directories */
|
||||
|
||||
static struct listitem { /* source file names without view pathing */
|
||||
char *text;
|
||||
struct listitem *next;
|
||||
} *srcnames[HASHMOD];
|
||||
|
||||
/* Internal prototypes: */
|
||||
static BOOL accessible_file(char *file);
|
||||
static BOOL issrcfile(char *file);
|
||||
static void addsrcdir(char *dir);
|
||||
static void addincdir(char *name, char *path);
|
||||
static void scan_dir(const char *dirfile, BOOL recurse);
|
||||
static void makevpsrcdirs(void);
|
||||
|
||||
|
||||
/* make the view source directory list */
|
||||
|
||||
static void
|
||||
makevpsrcdirs(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* return if this function has already been called */
|
||||
if (nsrcdirs > 0) {
|
||||
return;
|
||||
}
|
||||
/* get the current directory name */
|
||||
if (getcwd(currentdir, PATHLEN) == NULL) {
|
||||
fprintf(stderr, "cscope: warning: cannot get current directory name\n");
|
||||
strcpy(currentdir, "<unknown>");
|
||||
}
|
||||
/* see if there is a view path and this directory is in it */
|
||||
vpinit(currentdir);
|
||||
if (vpndirs > 1) {
|
||||
nsrcdirs = vpndirs;
|
||||
} else {
|
||||
nsrcdirs = 1;
|
||||
}
|
||||
/* create the source directory list */
|
||||
msrcdirs = nsrcdirs + DIRINC;
|
||||
srcdirs = malloc(msrcdirs * sizeof(*srcdirs));
|
||||
*srcdirs = "."; /* first source dir is always current dir */
|
||||
for (i = 1; i < vpndirs; ++i) {
|
||||
srcdirs[i] = vpdirs[i];
|
||||
}
|
||||
/* save the number of original source directories in the view path */
|
||||
nvpsrcdirs = nsrcdirs;
|
||||
}
|
||||
|
||||
/* add a source directory to the list for each view path source directory */
|
||||
|
||||
void
|
||||
sourcedir(char *dirlist)
|
||||
{
|
||||
char path[PATHLEN + 1];
|
||||
char *dir;
|
||||
unsigned int i;
|
||||
|
||||
makevpsrcdirs(); /* make the view source directory list */
|
||||
dirlist = strdup(dirlist); /* don't change environment variable text */
|
||||
|
||||
/* parse the directory list */
|
||||
dir = strtok(dirlist, DIRSEPS);
|
||||
while (dir != NULL) {
|
||||
int dir_len = strlen(dir);
|
||||
|
||||
addsrcdir(dir);
|
||||
|
||||
/* if it isn't a full path name and there is a
|
||||
multi-directory view path */
|
||||
if (*dirlist != '/' && vpndirs > 1) {
|
||||
|
||||
/* compute its path from higher view path source dirs */
|
||||
for (i = 1; i < nvpsrcdirs; ++i) {
|
||||
snprintf(path, sizeof(path), "%.*s/%s",
|
||||
PATHLEN - 2 - dir_len,
|
||||
srcdirs[i], dir);
|
||||
addsrcdir(path);
|
||||
}
|
||||
}
|
||||
dir = strtok(NULL, DIRSEPS);
|
||||
}
|
||||
free(dirlist); /* HBB 20000421: avoid memory leaks */
|
||||
}
|
||||
|
||||
/* add a source directory to the list */
|
||||
|
||||
static void
|
||||
addsrcdir(char *dir)
|
||||
{
|
||||
struct stat statstruct;
|
||||
|
||||
/* make sure it is a directory */
|
||||
if (lstat(compath(dir), &statstruct) == 0 &&
|
||||
S_ISDIR(statstruct.st_mode)) {
|
||||
|
||||
/* note: there already is a source directory list */
|
||||
if (nsrcdirs == msrcdirs) {
|
||||
msrcdirs += DIRINC;
|
||||
srcdirs = realloc(srcdirs, msrcdirs * sizeof(*srcdirs));
|
||||
}
|
||||
srcdirs[nsrcdirs++] = strdup(dir);
|
||||
}
|
||||
}
|
||||
|
||||
/* HBB 20000421: new function, for avoiding leaks */
|
||||
/* free list of src directories */
|
||||
void
|
||||
freesrclist()
|
||||
{
|
||||
if (!srcdirs)
|
||||
return;
|
||||
while(nsrcdirs>1)
|
||||
free(srcdirs[--nsrcdirs]);
|
||||
free(srcdirs);
|
||||
}
|
||||
|
||||
/* add a #include directory to the list for each view path source directory */
|
||||
|
||||
void
|
||||
includedir(char *dirlist)
|
||||
{
|
||||
char path[PATHLEN + 1];
|
||||
char *dir;
|
||||
unsigned int i;
|
||||
|
||||
makevpsrcdirs(); /* make the view source directory list */
|
||||
dirlist = strdup(dirlist); /* don't change environment variable text */
|
||||
|
||||
/* parse the directory list */
|
||||
dir = strtok(dirlist, DIRSEPS);
|
||||
while (dir != NULL) {
|
||||
size_t dir_len = strlen(dir);
|
||||
|
||||
addincdir(dir, dir);
|
||||
|
||||
/* if it isn't a full path name and there is a
|
||||
multi-directory view path */
|
||||
if (*dirlist != '/' && vpndirs > 1) {
|
||||
|
||||
/* compute its path from higher view path source dirs */
|
||||
for (i = 1; i < nvpsrcdirs; ++i) {
|
||||
snprintf(path, sizeof(path), "%.*s/%s",
|
||||
(int)(PATHLEN - 2 - dir_len),
|
||||
srcdirs[i], dir);
|
||||
addincdir(dir, path);
|
||||
}
|
||||
}
|
||||
dir = strtok(NULL, DIRSEPS);
|
||||
}
|
||||
free(dirlist); /* HBB 20000421: avoid leaks */
|
||||
}
|
||||
|
||||
/* add a #include directory to the list */
|
||||
|
||||
static void
|
||||
addincdir(char *name, char *path)
|
||||
{
|
||||
struct stat statstruct;
|
||||
|
||||
/* make sure it is a directory */
|
||||
if (lstat(compath(path), &statstruct) == 0 &&
|
||||
S_ISDIR(statstruct.st_mode)) {
|
||||
if (incdirs == NULL) {
|
||||
incdirs = malloc(mincdirs * sizeof(*incdirs));
|
||||
incnames = malloc(mincdirs * sizeof(*incnames));
|
||||
} else if (nincdirs == mincdirs) {
|
||||
mincdirs += DIRINC;
|
||||
incdirs = realloc(incdirs, mincdirs * sizeof(*incdirs));
|
||||
incnames = realloc(incnames, mincdirs * sizeof(*incnames));
|
||||
}
|
||||
incdirs[nincdirs] = strdup(path);
|
||||
incnames[nincdirs++] = strdup(name);
|
||||
}
|
||||
}
|
||||
|
||||
/* HBB 2000421: new function, for avoiding memory leaks */
|
||||
/* free the list of include files, if wanted */
|
||||
|
||||
void
|
||||
freeinclist()
|
||||
{
|
||||
if (!incdirs)
|
||||
return;
|
||||
while(nincdirs>0) {
|
||||
free(incdirs[--nincdirs]);
|
||||
free(incnames[nincdirs]);
|
||||
}
|
||||
free(incdirs);
|
||||
free(incnames);
|
||||
}
|
||||
|
||||
/* make the source file list */
|
||||
|
||||
void
|
||||
makefilelist(void)
|
||||
{
|
||||
static BOOL firstbuild = YES; /* first time through */
|
||||
FILE *names; /* name file pointer */
|
||||
char dir[PATHLEN + 1];
|
||||
char path[PATHLEN + 1];
|
||||
char line[PATHLEN * 10];
|
||||
char *file;
|
||||
char *s;
|
||||
unsigned int i;
|
||||
|
||||
makevpsrcdirs(); /* make the view source directory list */
|
||||
|
||||
/* if -i was NOT given and there are source file arguments */
|
||||
if (namefile == NULL && fileargc > 0) {
|
||||
|
||||
/* put them in a list that can be expanded */
|
||||
for (i = 0; i < fileargc; ++i) {
|
||||
file = fileargv[i];
|
||||
if (infilelist(file) == NO) {
|
||||
if ((s = inviewpath(file)) != NULL) {
|
||||
addsrcfile(s);
|
||||
} else {
|
||||
fprintf(stderr, "cscope: cannot find file %s\n",
|
||||
file);
|
||||
errorsfound = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* see if a file name file exists */
|
||||
if (namefile == NULL && vpaccess(NAMEFILE, READ) == 0) {
|
||||
namefile = NAMEFILE;
|
||||
}
|
||||
|
||||
if (namefile == NULL) {
|
||||
/* No namefile --> make a list of all the source files
|
||||
* in the directories */
|
||||
for (i = 0; i < nsrcdirs; ++i) {
|
||||
scan_dir(srcdirs[i], recurse_dir);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Came here --> there is a file of source file names */
|
||||
|
||||
if (strcmp(namefile, "-") == 0)
|
||||
names = stdin;
|
||||
else if ((names = vpfopen(namefile, "r")) == NULL) {
|
||||
cannotopen(namefile);
|
||||
myexit(1);
|
||||
}
|
||||
|
||||
/* get the names in the file */
|
||||
while (fgets(line, 10*PATHLEN, names) != NULL) {
|
||||
char *point_in_line = line + (strlen(line) - 1);
|
||||
size_t length_of_name = 0;
|
||||
int unfinished_option = 0;
|
||||
BOOL done = NO;
|
||||
|
||||
/* Kill away \n left at end of fgets()'d string: */
|
||||
if (*point_in_line == '\n')
|
||||
*point_in_line = '\0';
|
||||
|
||||
/* Parse whitespace-terminated strings in line: */
|
||||
point_in_line = line;
|
||||
while (sscanf(point_in_line, "%" PATHLEN_STR "s", path) == 1) {
|
||||
/* Have to store this length --- inviewpath() will
|
||||
* modify path, later! */
|
||||
length_of_name = strlen(path);
|
||||
|
||||
if (*path == '-') { /* if an option */
|
||||
if (unfinished_option) {
|
||||
/* Can't have another option directly after an
|
||||
* -I or -p option with no name after it! */
|
||||
fprintf(stderr, "\
|
||||
cscope: Syntax error in namelist file %s: unfinished -I or -p option\n",
|
||||
namefile);
|
||||
unfinished_option = 0;
|
||||
}
|
||||
|
||||
i = path[1];
|
||||
switch (i) {
|
||||
case 'c': /* ASCII characters only in crossref */
|
||||
compress = NO;
|
||||
break;
|
||||
case 'k': /* ignore DFLT_INCDIR */
|
||||
kernelmode = YES;
|
||||
break;
|
||||
case 'q': /* quick search */
|
||||
invertedindex = YES;
|
||||
break;
|
||||
case 'T': /* truncate symbols to 8 characters */
|
||||
trun_syms = YES;
|
||||
break;
|
||||
case 'I': /* #include file directory */
|
||||
case 'p': /* file path components to display */
|
||||
/* coverity[overwrite_var] */
|
||||
s = path + 2; /* for "-Ipath" */
|
||||
if (*s == '\0') { /* if "-I path" */
|
||||
unfinished_option = i;
|
||||
break;
|
||||
}
|
||||
|
||||
/* this code block used several times in here
|
||||
* --> make it a macro to avoid unnecessary
|
||||
* duplication */
|
||||
#define HANDLE_OPTION_ARGUMENT(i, s) \
|
||||
switch (i) { \
|
||||
case 'I': /* #include file directory */ \
|
||||
if (firstbuild == YES) { \
|
||||
/* expand $ and ~ */ \
|
||||
shellpath(dir, sizeof(dir), (s)); \
|
||||
includedir(dir); \
|
||||
} \
|
||||
unfinished_option = 0; \
|
||||
done = YES; \
|
||||
break; \
|
||||
case 'p': /* file path components to display */ \
|
||||
if (*(s) < '0' || *(s) > '9') { \
|
||||
fprintf(stderr, \
|
||||
"cscope: -p option in file %s: missing or invalid numeric value\n", \
|
||||
namefile); \
|
||||
} \
|
||||
dispcomponents = atoi(s); \
|
||||
unfinished_option = 0; \
|
||||
done = YES; \
|
||||
break; \
|
||||
default: \
|
||||
done = NO; \
|
||||
} /* switch(i) */
|
||||
|
||||
/* ... and now call it for the first time */
|
||||
HANDLE_OPTION_ARGUMENT(i, s)
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "cscope: only -I, -c, -k, -p, and -T options can be in file %s\n",
|
||||
namefile);
|
||||
} /* switch(i) */
|
||||
} /* if('-') */
|
||||
else if (*path == '"') {
|
||||
/* handle quoted filenames... */
|
||||
size_t in = 1, out = 0;
|
||||
char *newpath = malloc(PATHLEN + 1);
|
||||
|
||||
while (in < PATHLEN && point_in_line[in] != '\0') {
|
||||
if (point_in_line[in] == '"') {
|
||||
newpath[out] = '\0';
|
||||
/* Tell outer loop to skip over this entire
|
||||
* quoted string */
|
||||
length_of_name = in + 1;
|
||||
break; /* found end of quoted string */
|
||||
} else if (point_in_line[in] == '\\'
|
||||
&& in < PATHLEN - 1
|
||||
&& (point_in_line[in + 1]== '"'
|
||||
|| point_in_line[in + 1] == '\\')) {
|
||||
/* un-escape \" or \\ sequence */
|
||||
newpath[out++] = point_in_line[in + 1];
|
||||
in += 2;
|
||||
} else {
|
||||
newpath[out++] = point_in_line[in++];
|
||||
}
|
||||
} /* while(in) */
|
||||
if (in >= PATHLEN) { /* safeguard against almost-overflow */
|
||||
newpath[out]='\0';
|
||||
}
|
||||
|
||||
/* If an -I or -p arguments was missing before,
|
||||
* treat this name as the argument: */
|
||||
HANDLE_OPTION_ARGUMENT(unfinished_option, newpath);
|
||||
if (! done) {
|
||||
/* coverity[overwrite_var] */
|
||||
if ((s = inviewpath(newpath)) != NULL) {
|
||||
addsrcfile(s);
|
||||
} else {
|
||||
fprintf(stderr, "cscope: cannot find file %s\n",
|
||||
newpath);
|
||||
errorsfound = YES;
|
||||
}
|
||||
}
|
||||
free(newpath);
|
||||
} /* if(quoted name) */
|
||||
else {
|
||||
/* ... so this is an ordinary file name, unquoted */
|
||||
|
||||
/* If an -I or -p arguments was missing before,
|
||||
* treat this name as the argument: */
|
||||
HANDLE_OPTION_ARGUMENT(unfinished_option, path);
|
||||
if (!done) {
|
||||
if ((s = inviewpath(path)) != NULL) {
|
||||
addsrcfile(s);
|
||||
} else {
|
||||
fprintf(stderr, "cscope: cannot find file %s\n",
|
||||
path);
|
||||
errorsfound = YES;
|
||||
}
|
||||
}
|
||||
} /* else(ordinary name) */
|
||||
|
||||
point_in_line += length_of_name;
|
||||
while (isspace((unsigned char) *point_in_line))
|
||||
point_in_line ++;
|
||||
} /* while(sscanf(line)) */
|
||||
} /* while(fgets(line)) */
|
||||
|
||||
if (names == stdin)
|
||||
clearerr(stdin);
|
||||
else
|
||||
fclose(names);
|
||||
firstbuild = NO;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* scan a directory (recursively?) for source files */
|
||||
static void
|
||||
scan_dir(const char *adir, BOOL recurse_dir)
|
||||
{
|
||||
DIR *dirfile;
|
||||
int adir_len = strlen(adir);
|
||||
|
||||
/* FIXME: no guards against adir_len > PATHLEN, yet */
|
||||
|
||||
if ((dirfile = opendir(adir)) != NULL) {
|
||||
struct dirent *entry;
|
||||
char path[PATHLEN + 1];
|
||||
|
||||
while ((entry = readdir(dirfile)) != NULL) {
|
||||
if ((strcmp(".",entry->d_name) != 0)
|
||||
&& (strcmp("..",entry->d_name) != 0)) {
|
||||
struct stat buf;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%.*s", adir,
|
||||
PATHLEN - 2 - adir_len,
|
||||
entry->d_name);
|
||||
|
||||
if (lstat(path,&buf) == 0) {
|
||||
if (recurse_dir
|
||||
&& S_ISDIR(buf.st_mode) ) {
|
||||
scan_dir(path, recurse_dir);
|
||||
} else if (issrcfile(path)
|
||||
&& infilelist(path) == NO
|
||||
&& access(path, R_OK) == 0) {
|
||||
addsrcfile(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dirfile);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* see if this is a source file */
|
||||
static BOOL
|
||||
issrcfile(char *path)
|
||||
{
|
||||
struct stat statstruct;
|
||||
char *file = basename(path);
|
||||
char *s = strrchr(file, '.');
|
||||
BOOL looks_like_source = NO;
|
||||
|
||||
/* ensure there is some file suffix */
|
||||
if (s == NULL || *++s == '\0')
|
||||
return NO;
|
||||
|
||||
/* if an SCCS or versioned file */
|
||||
if (file[1] == '.' && file + 2 != s) { /* 1 character prefix */
|
||||
switch (*file) {
|
||||
case 's':
|
||||
case 'S':
|
||||
return(NO);
|
||||
}
|
||||
}
|
||||
|
||||
if (s[1] == '\0') { /* 1 character suffix */
|
||||
switch (*s) {
|
||||
case 'c':
|
||||
case 'h':
|
||||
case 'l':
|
||||
case 'y':
|
||||
case 'C':
|
||||
case 'G':
|
||||
case 'H':
|
||||
case 'L':
|
||||
looks_like_source = YES;
|
||||
}
|
||||
} else if ((s[2] == '\0') /* 2 char suffix */
|
||||
&& ((s[0] == 'b' && s[1] == 'p') /* breakpoint listing */
|
||||
|| (s[0] == 'q'
|
||||
&& (s[1] == 'c' || s[1] == 'h')) /* Ingres */
|
||||
|| (s[0] == 's' && s[1] == 'd') /* SDL */
|
||||
|| (s[0] == 'c' && s[1] == 'c') /* C++ source */
|
||||
|| (s[0] == 'h' && s[1] == 'h'))) { /* C++ header */
|
||||
looks_like_source = YES;
|
||||
|
||||
} else if((s[3] == '\0') /* 3 char suffix */
|
||||
/* C++ template source */
|
||||
&& ((s[0] == 't' && s[1] == 'c' && s[2] == 'c' )
|
||||
/* C++ source: */
|
||||
|| (s[0] == 'c' && s[1] == 'p' && s[2] == 'p' )
|
||||
|| (s[0] == 'c' && s[1] == 'x' && s[2] == 'x' )
|
||||
|| (s[0] == 'h' && s[1] == 'p' && s[2] == 'p' )
|
||||
|| (s[0] == 'h' && s[1] == 'x' && s[2] == 'x' ))
|
||||
) {
|
||||
looks_like_source = YES;
|
||||
}
|
||||
|
||||
if (looks_like_source != YES)
|
||||
return NO;
|
||||
|
||||
/* make sure it is a file */
|
||||
if (lstat(path, &statstruct) == 0 &&
|
||||
S_ISREG(statstruct.st_mode)) {
|
||||
return(YES);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
/* add an include file to the source file list */
|
||||
void
|
||||
incfile(char *file, char *type)
|
||||
{
|
||||
char name[PATHLEN + 1];
|
||||
char path[PATHLEN + 1];
|
||||
char *s;
|
||||
unsigned int i;
|
||||
|
||||
assert(file != NULL); /* should never happen, but let's make sure anyway */
|
||||
/* see if the file is already in the source file list */
|
||||
if (infilelist(file) == YES) {
|
||||
return;
|
||||
}
|
||||
/* look in current directory if it was #include "file" */
|
||||
if (type[0] == '"' && (s = inviewpath(file)) != NULL) {
|
||||
addsrcfile(s);
|
||||
} else {
|
||||
size_t file_len = strlen(file);
|
||||
|
||||
/* search for the file in the #include directory list */
|
||||
for (i = 0; i < nincdirs; ++i) {
|
||||
/* don't include the file from two directories */
|
||||
snprintf(name, sizeof(name), "%.*s/%s",
|
||||
(int)(PATHLEN - 2 - file_len), incnames[i],
|
||||
file);
|
||||
if (infilelist(name) == YES) {
|
||||
break;
|
||||
}
|
||||
/* make sure it exists and is readable */
|
||||
snprintf(path, sizeof(path), "%.*s/%s",
|
||||
(int)(PATHLEN - 2 - file_len), incdirs[i],
|
||||
file);
|
||||
if (access(compath(path), READ) == 0) {
|
||||
addsrcfile(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* see if the file is already in the list */
|
||||
BOOL
|
||||
infilelist(char *path)
|
||||
{
|
||||
struct listitem *p;
|
||||
|
||||
for (p = srcnames[hash(compath(path)) % HASHMOD];
|
||||
p != NULL;
|
||||
p = p->next) {
|
||||
if (strequal(path, p->text)) {
|
||||
return(YES);
|
||||
}
|
||||
}
|
||||
return(NO);
|
||||
}
|
||||
|
||||
|
||||
/* check if a file is readable enough to be allowed in the
|
||||
* database */
|
||||
static BOOL
|
||||
accessible_file(char *file)
|
||||
{
|
||||
if (access(compath(file), READ) == 0) {
|
||||
struct stat stats;
|
||||
|
||||
if (lstat(file, &stats) == 0
|
||||
&& S_ISREG(stats.st_mode)) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* search for the file in the view path */
|
||||
char *
|
||||
inviewpath(char *file)
|
||||
{
|
||||
static char path[PATHLEN + 1];
|
||||
unsigned int i;
|
||||
|
||||
/* look for the file */
|
||||
if (accessible_file(file)) {
|
||||
return(file);
|
||||
}
|
||||
|
||||
/* if it isn't a full path name and there is a multi-directory
|
||||
* view path */
|
||||
if (*file != '/' && vpndirs > 1) {
|
||||
int file_len = strlen(file);
|
||||
|
||||
/* compute its path from higher view path source dirs */
|
||||
for (i = 1; i < nvpsrcdirs; ++i) {
|
||||
snprintf(path, sizeof(path), "%.*s/%s",
|
||||
PATHLEN - 2 - file_len, srcdirs[i],
|
||||
file);
|
||||
if (accessible_file(path)) {
|
||||
return(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* add a source file to the list */
|
||||
|
||||
void
|
||||
addsrcfile(char *path)
|
||||
{
|
||||
struct listitem *p;
|
||||
int i;
|
||||
|
||||
/* make sure there is room for the file */
|
||||
if (nsrcfiles == msrcfiles) {
|
||||
msrcfiles += SRCINC;
|
||||
srcfiles = realloc(srcfiles, msrcfiles * sizeof(*srcfiles));
|
||||
}
|
||||
/* add the file to the list */
|
||||
srcfiles[nsrcfiles++] = strdup(compath(path));
|
||||
p = malloc(sizeof(*p));
|
||||
p->text = strdup(compath(path));
|
||||
i = hash(p->text) % HASHMOD;
|
||||
p->next = srcnames[i];
|
||||
srcnames[i] = p;
|
||||
}
|
||||
|
||||
/* free the memory allocated for the source file list */
|
||||
|
||||
void
|
||||
freefilelist(void)
|
||||
{
|
||||
struct listitem *p, *nextp;
|
||||
int i;
|
||||
|
||||
/* if '-d' option is used a string space block is allocated */
|
||||
if (isuptodate == NO) {
|
||||
while (nsrcfiles > 0) {
|
||||
free (srcfiles[--nsrcfiles]);
|
||||
}
|
||||
} else {
|
||||
/* for '-d' option free the string space block */
|
||||
/* protect against empty list */
|
||||
if (nsrcfiles > 0)
|
||||
free (srcfiles[0]);
|
||||
nsrcfiles = 0;
|
||||
}
|
||||
|
||||
free (srcfiles); /* HBB 20000421: avoid leak */
|
||||
msrcfiles = 0;
|
||||
srcfiles=0;
|
||||
|
||||
for (i = 0; i < HASHMOD; ++i) {
|
||||
for (p = srcnames[i]; p != NULL; p = nextp) {
|
||||
/* HBB 20000421: avoid memory leak */
|
||||
free(p->text);
|
||||
nextp = p->next;
|
||||
free(p);
|
||||
}
|
||||
srcnames[i] = NULL;
|
||||
}
|
||||
}
|
784
src/display.c
Normal file
784
src/display.c
Normal file
@ -0,0 +1,784 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* display functions
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "build.h"
|
||||
|
||||
#ifdef CCS
|
||||
#include "sgs.h" /* ESG_PKG and ESG_REL */
|
||||
#else
|
||||
#include "version.h" /* FILEVERSION and FIXVERSION */
|
||||
#endif
|
||||
|
||||
#include <ncurses.h>
|
||||
#include <setjmp.h> /* jmp_buf */
|
||||
#include <stdarg.h> /* va_list stuff */
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int booklen; /* OGS book name display field length */
|
||||
int *displine; /* screen line of displayed reference */
|
||||
unsigned int disprefs; /* displayed references */
|
||||
int field; /* input field */
|
||||
int filelen; /* file name display field length */
|
||||
int fcnlen; /* function name display field length */
|
||||
unsigned int mdisprefs; /* maximum displayed references */
|
||||
unsigned int nextline; /* next line to be shown */
|
||||
FILE *nonglobalrefs; /* non-global references file */
|
||||
int numlen; /* line number display field length */
|
||||
unsigned int topline = 1; /* top line of page */
|
||||
int bottomline; /* bottom line of page */
|
||||
long searchcount; /* count of files searched */
|
||||
int subsystemlen; /* OGS subsystem name display field length */
|
||||
unsigned int totallines; /* total reference lines */
|
||||
unsigned fldcolumn; /* input field column */
|
||||
WINDOW* body;
|
||||
WINDOW* input_fields;
|
||||
|
||||
static enum {
|
||||
CH_BODY = 0x0001,
|
||||
CH_INPUT_FIELDS = CH_BODY << 1,
|
||||
CH_COMMAND_FIELD = CH_BODY << 2,
|
||||
CH_ALL = CH_BODY | CH_INPUT_FIELDS | CH_COMMAND_FIELD
|
||||
};
|
||||
|
||||
const char dispchars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
static int fldline; /* input field line */
|
||||
static sigjmp_buf env; /* setjmp/longjmp buffer */
|
||||
static int lastdispline; /* last displayed reference line */
|
||||
static char lastmsg[MSGLEN + 1]; /* last message displayed */
|
||||
static const char helpstring[] = "Press the ? key for help";
|
||||
static const char selprompt[] =
|
||||
"Select lines to change (press the ? key for help): ";
|
||||
|
||||
typedef char * (*FP)(char *); /* pointer to function returning a character pointer */
|
||||
|
||||
/* HBB 2000/05/05: I removed the casts to function pointer type. It is
|
||||
* fundamentally unsafe to call a function through a pointer of a
|
||||
* different type ('undefined behaviour' in the words of the ANSI/ISO
|
||||
* C standard). Instead, I made all the find...() functions adhere to
|
||||
* the same function type, by changing argument passing a bit. */
|
||||
static struct { /* text of input fields */
|
||||
char *text1;
|
||||
char *text2;
|
||||
FP findfcn;
|
||||
} fields[FIELDS + 1] = { /* samuel has a search that is not part of the cscope display */
|
||||
{"Find this", "C symbol", findsymbol},
|
||||
{"Find this", "global definition", finddef},
|
||||
{"Find", "functions called by this function", findcalledby},
|
||||
{"Find", "functions calling this function", findcalling},
|
||||
{"Find this", "text string", findstring},
|
||||
{"Change this", "text string", findstring},
|
||||
{"Find this", "egrep pattern", findregexp},
|
||||
{"Find this", "file", findfile},
|
||||
{"Find", "files #including this file", findinclude},
|
||||
{"Find", "assignments to this symbol", findassign},
|
||||
{"Find all", "function definitions", findallfcns}, /* samuel only */
|
||||
};
|
||||
|
||||
/* Internal prototypes: */
|
||||
static void jumpback(int sig);
|
||||
|
||||
/* initialize display parameters */
|
||||
|
||||
void
|
||||
dispinit(void)
|
||||
{
|
||||
/* initialize the curses display package */
|
||||
initscr(); /* initialize the screen */
|
||||
entercurses();
|
||||
keypad(stdscr, TRUE); /* enable the keypad */
|
||||
//fixkeypad(); /* fix for getch() intermittently returning garbage */
|
||||
standend(); /* turn off reverse video */
|
||||
|
||||
/* calculate the maximum displayed reference lines */
|
||||
lastdispline = FLDLINE - 3;
|
||||
mdisprefs = lastdispline - REFLINE + 1;
|
||||
|
||||
|
||||
if (mdisprefs <= 0) {
|
||||
postfatal("%s: screen too small\n", argv0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
if (mouse == NO && mdisprefs > strlen(dispchars))
|
||||
mdisprefs = strlen(dispchars);
|
||||
|
||||
/* allocate the displayed line array */
|
||||
displine = malloc(mdisprefs * sizeof(*displine));
|
||||
|
||||
/* initialize windows */
|
||||
body = newwin(LINES-2-FIELDS, COLS-2, 1, 1);
|
||||
input_fields = newwin(FIELDS, COLS-2, FLDLINE, 1);
|
||||
refresh();
|
||||
}
|
||||
|
||||
static inline void display_frame(){
|
||||
|
||||
box(stdscr, 0, 0);
|
||||
/* Title*/
|
||||
const int LEFT_PADDING = 5;
|
||||
wmove(stdscr, 0, LEFT_PADDING);
|
||||
#if CCS
|
||||
if (displayversion == YES) {
|
||||
wprintw(stdscr, "cscope %s", ESG_REL);
|
||||
}
|
||||
else {
|
||||
waddstr(stdscr, "cscope");
|
||||
}
|
||||
#else
|
||||
wprintw(stdscr, "Cscope version %d%s", FILEVERSION, FIXVERSION);
|
||||
#endif
|
||||
wmove(stdscr, 0, COLS - (int) sizeof(helpstring));
|
||||
waddstr(stdscr, helpstring);
|
||||
wmove(input_fields, 0, 0);
|
||||
for(int i = 0; i < COLS-2; i++){
|
||||
waddch(input_fields, ACS_HLINE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void display_input_fields(){
|
||||
/* display the input fields */
|
||||
wmove(input_fields, 1, 0);
|
||||
for(int i = 0; i < FIELDS; ++i){
|
||||
wprintw(input_fields, "%s %s:\n", fields[i].text1, fields[i].text2);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void display_command_field(){
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
display(void)
|
||||
{
|
||||
char *subsystem; /* OGS subsystem name */
|
||||
char *book; /* OGS book name */
|
||||
char file[PATHLEN + 1]; /* file name */
|
||||
char function[PATLEN + 1]; /* function name */
|
||||
char linenum[NUMLEN + 1]; /* line number */
|
||||
int screenline; /* screen line number */
|
||||
int width; /* source line display width */
|
||||
int i;
|
||||
char *s;
|
||||
|
||||
erase();
|
||||
display_frame();
|
||||
|
||||
if (totallines == 0) {
|
||||
/* if no references were found */
|
||||
/* redisplay the last message */
|
||||
waddstr(body, lastmsg);
|
||||
} else {
|
||||
/* display the pattern */
|
||||
if (changing == YES) {
|
||||
wprintw(body, "Change \"%s\" to \"%s\"", Pattern, newpat);
|
||||
} else {
|
||||
wprintw(body, "%c%s: %s", toupper((unsigned char)fields[field].text2[0]),
|
||||
fields[field].text2 + 1, Pattern);
|
||||
}
|
||||
/* display the column headings */
|
||||
wmove(body, 2, 2);
|
||||
if (ogs == YES && field != FILENAME) {
|
||||
wprintw(body, "%-*s ", subsystemlen, "Subsystem");
|
||||
wprintw(body, "%-*s ", booklen, "Book");
|
||||
}
|
||||
if (dispcomponents > 0)
|
||||
wprintw(body, "%-*s ", filelen, "File");
|
||||
|
||||
if (field == SYMBOL || field == CALLEDBY || field == CALLING) {
|
||||
wprintw(body, "%-*s ", fcnlen, "Function");
|
||||
}
|
||||
if (field != FILENAME) {
|
||||
waddstr(body, "Line");
|
||||
}
|
||||
waddch(body, '\n');
|
||||
|
||||
/* if at end of file go back to beginning */
|
||||
if (nextline > totallines) {
|
||||
seekline(1);
|
||||
}
|
||||
/* calculate the source text column */
|
||||
|
||||
width = COLS - numlen - 3;
|
||||
|
||||
if (ogs == YES) {
|
||||
width -= subsystemlen + booklen + 2;
|
||||
}
|
||||
if (dispcomponents > 0) {
|
||||
width -= filelen + 1;
|
||||
}
|
||||
if (field == SYMBOL || field == CALLEDBY || field == CALLING) {
|
||||
width -= fcnlen + 1;
|
||||
}
|
||||
|
||||
/* until the max references have been displayed or
|
||||
there is no more room */
|
||||
topline = nextline;
|
||||
for (disprefs = 0, screenline = REFLINE;
|
||||
disprefs < mdisprefs && screenline <= lastdispline;
|
||||
++disprefs, ++screenline) {
|
||||
/* read the reference line */
|
||||
if (fscanf(refsfound, "%" PATHLEN_STR "s%" PATHLEN_STR "s%" NUMLEN_STR "s %" TEMPSTRING_LEN_STR "[^\n]", file, function,
|
||||
linenum, tempstring) < 4) {
|
||||
break;
|
||||
}
|
||||
++nextline;
|
||||
displine[disprefs] = screenline;
|
||||
|
||||
/* if no mouse, display the selection number */
|
||||
if (mouse == YES) {
|
||||
waddch(body, ' ');
|
||||
} else {
|
||||
wprintw(body, "%c", dispchars[disprefs]);
|
||||
}
|
||||
|
||||
/* display any change mark */
|
||||
if (changing == YES &&
|
||||
change[topline + disprefs - 1] == YES) {
|
||||
waddch(body, '>');
|
||||
} else {
|
||||
waddch(body, ' ');
|
||||
}
|
||||
|
||||
/* display the file name */
|
||||
if (field == FILENAME) {
|
||||
wprintw(body, "%-*s ", filelen, file);
|
||||
} else {
|
||||
/* if OGS, display the subsystem and book names */
|
||||
if (ogs == YES) {
|
||||
ogsnames(file, &subsystem, &book);
|
||||
wprintw(body, "%-*.*s ", subsystemlen, subsystemlen, subsystem);
|
||||
wprintw(body, "%-*.*s ", booklen, booklen, book);
|
||||
}
|
||||
/* display the requested path components */
|
||||
if (dispcomponents > 0) {
|
||||
wprintw(body, "%-*.*s ", filelen, filelen,
|
||||
pathcomponents(file, dispcomponents));
|
||||
}
|
||||
} /* else(field == FILENAME) */
|
||||
|
||||
/* display the function name */
|
||||
if (field == SYMBOL || field == CALLEDBY || field == CALLING) {
|
||||
wprintw(body, "%-*.*s ", fcnlen, fcnlen, function);
|
||||
}
|
||||
if (field == FILENAME) {
|
||||
waddch(body, '\n'); /* go to next line */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* display the line number */
|
||||
wprintw(body, "%*s ", numlen, linenum);
|
||||
/* there may be tabs in egrep output */
|
||||
while ((s = strchr(tempstring, '\t')) != NULL) {
|
||||
*s = ' ';
|
||||
}
|
||||
|
||||
/* display the source line */
|
||||
s = tempstring;
|
||||
for (;;) {
|
||||
/* see if the source line will fit */
|
||||
if ((i = strlen(s)) > width) {
|
||||
|
||||
/* find the nearest blank */
|
||||
for (i = width; s[i] != ' ' && i > 0; --i) {
|
||||
;
|
||||
}
|
||||
if (i == 0) {
|
||||
i = width; /* no blank */
|
||||
}
|
||||
}
|
||||
/* print up to this point */
|
||||
wprintw(body, "%.*s", i, s);
|
||||
s += i;
|
||||
|
||||
/* if line didn't wrap around */
|
||||
if (i < width) {
|
||||
waddch(body, '\n'); /* go to next line */
|
||||
}
|
||||
/* skip blanks */
|
||||
while (*s == ' ') {
|
||||
++s;
|
||||
}
|
||||
/* see if there is more text */
|
||||
if (*s == '\0') {
|
||||
break;
|
||||
}
|
||||
/* if the source line is too long */
|
||||
if (++screenline > lastdispline) {
|
||||
|
||||
/* if this is the first displayed line,
|
||||
display what will fit on the screen */
|
||||
if (topline == nextline -1) {
|
||||
disprefs++;
|
||||
/* break out of two loops */
|
||||
goto endrefs;
|
||||
}
|
||||
|
||||
/* erase the reference */
|
||||
while (--screenline >= displine[disprefs]) {
|
||||
wmove(body, screenline, 0);
|
||||
clrtoeol();
|
||||
}
|
||||
++screenline;
|
||||
|
||||
/* go back to the beginning of this reference */
|
||||
--nextline;
|
||||
seekline(nextline);
|
||||
goto endrefs;
|
||||
}
|
||||
/* indent the continued source line */
|
||||
wmove(body, screenline, COLS - width);
|
||||
} /* for(ever) */
|
||||
} /* for(reference output lines) */
|
||||
endrefs:
|
||||
/* position the cursor for the message */
|
||||
i = FLDLINE - 1;
|
||||
if (screenline < i) {
|
||||
waddch(body, '\n');
|
||||
}
|
||||
else {
|
||||
wmove(body, i, 0);
|
||||
}
|
||||
/* check for more references */
|
||||
i = totallines - nextline + 1;
|
||||
bottomline = nextline;
|
||||
if (i > 0) {
|
||||
wprintw(body, "* Lines %d-%d of %d, %d more - press the space bar to display more *", topline, bottomline, totallines, i);
|
||||
}
|
||||
/* if this is the last page of references */
|
||||
else if (topline > 1 && nextline > totallines) {
|
||||
waddstr(body, "* Press the space bar to display the first lines again *");
|
||||
}
|
||||
}
|
||||
drawscrollbar(topline, nextline); /* display the scrollbar */
|
||||
|
||||
atfield();
|
||||
|
||||
display_input_fields();
|
||||
display_prompt();
|
||||
|
||||
refresh();
|
||||
wrefresh(body);
|
||||
wrefresh(input_fields);
|
||||
}
|
||||
|
||||
/* set the cursor position for the field */
|
||||
//void
|
||||
//setfield(void)
|
||||
//{
|
||||
// fldline = FLDLINE + field;
|
||||
// fldcolumn = strlen(fields[field].text1) + strlen(fields[field].text2) + 3;
|
||||
//}
|
||||
|
||||
/* move to the current input field */
|
||||
//
|
||||
//void
|
||||
//atfield(void)
|
||||
//{
|
||||
// wmove(input_fields, fldline, fldcolumn);
|
||||
//}
|
||||
|
||||
/* move to the changing lines prompt */
|
||||
|
||||
//void
|
||||
//atchange(void)
|
||||
//{
|
||||
// wmove(body, PRLINE, (int) sizeof(selprompt) - 1);
|
||||
//}
|
||||
|
||||
/* search for the symbol or text pattern */
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
jumpback(int sig)
|
||||
{
|
||||
signal(sig, jumpback);
|
||||
siglongjmp(env, 1);
|
||||
}
|
||||
|
||||
BOOL
|
||||
search(void)
|
||||
{
|
||||
char *findresult = NULL; /* find function output */
|
||||
BOOL funcexist = YES; /* find "function" error */
|
||||
FINDINIT rc = NOERROR; /* findinit return code */
|
||||
sighandler_t savesig; /* old value of signal */
|
||||
FP f; /* searching function */
|
||||
int c;
|
||||
|
||||
/* open the references found file for writing */
|
||||
if (writerefsfound() == NO) {
|
||||
return(NO);
|
||||
}
|
||||
/* find the pattern - stop on an interrupt */
|
||||
if (linemode == NO) {
|
||||
postmsg("Searching");
|
||||
}
|
||||
searchcount = 0;
|
||||
savesig = signal(SIGINT, jumpback);
|
||||
if (sigsetjmp(env, 1) == 0) {
|
||||
f = fields[field].findfcn;
|
||||
if (f == findregexp || f == findstring) {
|
||||
findresult = (*f)(Pattern);
|
||||
} else {
|
||||
if ((nonglobalrefs = myfopen(temp2, "wb")) == NULL) {
|
||||
cannotopen(temp2);
|
||||
return(NO);
|
||||
}
|
||||
if ((rc = findinit(Pattern)) == NOERROR) {
|
||||
(void) dbseek(0L); /* read the first block */
|
||||
findresult = (*f)(Pattern);
|
||||
if (f == findcalledby)
|
||||
funcexist = (*findresult == 'y');
|
||||
findcleanup();
|
||||
|
||||
/* append the non-global references */
|
||||
(void) fclose(nonglobalrefs);
|
||||
if ((nonglobalrefs = myfopen(temp2, "rb"))
|
||||
== NULL) {
|
||||
cannotopen(temp2);
|
||||
return(NO);
|
||||
}
|
||||
while ((c = getc(nonglobalrefs)) != EOF) {
|
||||
(void) putc(c, refsfound);
|
||||
}
|
||||
}
|
||||
(void) fclose(nonglobalrefs);
|
||||
}
|
||||
}
|
||||
signal(SIGINT, savesig);
|
||||
|
||||
/* rewind the cross-reference file */
|
||||
(void) lseek(symrefs, (long) 0, 0);
|
||||
|
||||
/* reopen the references found file for reading */
|
||||
(void) fclose(refsfound);
|
||||
if ((refsfound = myfopen(temp1, "rb")) == NULL) {
|
||||
cannotopen(temp1);
|
||||
return(NO);
|
||||
}
|
||||
nextline = 1;
|
||||
totallines = 0;
|
||||
disprefs = 0;
|
||||
|
||||
/* see if it is empty */
|
||||
if ((c = getc(refsfound)) == EOF) {
|
||||
if (findresult != NULL) {
|
||||
(void) snprintf(lastmsg, sizeof(lastmsg), "Egrep %s in this pattern: %s",
|
||||
findresult, Pattern);
|
||||
} else if (rc == NOTSYMBOL) {
|
||||
(void) snprintf(lastmsg, sizeof(lastmsg), "This is not a C symbol: %s",
|
||||
Pattern);
|
||||
} else if (rc == REGCMPERROR) {
|
||||
(void) snprintf(lastmsg, sizeof(lastmsg), "Error in this regcomp(3) regular expression: %s",
|
||||
Pattern);
|
||||
|
||||
} else if (funcexist == NO) {
|
||||
(void) snprintf(lastmsg, sizeof(lastmsg), "Function definition does not exist: %s",
|
||||
Pattern);
|
||||
} else {
|
||||
(void) snprintf(lastmsg, sizeof(lastmsg), "Could not find the %s: %s",
|
||||
fields[field].text2, Pattern);
|
||||
}
|
||||
return(NO);
|
||||
}
|
||||
/* put back the character read */
|
||||
(void) ungetc(c, refsfound);
|
||||
|
||||
/* HBB 20041027: this used to hold a copy of the code of
|
||||
* countrefs(), but with the crucial display width adjustments
|
||||
* missing. Just call the real thing instead! */
|
||||
countrefs();
|
||||
return(YES);
|
||||
}
|
||||
|
||||
/* display search progress with default custom format */
|
||||
|
||||
void
|
||||
progress(char *what, long current, long max)
|
||||
{
|
||||
static long start;
|
||||
long now;
|
||||
char msg[MSGLEN + 1];
|
||||
int i;
|
||||
|
||||
/* save the start time */
|
||||
if (searchcount == 0) {
|
||||
start = time(NULL);
|
||||
}
|
||||
if ((now = time(NULL)) - start >= 1)
|
||||
{
|
||||
if (linemode == NO)
|
||||
{
|
||||
wmove(body, MSGLINE, 0);
|
||||
clrtoeol();
|
||||
waddstr(body, what);
|
||||
snprintf(msg, sizeof(msg), "%ld", current);
|
||||
wmove(body, MSGLINE, (COLS / 2) - (strlen(msg) / 2));
|
||||
waddstr(body, msg);
|
||||
snprintf(msg, sizeof(msg), "%ld", max);
|
||||
wmove(body, MSGLINE, COLS - strlen(msg));
|
||||
waddstr(body, msg);
|
||||
refresh();
|
||||
}
|
||||
else if (verbosemode == YES)
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "> %s %ld of %ld", what, current, max);
|
||||
}
|
||||
|
||||
start = now;
|
||||
if ((linemode == NO) && (incurses == YES))
|
||||
{
|
||||
wmove(body, MSGLINE, 0);
|
||||
i = (float)COLS * (float)current / (float)max;
|
||||
|
||||
standout();
|
||||
for (; i > 0; i--)
|
||||
waddch(body, inch());
|
||||
standend();
|
||||
refresh();
|
||||
}
|
||||
else
|
||||
if (linemode == NO || verbosemode == YES)
|
||||
postmsg(msg);
|
||||
}
|
||||
++searchcount;
|
||||
}
|
||||
|
||||
/* print error message on system call failure */
|
||||
|
||||
void
|
||||
myperror(char *text)
|
||||
{
|
||||
char msg[MSGLEN + 1]; /* message */
|
||||
char *s;
|
||||
|
||||
s = strerror(errno);
|
||||
|
||||
(void) snprintf(msg, sizeof(msg), "%s: %s", text, s);
|
||||
postmsg(msg);
|
||||
}
|
||||
|
||||
/* postmsg clears the message line and prints the message */
|
||||
|
||||
/* VARARGS */
|
||||
void
|
||||
postmsg(char *msg)
|
||||
{
|
||||
if (linemode == YES || incurses == NO) {
|
||||
(void) printf("%s\n", msg);
|
||||
fflush(stdout);
|
||||
}
|
||||
else {
|
||||
clearmsg();
|
||||
waddstr(body, msg);
|
||||
refresh();
|
||||
}
|
||||
(void) strncpy(lastmsg, msg, sizeof(lastmsg) - 1);
|
||||
}
|
||||
|
||||
/* clearmsg clears the first message line */
|
||||
|
||||
void
|
||||
clearmsg(void)
|
||||
{
|
||||
if (linemode == NO) {
|
||||
wmove(body, MSGLINE, 0);
|
||||
clrtoeol();
|
||||
}
|
||||
}
|
||||
|
||||
/* clearmsg2 clears the second message line */
|
||||
|
||||
void
|
||||
clearmsg2(void)
|
||||
{
|
||||
if (linemode == NO) {
|
||||
wmove(body, MSGLINE + 1, 0);
|
||||
clrtoeol();
|
||||
}
|
||||
}
|
||||
|
||||
/* postmsg2 clears the second message line and prints the message */
|
||||
|
||||
void
|
||||
postmsg2(char *msg)
|
||||
{
|
||||
if (linemode == YES) {
|
||||
(void) printf("%s\n", msg);
|
||||
}
|
||||
else {
|
||||
clearmsg2();
|
||||
waddstr(body, msg);
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/* display an error mesg - stdout or on second msg line */
|
||||
void
|
||||
posterr(char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char errbuf[MSGLEN];
|
||||
|
||||
va_start(ap, msg);
|
||||
if (linemode == YES || incurses == NO)
|
||||
{
|
||||
(void) vfprintf(stderr, msg, ap);
|
||||
(void) fputc('\n', stderr);
|
||||
} else {
|
||||
vsnprintf(errbuf, sizeof(errbuf), msg, ap);
|
||||
postmsg2(errbuf);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* display a fatal error mesg -- stderr *after* shutting down curses */
|
||||
void
|
||||
postfatal(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char errbuf[MSGLEN];
|
||||
|
||||
va_start(ap, msg);
|
||||
vsnprintf(errbuf, sizeof(errbuf), msg, ap);
|
||||
/* restore the terminal to its original mode */
|
||||
if (incurses == YES) {
|
||||
exitcurses();
|
||||
}
|
||||
|
||||
/* display fatal error messages */
|
||||
fprintf(stderr,"%s",errbuf);
|
||||
|
||||
/* shut down */
|
||||
myexit(1);
|
||||
}
|
||||
|
||||
/* position references found file at specified line */
|
||||
|
||||
void
|
||||
seekline(unsigned int line)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* verify that there is a references found file */
|
||||
if (refsfound == NULL) {
|
||||
return;
|
||||
}
|
||||
/* go to the beginning of the file */
|
||||
rewind(refsfound);
|
||||
|
||||
/* find the requested line */
|
||||
nextline = 1;
|
||||
while (nextline < line && (c = getc(refsfound)) != EOF) {
|
||||
if (c == '\n') {
|
||||
nextline++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get the OGS subsystem and book names */
|
||||
|
||||
void
|
||||
ogsnames(char *file, char **subsystem, char **book)
|
||||
{
|
||||
static char buf[PATHLEN + 1];
|
||||
char *s, *slash;
|
||||
|
||||
*subsystem = *book = "";
|
||||
(void) strcpy(buf,file);
|
||||
s = buf;
|
||||
if (*s == '/') {
|
||||
++s;
|
||||
}
|
||||
while ((slash = strchr(s, '/')) != NULL) {
|
||||
*slash = '\0';
|
||||
if ((int)strlen(s) >= 3 && strncmp(slash - 3, ".ss", 3) == 0) {
|
||||
*subsystem = s;
|
||||
s = slash + 1;
|
||||
if ((slash = strchr(s, '/')) != NULL) {
|
||||
*book = s;
|
||||
*slash = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
s = slash + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the requested path components */
|
||||
|
||||
char *
|
||||
pathcomponents(char *path, int components)
|
||||
{
|
||||
int i;
|
||||
char *s;
|
||||
|
||||
s = path + strlen(path) - 1;
|
||||
for (i = 0; i < components; ++i) {
|
||||
while (s > path && *--s != '/') {
|
||||
;
|
||||
}
|
||||
}
|
||||
if (s > path && *s == '/') {
|
||||
++s;
|
||||
}
|
||||
return(s);
|
||||
}
|
||||
|
||||
/* open the references found file for writing */
|
||||
|
||||
BOOL
|
||||
writerefsfound(void)
|
||||
{
|
||||
if (refsfound == NULL) {
|
||||
if ((refsfound = myfopen(temp1, "wb")) == NULL) {
|
||||
cannotopen(temp1);
|
||||
return(NO);
|
||||
}
|
||||
} else {
|
||||
(void) fclose(refsfound);
|
||||
if ( (refsfound = myfopen(temp1, "wb")) == NULL) {
|
||||
postmsg("Cannot reopen temporary file");
|
||||
return(NO);
|
||||
}
|
||||
}
|
||||
return(YES);
|
||||
}
|
137
src/edit.c
Normal file
137
src/edit.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* file editing functions
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
|
||||
#include <ncurses.h>
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
|
||||
/* edit this displayed reference */
|
||||
|
||||
void
|
||||
editref(int i)
|
||||
{
|
||||
char file[PATHLEN + 1]; /* file name */
|
||||
char linenum[NUMLEN + 1]; /* line number */
|
||||
|
||||
/* verify that there is a references found file */
|
||||
if (refsfound == NULL) {
|
||||
return;
|
||||
}
|
||||
/* get the selected line */
|
||||
seekline(i + topline);
|
||||
|
||||
/* get the file name and line number */
|
||||
if (fscanf(refsfound, "%" PATHLEN_STR "s%*s%" NUMLEN_STR "s", file, linenum) == 2) {
|
||||
edit(file, linenum); /* edit it */
|
||||
}
|
||||
seekline(topline); /* restore the line pointer */
|
||||
}
|
||||
|
||||
/* edit all references */
|
||||
|
||||
void
|
||||
editall(void)
|
||||
{
|
||||
char file[PATHLEN + 1]; /* file name */
|
||||
char linenum[NUMLEN + 1]; /* line number */
|
||||
int c;
|
||||
|
||||
/* verify that there is a references found file */
|
||||
if (refsfound == NULL) {
|
||||
return;
|
||||
}
|
||||
/* get the first line */
|
||||
seekline(1);
|
||||
|
||||
/* get each file name and line number */
|
||||
while (fscanf(refsfound, "%" PATHLEN_STR "s%*s%" NUMLEN_STR "s%*[^\n]", file, linenum) == 2) {
|
||||
edit(file, linenum); /* edit it */
|
||||
if (editallprompt == YES) {
|
||||
addstr("Type ^D to stop editing all lines, or any other character to continue: ");
|
||||
if ((c = mygetch()) == EOF || c == ctrl('D') || c == ctrl('Z')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
seekline(topline);
|
||||
}
|
||||
|
||||
/* call the editor */
|
||||
|
||||
void
|
||||
edit(char *file, char *linenum)
|
||||
{
|
||||
char msg[MSGLEN + 1]; /* message */
|
||||
char plusnum[NUMLEN + 20]; /* line number option: allow space for wordy line# flag */
|
||||
char *s;
|
||||
|
||||
file = filepath(file);
|
||||
(void) snprintf(msg, sizeof(msg), "%s +%s %s", basename(editor), linenum, file);
|
||||
postmsg(msg);
|
||||
(void) snprintf(plusnum, sizeof(plusnum), lineflag, linenum);
|
||||
/* if this is the more or page commands */
|
||||
if (strcmp(s = basename(editor), "more") == 0 || strcmp(s, "page") == 0) {
|
||||
|
||||
/* get it to pause after displaying a file smaller than the screen
|
||||
length */
|
||||
(void) execute(editor, editor, plusnum, file, "/dev/null", NULL);
|
||||
}
|
||||
else if (lineflagafterfile) {
|
||||
(void) execute(editor, editor, file, plusnum, NULL);
|
||||
}
|
||||
else {
|
||||
(void) execute(editor, editor, plusnum, file, NULL);
|
||||
}
|
||||
clear(); /* redisplay screen */
|
||||
}
|
||||
|
||||
/* if requested, prepend a path to a relative file name */
|
||||
|
||||
char *
|
||||
filepath(char *file)
|
||||
{
|
||||
static char path[PATHLEN + 1];
|
||||
|
||||
if (prependpath != NULL && *file != '/') {
|
||||
(void) snprintf(path, sizeof(path), "%s/%s", prependpath, file);
|
||||
file = path;
|
||||
}
|
||||
return(file);
|
||||
}
|
2053
src/egrep.c
Normal file
2053
src/egrep.c
Normal file
File diff suppressed because it is too large
Load Diff
98
src/egrep.h
Normal file
98
src/egrep.h
Normal file
@ -0,0 +1,98 @@
|
||||
/* A Bison parser, made by GNU Bison 3.8.2. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
|
||||
especially those whose name start with YY_ or yy_. They are
|
||||
private implementation details that can be changed or removed. */
|
||||
|
||||
#ifndef YY_YY_EGREP_H_INCLUDED
|
||||
# define YY_YY_EGREP_H_INCLUDED
|
||||
/* Debug traces. */
|
||||
#ifndef YYDEBUG
|
||||
# define YYDEBUG 0
|
||||
#endif
|
||||
#if YYDEBUG
|
||||
extern int yydebug;
|
||||
#endif
|
||||
|
||||
/* Token kinds. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
enum yytokentype
|
||||
{
|
||||
YYEMPTY = -2,
|
||||
YYEOF = 0, /* "end of file" */
|
||||
YYerror = 256, /* error */
|
||||
YYUNDEF = 257, /* "invalid token" */
|
||||
CHAR = 258, /* CHAR */
|
||||
DOT = 259, /* DOT */
|
||||
CCL = 260, /* CCL */
|
||||
NCCL = 261, /* NCCL */
|
||||
OR = 262, /* OR */
|
||||
CAT = 263, /* CAT */
|
||||
STAR = 264, /* STAR */
|
||||
PLUS = 265, /* PLUS */
|
||||
QUEST = 266 /* QUEST */
|
||||
};
|
||||
typedef enum yytokentype yytoken_kind_t;
|
||||
#endif
|
||||
/* Token kinds. */
|
||||
#define YYEMPTY -2
|
||||
#define YYEOF 0
|
||||
#define YYerror 256
|
||||
#define YYUNDEF 257
|
||||
#define CHAR 258
|
||||
#define DOT 259
|
||||
#define CCL 260
|
||||
#define NCCL 261
|
||||
#define OR 262
|
||||
#define CAT 263
|
||||
#define STAR 264
|
||||
#define PLUS 265
|
||||
#define QUEST 266
|
||||
|
||||
/* Value type. */
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef int YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
#endif
|
||||
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
|
||||
int yyparse (void);
|
||||
|
||||
|
||||
#endif /* !YY_YY_EGREP_H_INCLUDED */
|
663
src/egrep.y
Normal file
663
src/egrep.y
Normal file
@ -0,0 +1,663 @@
|
||||
%{
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/*
|
||||
* egrep -- fine lines containing a regular expression
|
||||
*/
|
||||
%}
|
||||
|
||||
%token CHAR DOT CCL NCCL OR CAT STAR PLUS QUEST
|
||||
%left OR
|
||||
%left CHAR DOT CCL NCCL '('
|
||||
%left CAT
|
||||
%left STAR PLUS QUEST
|
||||
|
||||
%{
|
||||
#include "global.h"
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <setjmp.h> /* jmp_buf */
|
||||
|
||||
#define nextch() (*input++)
|
||||
|
||||
#define MAXLIN 350
|
||||
#define MAXPOS 4000
|
||||
#define NCHARS 256
|
||||
#define NSTATES 128
|
||||
#define FINAL -1
|
||||
static char gotofn[NSTATES][NCHARS];
|
||||
static int state[NSTATES];
|
||||
static char out[NSTATES];
|
||||
static unsigned int line;
|
||||
static int name[MAXLIN];
|
||||
static unsigned int left[MAXLIN];
|
||||
static unsigned int right[MAXLIN];
|
||||
static unsigned int parent[MAXLIN];
|
||||
static int foll[MAXLIN];
|
||||
static int positions[MAXPOS];
|
||||
static char chars[MAXLIN];
|
||||
static int nxtpos;
|
||||
static int nxtchar;
|
||||
static int tmpstat[MAXLIN];
|
||||
static int initstat[MAXLIN];
|
||||
static int xstate;
|
||||
static int count;
|
||||
static int icount;
|
||||
static char *input;
|
||||
static long lnum;
|
||||
static int iflag;
|
||||
static jmp_buf env; /* setjmp/longjmp buffer */
|
||||
static char *message; /* error message */
|
||||
|
||||
/* Internal prototypes: */
|
||||
static void cfoll(int v);
|
||||
static void cgotofn(void);
|
||||
static int cstate(int v);
|
||||
static int member(int symb, int set, int torf);
|
||||
static int notin(int n);
|
||||
static void synerror(void);
|
||||
static void overflo(void);
|
||||
static void add(int *array, int n);
|
||||
static void follow(unsigned int v);
|
||||
static int unary(int x, int d);
|
||||
static int node(int x, int l, int r);
|
||||
static unsigned int cclenter(int x);
|
||||
static unsigned int enter(int x);
|
||||
|
||||
static int yylex(void);
|
||||
static int yyerror(char *);
|
||||
%}
|
||||
|
||||
%%
|
||||
s: t
|
||||
{ unary(FINAL, $1);
|
||||
line--;
|
||||
}
|
||||
;
|
||||
t: b r
|
||||
{ $$ = node(CAT, $1, $2); }
|
||||
| OR b r OR
|
||||
{ $$ = node(CAT, $2, $3); }
|
||||
| OR b r
|
||||
{ $$ = node(CAT, $2, $3); }
|
||||
| b r OR
|
||||
{ $$ = node(CAT, $1, $2); }
|
||||
;
|
||||
b:
|
||||
{ $$ = enter(DOT);
|
||||
$$ = unary(STAR, $$); }
|
||||
;
|
||||
r: CHAR
|
||||
{ $$ = enter($1); }
|
||||
| DOT
|
||||
{ $$ = enter(DOT); }
|
||||
| CCL
|
||||
{ $$ = cclenter(CCL); }
|
||||
| NCCL
|
||||
{ $$ = cclenter(NCCL); }
|
||||
;
|
||||
|
||||
r: r OR r
|
||||
{ $$ = node(OR, $1, $3); }
|
||||
| r r %prec CAT
|
||||
{ $$ = node(CAT, $1, $2); }
|
||||
| r STAR
|
||||
{ $$ = unary(STAR, $1); }
|
||||
| r PLUS
|
||||
{ $$ = unary(PLUS, $1); }
|
||||
| r QUEST
|
||||
{ $$ = unary(QUEST, $1); }
|
||||
| '(' r ')'
|
||||
{ $$ = $2; }
|
||||
| error
|
||||
;
|
||||
|
||||
%%
|
||||
static int
|
||||
yyerror(char *s)
|
||||
{
|
||||
message = s;
|
||||
longjmp(env, 1);
|
||||
return 1; /* silence a warning */
|
||||
}
|
||||
|
||||
static int
|
||||
yylex(void)
|
||||
{
|
||||
int cclcnt, x;
|
||||
char c, d;
|
||||
|
||||
switch(c = nextch()) {
|
||||
case '|':
|
||||
case '\n':
|
||||
return (OR);
|
||||
case '*':
|
||||
return (STAR);
|
||||
case '+':
|
||||
return (PLUS);
|
||||
case '?':
|
||||
return (QUEST);
|
||||
case '(':
|
||||
case ')':
|
||||
return (c);
|
||||
case '.':
|
||||
return (DOT);
|
||||
case '\0':
|
||||
return (0);
|
||||
case '[':
|
||||
x = CCL;
|
||||
cclcnt = 0;
|
||||
count = nxtchar++;
|
||||
if ((c = nextch()) == '^') {
|
||||
x = NCCL;
|
||||
c = nextch();
|
||||
}
|
||||
do {
|
||||
if (c == '\0')
|
||||
synerror();
|
||||
if ( (c == '-')
|
||||
&& (cclcnt > 0)
|
||||
&& (chars[nxtchar-1] != 0)
|
||||
) {
|
||||
if ((d = nextch()) != 0) {
|
||||
c = chars[nxtchar-1];
|
||||
while ((unsigned int)c < (unsigned int)d) {
|
||||
if (nxtchar >= MAXLIN)
|
||||
overflo();
|
||||
chars[nxtchar++] = ++c;
|
||||
cclcnt++;
|
||||
}
|
||||
continue;
|
||||
} /* if() */
|
||||
} /* if() */
|
||||
if (nxtchar >= MAXLIN)
|
||||
overflo();
|
||||
chars[nxtchar++] = c;
|
||||
cclcnt++;
|
||||
} while ((c = nextch()) != ']');
|
||||
chars[count] = cclcnt;
|
||||
return (x);
|
||||
case '\\':
|
||||
if ((c = nextch()) == '\0')
|
||||
synerror();
|
||||
yylval = c;
|
||||
return (CHAR);
|
||||
case '$':
|
||||
case '^':
|
||||
c = '\n';
|
||||
yylval = c;
|
||||
return (CHAR);
|
||||
default:
|
||||
yylval = c;
|
||||
return (CHAR);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
synerror(void)
|
||||
{
|
||||
yyerror("Syntax error");
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
enter(int x)
|
||||
{
|
||||
if(line >= MAXLIN)
|
||||
overflo();
|
||||
name[line] = x;
|
||||
left[line] = 0;
|
||||
right[line] = 0;
|
||||
return(line++);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
cclenter(int x)
|
||||
{
|
||||
unsigned int linno;
|
||||
|
||||
linno = enter(x);
|
||||
right[linno] = count;
|
||||
return (linno);
|
||||
}
|
||||
|
||||
static int
|
||||
node(int x, int l, int r)
|
||||
{
|
||||
if(line >= MAXLIN)
|
||||
overflo();
|
||||
name[line] = x;
|
||||
left[line] = l;
|
||||
right[line] = r;
|
||||
parent[l] = line;
|
||||
parent[r] = line;
|
||||
return(line++);
|
||||
}
|
||||
|
||||
static int
|
||||
unary(int x, int d)
|
||||
{
|
||||
if(line >= MAXLIN)
|
||||
overflo();
|
||||
name[line] = x;
|
||||
left[line] = d;
|
||||
right[line] = 0;
|
||||
parent[d] = line;
|
||||
return(line++);
|
||||
}
|
||||
|
||||
static void
|
||||
overflo(void)
|
||||
{
|
||||
yyerror("internal table overflow");
|
||||
}
|
||||
|
||||
static void
|
||||
cfoll(int v)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (left[v] == 0) {
|
||||
count = 0;
|
||||
for (i = 1; i <= line; i++)
|
||||
tmpstat[i] = 0;
|
||||
follow(v);
|
||||
add(foll, v);
|
||||
} else if (right[v] == 0)
|
||||
cfoll(left[v]);
|
||||
else {
|
||||
cfoll(left[v]);
|
||||
cfoll(right[v]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cgotofn(void)
|
||||
{
|
||||
unsigned int i, n, s;
|
||||
int c, k;
|
||||
char symbol[NCHARS];
|
||||
unsigned int j, l, pc, pos;
|
||||
unsigned int nc;
|
||||
int curpos;
|
||||
unsigned int num, number, newpos;
|
||||
|
||||
count = 0;
|
||||
for (n=3; n<=line; n++)
|
||||
tmpstat[n] = 0;
|
||||
if (cstate(line-1)==0) {
|
||||
tmpstat[line] = 1;
|
||||
count++;
|
||||
out[0] = 1;
|
||||
}
|
||||
for (n=3; n<=line; n++)
|
||||
initstat[n] = tmpstat[n];
|
||||
count--; /*leave out position 1 */
|
||||
icount = count;
|
||||
tmpstat[1] = 0;
|
||||
add(state, 0);
|
||||
n = 0;
|
||||
for (s = 0; s <= n; s++) {
|
||||
if (out[s] == 1)
|
||||
continue;
|
||||
for (i = 0; i < NCHARS; i++)
|
||||
symbol[i] = 0;
|
||||
num = positions[state[s]];
|
||||
count = icount;
|
||||
for (i = 3; i <= line; i++)
|
||||
tmpstat[i] = initstat[i];
|
||||
pos = state[s] + 1;
|
||||
for (i = 0; i < num; i++) {
|
||||
curpos = positions[pos];
|
||||
if ((c = name[curpos]) >= 0) {
|
||||
if (c < NCHARS) {
|
||||
symbol[c] = 1;
|
||||
} else if (c == DOT) {
|
||||
for (k = 0; k < NCHARS; k++)
|
||||
if (k != '\n')
|
||||
symbol[k] = 1;
|
||||
} else if (c == CCL) {
|
||||
nc = chars[right[curpos]];
|
||||
pc = right[curpos] + 1;
|
||||
for (j = 0; j < nc; j++)
|
||||
symbol[(unsigned char)chars[pc++]] = 1;
|
||||
} else if (c == NCCL) {
|
||||
nc = chars[right[curpos]];
|
||||
for (j = 0; j < NCHARS; j++) {
|
||||
pc = right[curpos] + 1;
|
||||
for (l = 0; l < nc; l++)
|
||||
if (j==(unsigned char)chars[pc++])
|
||||
goto cont;
|
||||
if (j != '\n')
|
||||
symbol[j] = 1;
|
||||
cont:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
} /* for (i) */
|
||||
for (c=0; c<NCHARS; c++) {
|
||||
if (symbol[c] == 1) {
|
||||
/* nextstate(s,c) */
|
||||
count = icount;
|
||||
for (i=3; i <= line; i++)
|
||||
tmpstat[i] = initstat[i];
|
||||
pos = state[s] + 1;
|
||||
for (i=0; i<num; i++) {
|
||||
curpos = positions[pos];
|
||||
if ((k = name[curpos]) >= 0)
|
||||
if ((k == c)
|
||||
|| (k == DOT)
|
||||
|| (k == CCL && member(c, right[curpos], 1))
|
||||
|| (k == NCCL && member(c, right[curpos], 0))
|
||||
) {
|
||||
number = positions[foll[curpos]];
|
||||
newpos = foll[curpos] + 1;
|
||||
for (j = 0; j < number; j++) {
|
||||
if (tmpstat[positions[newpos]] != 1) {
|
||||
tmpstat[positions[newpos]] = 1;
|
||||
count++;
|
||||
}
|
||||
newpos++;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
} /* end nextstate */
|
||||
if (notin(n)) {
|
||||
if (n >= NSTATES)
|
||||
overflo();
|
||||
add(state, ++n);
|
||||
if (tmpstat[line] == 1)
|
||||
out[n] = 1;
|
||||
gotofn[s][c] = n;
|
||||
} else {
|
||||
gotofn[s][c] = xstate;
|
||||
}
|
||||
} /* if (symbol) */
|
||||
} /* for(c) */
|
||||
} /* for(s) */
|
||||
}
|
||||
|
||||
static int
|
||||
cstate(int v)
|
||||
{
|
||||
int b;
|
||||
if (left[v] == 0) {
|
||||
if (tmpstat[v] != 1) {
|
||||
tmpstat[v] = 1;
|
||||
count++;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
else if (right[v] == 0) {
|
||||
if (cstate(left[v]) == 0) return (0);
|
||||
else if (name[v] == PLUS) return (1);
|
||||
else return (0);
|
||||
}
|
||||
else if (name[v] == CAT) {
|
||||
if (cstate(left[v]) == 0 && cstate(right[v]) == 0) return (0);
|
||||
else return (1);
|
||||
}
|
||||
else { /* name[v] == OR */
|
||||
b = cstate(right[v]);
|
||||
if (cstate(left[v]) == 0 || b == 0) return (0);
|
||||
else return (1);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
member(int symb, int set, int torf)
|
||||
{
|
||||
unsigned int i, num, pos;
|
||||
|
||||
num = chars[set];
|
||||
pos = set + 1;
|
||||
for (i = 0; i < num; i++)
|
||||
if (symb == (unsigned char)(chars[pos++]))
|
||||
return (torf);
|
||||
return (!torf);
|
||||
}
|
||||
|
||||
static int
|
||||
notin(int n)
|
||||
{
|
||||
int i, j, pos;
|
||||
for (i=0; i<=n; i++) {
|
||||
if (positions[state[i]] == count) {
|
||||
pos = state[i] + 1;
|
||||
for (j=0; j < count; j++)
|
||||
if (tmpstat[positions[pos++]] != 1) goto nxt;
|
||||
xstate = i;
|
||||
return (0);
|
||||
}
|
||||
nxt: ;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
add(int *array, int n)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (nxtpos + count > MAXPOS)
|
||||
overflo();
|
||||
array[n] = nxtpos;
|
||||
positions[nxtpos++] = count;
|
||||
for (i=3; i <= line; i++) {
|
||||
if (tmpstat[i] == 1) {
|
||||
positions[nxtpos++] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
follow(unsigned int v)
|
||||
{
|
||||
unsigned int p;
|
||||
|
||||
if (v == line)
|
||||
return;
|
||||
p = parent[v];
|
||||
switch(name[p]) {
|
||||
case STAR:
|
||||
case PLUS: cstate(v);
|
||||
follow(p);
|
||||
return;
|
||||
|
||||
case OR:
|
||||
case QUEST: follow(p);
|
||||
return;
|
||||
|
||||
case CAT:
|
||||
if (v == left[p]) {
|
||||
if (cstate(right[p]) == 0) {
|
||||
follow(p);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
follow(p);
|
||||
return;
|
||||
case FINAL:
|
||||
if (tmpstat[line] != 1) {
|
||||
tmpstat[line] = 1;
|
||||
count++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
egrepinit(char *egreppat)
|
||||
{
|
||||
/* initialize the global data */
|
||||
memset(gotofn, 0, sizeof(gotofn));
|
||||
memset(state, 0, sizeof(state));
|
||||
memset(out, 0, sizeof(out));
|
||||
line = 1;
|
||||
memset(name, 0, sizeof(name));
|
||||
memset(left, 0, sizeof(left));
|
||||
memset(right, 0, sizeof(right));
|
||||
memset(parent, 0, sizeof(parent));
|
||||
memset(foll, 0, sizeof(foll));
|
||||
memset(positions, 0, sizeof(positions));
|
||||
memset(chars, 0, sizeof(chars));
|
||||
nxtpos = 0;
|
||||
nxtchar = 0;
|
||||
memset(tmpstat, 0, sizeof(tmpstat));
|
||||
memset(initstat, 0, sizeof(initstat));
|
||||
xstate = 0;
|
||||
count = 0;
|
||||
icount = 0;
|
||||
input = egreppat;
|
||||
message = NULL;
|
||||
if (setjmp(env) == 0) {
|
||||
yyparse();
|
||||
cfoll(line-1);
|
||||
cgotofn();
|
||||
}
|
||||
return(message);
|
||||
}
|
||||
|
||||
static char buf[2 * BUFSIZ];
|
||||
static const char *buf_end = buf + (sizeof(buf) / sizeof(*buf));
|
||||
|
||||
static size_t read_next_chunk(char **p, FILE *fptr)
|
||||
{
|
||||
if (*p <= (buf + BUFSIZ)) {
|
||||
/* bwlow the middle, so enough space left for one entire BUFSIZ */
|
||||
return fread(*p, sizeof(**p), BUFSIZ, fptr);
|
||||
} else if (*p == buf_end) {
|
||||
/* exactly at end ... wrap around and use lower half */
|
||||
*p = buf;
|
||||
return fread(*p, sizeof(**p), BUFSIZ, fptr);
|
||||
}
|
||||
/* somewhere in second half, so do a limited read */
|
||||
return fread(*p, sizeof(**p), buf_end - *p, fptr);
|
||||
}
|
||||
|
||||
int
|
||||
egrep(char *file, FILE *output, char *format)
|
||||
{
|
||||
char *p;
|
||||
unsigned int cstat;
|
||||
int ccount;
|
||||
char *nlp;
|
||||
unsigned int istat;
|
||||
int in_line;
|
||||
FILE *fptr;
|
||||
|
||||
if ((fptr = myfopen(file, "r")) == NULL)
|
||||
return(-1);
|
||||
|
||||
lnum = 1;
|
||||
p = buf;
|
||||
nlp = p;
|
||||
ccount = read_next_chunk(&p, fptr);
|
||||
|
||||
if (ccount <= 0) {
|
||||
fclose(fptr);
|
||||
return(0);
|
||||
}
|
||||
in_line = 1;
|
||||
istat = cstat = (unsigned int) gotofn[0]['\n'];
|
||||
if (out[cstat])
|
||||
goto found;
|
||||
for (;;) {
|
||||
if (!iflag) {
|
||||
/* all input chars made positive */
|
||||
cstat = (unsigned int) gotofn[cstat][(unsigned char)*p];
|
||||
} else {
|
||||
/* for -i option*/
|
||||
cstat = (unsigned int) gotofn[cstat][tolower((unsigned char)*p)];
|
||||
}
|
||||
if (out[cstat]) {
|
||||
found:
|
||||
for(;;) {
|
||||
if (*p++ == '\n') {
|
||||
in_line = 0;
|
||||
succeed:
|
||||
fprintf(output, format, file, lnum);
|
||||
if (p <= nlp) {
|
||||
while (nlp < buf_end)
|
||||
putc(*nlp++, output);
|
||||
nlp = buf;
|
||||
}
|
||||
while (nlp < p)
|
||||
putc(*nlp++, output);
|
||||
lnum++;
|
||||
nlp = p;
|
||||
if (out[cstat = istat] == 0)
|
||||
goto brk2;
|
||||
} /* if (p++ == \n) */
|
||||
cfound:
|
||||
if (--ccount <= 0) {
|
||||
ccount = read_next_chunk(&p, fptr);
|
||||
if (ccount <= 0) {
|
||||
if (in_line) {
|
||||
in_line = 0;
|
||||
goto succeed;
|
||||
}
|
||||
fclose(fptr);
|
||||
return(0);
|
||||
}
|
||||
} /* if(ccount <= 0) */
|
||||
in_line = 1;
|
||||
} /* for(ever) */
|
||||
} /* if(out[cstat]) */
|
||||
|
||||
if (*p++ == '\n') {
|
||||
in_line = 0;
|
||||
lnum++;
|
||||
nlp = p;
|
||||
if (out[(cstat=istat)])
|
||||
goto cfound;
|
||||
}
|
||||
brk2:
|
||||
if (--ccount <= 0) {
|
||||
ccount = read_next_chunk(&p, fptr);
|
||||
if (ccount <= 0)
|
||||
break;
|
||||
}
|
||||
in_line = 1;
|
||||
}
|
||||
fclose(fptr);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
egrepcaseless(int i)
|
||||
{
|
||||
iflag = i; /* simulate "egrep -i" */
|
||||
}
|
188
src/exec.c
Normal file
188
src/exec.c
Normal file
@ -0,0 +1,188 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* process execution functions
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "global.h"
|
||||
#include <stdarg.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h> /* pid_t */
|
||||
#ifdef __DJGPP__
|
||||
#include <process.h>
|
||||
#endif
|
||||
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
|
||||
#include <ncurses.h>
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
|
||||
static sighandler_t oldsigquit; /* old value of quit signal */
|
||||
static sighandler_t oldsighup; /* old value of hangup signal */
|
||||
static sighandler_t oldsigtstp; /* old value of SIGTSTP */
|
||||
|
||||
#ifndef __MSDOS__ /* none of these is needed, there */
|
||||
static int join(pid_t p);
|
||||
static int myexecvp(char *a, char **args);
|
||||
static pid_t myfork(void);
|
||||
#endif
|
||||
|
||||
/* execute forks and executes a program or shell script, waits for it to
|
||||
* finish, and returns its exit code.
|
||||
*/
|
||||
|
||||
/*VARARGS1*/
|
||||
int
|
||||
execute(char *a, ...) /* note: "exec" is already defined on u370 */
|
||||
{
|
||||
va_list ap;
|
||||
int exitcode = -1; /* initialize, to avoid warning */
|
||||
char *argv[BUFSIZ];
|
||||
pid_t p;
|
||||
|
||||
/* fork and exec the program or shell script */
|
||||
endwin(); /* restore the terminal modes */
|
||||
mousecleanup();
|
||||
fflush(stdout);
|
||||
va_start(ap, a);
|
||||
for (p = 0; (argv[p] = va_arg(ap, char *)) != 0; p++)
|
||||
;
|
||||
#ifdef __MSDOS__
|
||||
/* HBB 20010313: in MSDOG, everything is completely different.
|
||||
* No fork()/exec()/wait(), but rather a single libc call: */
|
||||
exitcode = spawnvp(P_WAIT, a, argv);
|
||||
#else
|
||||
if ((p = myfork()) == 0) {
|
||||
myexecvp(a, argv); /* child */
|
||||
}
|
||||
else {
|
||||
exitcode = join(p); /* parent */
|
||||
}
|
||||
#endif /* MSDOS */
|
||||
|
||||
/* the menu and scrollbar may be changed by the command executed */
|
||||
#if UNIXPC || !TERMINFO
|
||||
# ifndef __DJGPP__ /* leave CRLF handling as is */
|
||||
nonl();
|
||||
# endif
|
||||
raw(); /* endwin() turns off cbreak mode so restore it */
|
||||
noecho();
|
||||
#endif
|
||||
mousemenu();
|
||||
drawscrollbar(topline, nextline);
|
||||
va_end(ap);
|
||||
return(exitcode);
|
||||
}
|
||||
|
||||
#ifndef __MSDOS__ /* None of the following functions is used there */
|
||||
|
||||
/* myexecvp is an interface to the execvp system call to
|
||||
* modify argv[0] to reference the last component of its path-name.
|
||||
*/
|
||||
static int
|
||||
myexecvp(char *a, char **args)
|
||||
{
|
||||
char msg[MSGLEN + 1];
|
||||
|
||||
/* modify argv[0] to reference the last component of its path name */
|
||||
args[0] = basename(args[0]);
|
||||
|
||||
/* execute the program or shell script */
|
||||
execvp(a, args); /* returns only on failure */
|
||||
snprintf(msg, sizeof(msg), "\nCannot exec %s", a);
|
||||
perror(msg); /* display the reason */
|
||||
askforreturn(); /* wait until the user sees the message */
|
||||
myexit(1); /* exit the child */
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* myfork acts like fork but also handles signals */
|
||||
|
||||
static pid_t
|
||||
myfork(void)
|
||||
{
|
||||
pid_t p; /* process number */
|
||||
|
||||
p = fork();
|
||||
|
||||
/* the parent ignores the interrupt, quit, and hangup signals */
|
||||
if (p > 0) {
|
||||
oldsigquit = signal(SIGQUIT, SIG_IGN);
|
||||
oldsighup = signal(SIGHUP, SIG_IGN);
|
||||
#ifdef SIGTSTP
|
||||
oldsigtstp = signal(SIGTSTP, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
/* so they can be used to stop the child */
|
||||
else if (p == 0) {
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGQUIT, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
/* check for fork failure */
|
||||
if (p == -1) {
|
||||
myperror("Cannot fork");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* join is the compliment of fork */
|
||||
|
||||
static int
|
||||
join(pid_t p)
|
||||
{
|
||||
int status = -1;
|
||||
pid_t w;
|
||||
|
||||
/* wait for the correct child to exit */
|
||||
do {
|
||||
w = wait(&status);
|
||||
} while (p != -1 && w != p);
|
||||
|
||||
/* restore signal handling */
|
||||
signal(SIGQUIT, oldsigquit);
|
||||
signal(SIGHUP, oldsighup);
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, oldsigtstp);
|
||||
#endif
|
||||
|
||||
/* return the child's exit code */
|
||||
return(status >> 8);
|
||||
}
|
||||
|
||||
#endif /* !MSDOS */
|
1301
src/find.c
Normal file
1301
src/find.c
Normal file
File diff suppressed because it is too large
Load Diff
904
src/fscanner.l
Normal file
904
src/fscanner.l
Normal file
@ -0,0 +1,904 @@
|
||||
%{
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* C symbol scanner
|
||||
*/
|
||||
#include "global.h"
|
||||
|
||||
#include "scanner.h"
|
||||
#include "lookup.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* the line counting has been moved from character reading for speed */
|
||||
/* comments are discarded */
|
||||
|
||||
#ifndef FLEX_SCANNER
|
||||
# error Sorry, this scanner needs flex. It is not usable with AT&T Lex.
|
||||
#endif
|
||||
|
||||
#define IFLEVELINC 5 /* #if nesting level size increment */
|
||||
#define YY_NO_TOP_STATE 1
|
||||
|
||||
int first; /* buffer index for first char of symbol */
|
||||
int last; /* buffer index for last char of symbol */
|
||||
int lineno; /* symbol line number */
|
||||
int myylineno = 1;
|
||||
|
||||
/* HBB 20001007: new variables, emulating yytext in a way that allows
|
||||
* the yymore() simulation, my_yymore(), to be used even in the presence of
|
||||
* yyless(). */
|
||||
size_t my_yyleng = 0;
|
||||
char *my_yytext = NULL;
|
||||
|
||||
static BOOL arraydimension; /* inside array dimension declaration */
|
||||
static BOOL bplisting; /* breakpoint listing */
|
||||
static int braces; /* unmatched left brace count */
|
||||
static BOOL classdef; /* c++ class definition */
|
||||
static BOOL elseelif; /* #else or #elif found */
|
||||
static BOOL esudef; /* enum/struct/union global definition */
|
||||
static BOOL external; /* external definition */
|
||||
static int externalbraces; /* external definition outer brace count */
|
||||
static BOOL fcndef; /* function definition */
|
||||
static BOOL global; /* file global scope (outside functions) */
|
||||
static size_t iflevel; /* #if nesting level */
|
||||
static BOOL initializer; /* data initializer */
|
||||
static int initializerbraces; /* data initializer outer brace count */
|
||||
static BOOL lex; /* lex file */
|
||||
static size_t miflevel = IFLEVELINC; /* maximum #if nesting level */
|
||||
static int *maxifbraces; /* maximum brace count within #if */
|
||||
static int *preifbraces; /* brace count before #if */
|
||||
static int parens; /* unmatched left parenthesis count */
|
||||
static BOOL ppdefine; /* preprocessor define statement */
|
||||
static BOOL pseudoelif; /* pseudo-#elif */
|
||||
static BOOL oldtype; /* next identifier is an old type */
|
||||
static BOOL rules; /* lex/yacc rules */
|
||||
static BOOL sdl; /* sdl file */
|
||||
static BOOL structfield; /* structure field declaration */
|
||||
static int tagdef; /* class/enum/struct/union tag definition */
|
||||
static BOOL template; /* function template */
|
||||
static int templateparens; /* function template outer parentheses count */
|
||||
static int typedefbraces = -1; /* initial typedef brace count */
|
||||
static int token; /* token found */
|
||||
static int ident_start; /* begin of preceding identifier */
|
||||
|
||||
static void my_yymore(void);
|
||||
|
||||
%}
|
||||
identifier [a-zA-Z_$][a-zA-Z_0-9$]*
|
||||
number \.?[0-9][.0-9a-fA-FlLuUxX]*
|
||||
comment "/*"([^*]*("*"+[^/])?)*"*/"|"//"[^\n]*\n
|
||||
ws [ \t\r\v\f]
|
||||
wsnl [ \t\r\v\f\n]|{comment}
|
||||
|
||||
/* flex options: stack of start conditions, and don't use yywrap() */
|
||||
%option stack
|
||||
%option noyywrap
|
||||
|
||||
%start SDL
|
||||
%a 4000
|
||||
%o 7000
|
||||
|
||||
/* exclusive start conditions. not available in AT&T lex -> use flex! */
|
||||
%x IN_PREPROC WAS_ENDIF WAS_IDENTIFIER WAS_ESU IN_DQUOTE IN_SQUOTE COMMENT
|
||||
|
||||
%%
|
||||
|
||||
%\{ { /* lex/yacc C declarations/definitions */
|
||||
global = YES;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
%\} {
|
||||
global = NO;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
^%% { /* lex/yacc rules delimiter */
|
||||
braces = 0;
|
||||
if (rules == NO) {
|
||||
/* this %% starts the section containing the rules */
|
||||
rules = YES;
|
||||
|
||||
/* Copy yytext to private buffer, to be able to add further
|
||||
* content following it: */
|
||||
my_yymore();
|
||||
|
||||
/* simulate a yylex() or yyparse() definition */
|
||||
(void) strcat(my_yytext, " /* ");
|
||||
first = strlen(my_yytext);
|
||||
if (lex == YES) {
|
||||
(void) strcat(my_yytext, "yylex");
|
||||
} else {
|
||||
/* yacc: yyparse implicitly calls yylex */
|
||||
char *s = " yylex()";
|
||||
char *cp = s + strlen(s);
|
||||
while (--cp >= s) {
|
||||
unput(*cp);
|
||||
}
|
||||
(void) strcat(my_yytext, "yyparse");
|
||||
}
|
||||
last = strlen(my_yytext);
|
||||
(void) strcat(my_yytext, " */");
|
||||
my_yyleng = strlen(my_yytext);
|
||||
return(FCNDEF);
|
||||
} else {
|
||||
/* were in the rules section, now comes the closing one */
|
||||
rules = NO;
|
||||
global = YES;
|
||||
last = first;
|
||||
my_yymore();
|
||||
return(FCNEND);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
<SDL>STATE[ \t]+({identifier}|\*) { /* sdl state, treat as function def */
|
||||
braces = 1;
|
||||
fcndef = YES;
|
||||
token = FCNDEF;
|
||||
goto findident;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<SDL>ENDSTATE[ \t] { /* end of an sdl state, treat as end of a function */
|
||||
goto endstate;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
\{ { /* count unmatched left braces for fcn def detection */
|
||||
++braces;
|
||||
|
||||
/* mark an untagged enum/struct/union so its beginning
|
||||
can be found */
|
||||
if (tagdef) {
|
||||
if (braces == 1) {
|
||||
esudef = YES;
|
||||
}
|
||||
token = tagdef;
|
||||
tagdef = '\0';
|
||||
last = first;
|
||||
my_yymore();
|
||||
return(token);
|
||||
}
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
\#{ws}* { /* start a preprocessor line */
|
||||
if (rules == NO) /* don't consider CPP for lex/yacc rules */
|
||||
BEGIN(IN_PREPROC);
|
||||
yyleng = 1; /* get rid of the blanks, if any */
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<IN_PREPROC>endif([^a-zA-Z0-9_$\n].*)? { /* #endif */
|
||||
/* delay treatment of #endif depending on whether an
|
||||
* #if comes right after it, or not */
|
||||
/* HBB 20010619: new pattern allows trailing garbage
|
||||
* after the #endif */
|
||||
BEGIN(WAS_ENDIF);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<WAS_ENDIF>\n{wsnl}*#{ws}*if(ndef|def)?{ws}+ {
|
||||
/* attempt to correct erroneous brace count caused by:
|
||||
*
|
||||
* #if ...
|
||||
* ... {
|
||||
* #endif
|
||||
* #if ...
|
||||
* ... {
|
||||
* #endif
|
||||
*/
|
||||
/* the current #if must not have an #else or #elif */
|
||||
if (elseelif == YES) {
|
||||
goto endif;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
pseudoelif = YES;
|
||||
BEGIN(INITIAL);
|
||||
yyless(1); /* rescan all but the line ending */
|
||||
yy_set_bol(1);
|
||||
goto eol;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<WAS_ENDIF>\n{wsnl}* { /* an #endif with no #if right after it */
|
||||
endif:
|
||||
if (iflevel > 0) {
|
||||
/* get the maximum brace count for this #if */
|
||||
if (braces < maxifbraces[--iflevel]) {
|
||||
braces = maxifbraces[iflevel];
|
||||
}
|
||||
}
|
||||
BEGIN(INITIAL);
|
||||
yyless(1);
|
||||
yy_set_bol(1);
|
||||
goto eol;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
<IN_PREPROC>ifndef{ws}+ |
|
||||
<IN_PREPROC>ifdef{ws}+ |
|
||||
<IN_PREPROC>if{ws}+ { /* #if directive */
|
||||
elseelif = NO;
|
||||
if (pseudoelif == YES) {
|
||||
pseudoelif = NO;
|
||||
goto elif;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/* make sure there is room for the current brace count */
|
||||
if (iflevel == miflevel) {
|
||||
miflevel += IFLEVELINC;
|
||||
maxifbraces = realloc(maxifbraces, miflevel * sizeof(*maxifbraces));
|
||||
preifbraces = realloc(preifbraces, miflevel * sizeof(*preifbraces));
|
||||
}
|
||||
/* push the current brace count */
|
||||
preifbraces[iflevel] = braces;
|
||||
maxifbraces[iflevel++] = 0;
|
||||
BEGIN(INITIAL);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<IN_PREPROC>else({ws}.*)? { /* #else --- eat up whole line */
|
||||
elseelif = YES;
|
||||
if (iflevel > 0) {
|
||||
|
||||
/* save the maximum brace count for this #if */
|
||||
if (braces > maxifbraces[iflevel - 1]) {
|
||||
maxifbraces[iflevel - 1] = braces;
|
||||
}
|
||||
/* restore the brace count to before the #if */
|
||||
braces = preifbraces[iflevel - 1];
|
||||
}
|
||||
BEGIN(INITIAL);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<IN_PREPROC>elif{ws}+ { /* #elif */
|
||||
/* elseelif = YES; --- HBB I doubt this is correct */
|
||||
elif:
|
||||
if (iflevel > 0) {
|
||||
|
||||
/* save the maximum brace count for this #if */
|
||||
if (braces > maxifbraces[iflevel - 1]) {
|
||||
maxifbraces[iflevel - 1] = braces;
|
||||
}
|
||||
/* restore the brace count to before the #if */
|
||||
braces = preifbraces[iflevel - 1];
|
||||
}
|
||||
BEGIN(INITIAL);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
<IN_PREPROC>include{ws}*\"[^"\n]+\" |
|
||||
<IN_PREPROC>include{ws}*<[^>\n]+> { /* #include file */
|
||||
char *s;
|
||||
char remember = yytext[yyleng-1];
|
||||
|
||||
my_yymore();
|
||||
s = strpbrk(my_yytext, "\"<");
|
||||
if (!s)
|
||||
return(LEXERR);
|
||||
my_yytext[my_yyleng-1] = '\0';
|
||||
incfile(s + 1, s);
|
||||
my_yytext[my_yyleng-1] = remember;
|
||||
first = s - my_yytext;
|
||||
last = my_yyleng - 1;
|
||||
if (compress == YES) {
|
||||
my_yytext[0] = '\2'; /* compress the keyword */
|
||||
}
|
||||
BEGIN(INITIAL);
|
||||
return(INCLUDE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
\} {
|
||||
/* could be the last enum member initializer */
|
||||
if (braces == initializerbraces) {
|
||||
initializerbraces = -1;
|
||||
initializer = NO;
|
||||
}
|
||||
if (--braces <= 0) {
|
||||
endstate:
|
||||
braces = 0;
|
||||
classdef = NO;
|
||||
}
|
||||
if (braces == 0 || (braces == 1 && classdef == YES)) {
|
||||
|
||||
/* if the end of an enum/struct/union definition */
|
||||
if (esudef == YES) {
|
||||
esudef = NO;
|
||||
}
|
||||
/* if the end of the function */
|
||||
else if (fcndef == YES) {
|
||||
fcndef = NO;
|
||||
last = first;
|
||||
my_yymore();
|
||||
return(FCNEND);
|
||||
}
|
||||
}
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
\( { /* count unmatched left parentheses for function templates */
|
||||
++parens;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
\) {
|
||||
if (--parens <= 0) {
|
||||
parens = 0;
|
||||
}
|
||||
/* if the end of a function template */
|
||||
if (parens == templateparens) {
|
||||
templateparens = -1;
|
||||
template = NO;
|
||||
}
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
= { /* if a global definition initializer */
|
||||
if (!my_yytext)
|
||||
return(LEXERR);
|
||||
if (global == YES && ppdefine == NO && my_yytext[0] != '#') {
|
||||
initializerbraces = braces;
|
||||
initializer = YES;
|
||||
}
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
: { /* a if global structure field */
|
||||
if (!my_yytext)
|
||||
return(LEXERR);
|
||||
if (global == YES && ppdefine == NO && my_yytext[0] != '#') {
|
||||
structfield = YES;
|
||||
}
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
\, {
|
||||
if (braces == initializerbraces) {
|
||||
initializerbraces = -1;
|
||||
initializer = NO;
|
||||
}
|
||||
structfield = NO;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
; { /* if the enum/struct/union was not a definition */
|
||||
if (braces == 0) {
|
||||
esudef = NO;
|
||||
}
|
||||
/* if the end of a typedef */
|
||||
if (braces == typedefbraces) {
|
||||
typedefbraces = -1;
|
||||
}
|
||||
/* if the end of a external definition */
|
||||
if (braces == externalbraces) {
|
||||
externalbraces = -1;
|
||||
external = NO;
|
||||
}
|
||||
structfield = NO;
|
||||
initializer = NO;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<IN_PREPROC>define{ws}+{identifier} {
|
||||
|
||||
/* preprocessor macro or constant definition */
|
||||
ppdefine = YES;
|
||||
token = DEFINE;
|
||||
if (compress == YES) {
|
||||
my_yytext[0] = '\1'; /* compress the keyword */
|
||||
}
|
||||
findident:
|
||||
/* search backwards through yytext[] to find the identifier */
|
||||
/* NOTE: this had better be left to flex, by use of
|
||||
* yet another starting condition */
|
||||
my_yymore();
|
||||
first = my_yyleng - 1;
|
||||
while (my_yytext[first] != ' ' && my_yytext[first] != '\t') {
|
||||
--first;
|
||||
}
|
||||
++first;
|
||||
last = my_yyleng;
|
||||
BEGIN(INITIAL);
|
||||
goto definition;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<IN_PREPROC>\n { /* unknown preprocessor line */
|
||||
BEGIN(INITIAL);
|
||||
++myylineno;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<IN_PREPROC>. |
|
||||
<IN_PREPROC>{identifier} { /* unknown preprocessor line */
|
||||
BEGIN(INITIAL);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
class{wsnl}+{identifier}({wsnl}|{identifier}|[():])*\{ { /* class definition */
|
||||
classdef = YES;
|
||||
tagdef = 'c';
|
||||
yyless(5); /* eat up 'class', and re-scan */
|
||||
yy_set_bol(0);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
("enum"|"struct"|"union") {
|
||||
ident_start = first;
|
||||
BEGIN(WAS_ESU);
|
||||
goto more;
|
||||
}
|
||||
<WAS_ESU>{
|
||||
({wsnl}+{identifier}){wsnl}*\{ { /* e/s/u definition */
|
||||
tagdef = my_yytext[ident_start];
|
||||
BEGIN(WAS_IDENTIFIER);
|
||||
goto ident;
|
||||
}
|
||||
{wsnl}*\{ { /* e/s/u definition without a tag */
|
||||
tagdef = my_yytext[ident_start];
|
||||
BEGIN(INITIAL);
|
||||
if (braces == 0) {
|
||||
esudef = YES;
|
||||
}
|
||||
last = first;
|
||||
yyless(0); /* re-scan all this as normal text */
|
||||
tagdef = '\0';
|
||||
goto more;
|
||||
}
|
||||
({wsnl}+{identifier})?{wsnl}* |
|
||||
.|\n { /* e/s/u usage */
|
||||
BEGIN(WAS_IDENTIFIER);
|
||||
goto ident;
|
||||
}
|
||||
}
|
||||
|
||||
if{wsnl}*\( { /* ignore 'if' */
|
||||
yyless(2);
|
||||
yy_set_bol(0);
|
||||
goto more;
|
||||
}
|
||||
|
||||
{identifier} { /* identifier found: do nothing, yet. (!) */
|
||||
BEGIN(WAS_IDENTIFIER);
|
||||
ident_start = first;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
<WAS_IDENTIFIER>{
|
||||
{ws}*\(({wsnl}|{identifier}|{number}|[*&[\]=,.:])*\)([()]|{wsnl})*[:a-zA-Z_#{] {
|
||||
/* a function definition */
|
||||
/* note: "#define a (b) {" and "#if defined(a)\n#"
|
||||
* are not fcn definitions! */
|
||||
/* warning: "if (...)" must not overflow yytext,
|
||||
* so the content of function argument definitions
|
||||
* is restricted, in particular parentheses are
|
||||
* not allowed */
|
||||
/* FIXME HBB 20001003: the above 'not allowed' may well be the
|
||||
* reason for the parsing bug concerning function pointer usage,
|
||||
* I suspect. --- I think my new special-case rule for 'if'
|
||||
* could be helpful in removing that limitation */
|
||||
if ((braces == 0 && ppdefine == NO && my_yytext[0] != '#' && rules == NO) ||
|
||||
(braces == 1 && classdef == YES)) {
|
||||
fcndef = YES;
|
||||
token = FCNDEF;
|
||||
goto fcn;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
goto fcncal;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
{ws}*\(([*&[\]=,.]|{identifier}|{number}|{wsnl})* { /* function call */
|
||||
fcncal: if (fcndef == YES || ppdefine == YES || rules == YES) {
|
||||
token = FCNCALL;
|
||||
goto fcn;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
if (template == NO) {
|
||||
templateparens = parens;
|
||||
template = YES;
|
||||
}
|
||||
goto ident;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
("*"|{wsnl})+{identifier} { /* typedef name or modifier use */
|
||||
goto ident;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
.|\n { /* general identifer usage */
|
||||
char *s;
|
||||
|
||||
if (global == YES && ppdefine == NO && my_yytext[0] != '#' &&
|
||||
external == NO && initializer == NO &&
|
||||
arraydimension == NO && structfield == NO &&
|
||||
template == NO && fcndef == NO) {
|
||||
if (esudef == YES) {
|
||||
/* if enum/struct/union */
|
||||
token = MEMBERDEF;
|
||||
} else {
|
||||
token = GLOBALDEF;
|
||||
}
|
||||
} else {
|
||||
ident:
|
||||
token = IDENT;
|
||||
}
|
||||
fcn:
|
||||
if (YYSTATE == WAS_IDENTIFIER) {
|
||||
/* Position back to the actual identifier: */
|
||||
last = first;
|
||||
first = ident_start;
|
||||
yyless(0);
|
||||
/* HBB 20001008: if the anti-backup-pattern above matched,
|
||||
* and the matched context ended with a \n, then the scanner
|
||||
* believes it's at the start of a new line. But the yyless()
|
||||
* should feeds that \n back into the input, so that's
|
||||
* wrong. --> force 'beginning-of-line' status off. */
|
||||
yy_set_bol(0);
|
||||
BEGIN(INITIAL);
|
||||
} else {
|
||||
my_yymore();
|
||||
last = my_yyleng;
|
||||
}
|
||||
definition:
|
||||
|
||||
/* if a long line */
|
||||
if (yyleng > STMTMAX) {
|
||||
int c;
|
||||
|
||||
/* skip to the end of the line */
|
||||
warning("line too long");
|
||||
while ((c = input()) > LEXEOF) {
|
||||
if (c == '\n') {
|
||||
unput(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* truncate a long symbol */
|
||||
if (yyleng > PATLEN) {
|
||||
warning("symbol too long");
|
||||
my_yyleng = first + PATLEN;
|
||||
my_yytext[my_yyleng] = '\0';
|
||||
}
|
||||
|
||||
/* if found word was a keyword: */
|
||||
if ((s = lookup(my_yytext + first)) != NULL) {
|
||||
first = my_yyleng;
|
||||
|
||||
/* if the start of a typedef */
|
||||
if (s == typedeftext) {
|
||||
typedefbraces = braces;
|
||||
oldtype = YES;
|
||||
}
|
||||
/* if an enum/struct/union */
|
||||
/* (needed for "typedef struct tag name;" so
|
||||
tag isn't marked as the typedef name) */
|
||||
else if (s == enumtext || s == structtext || s == uniontext) {
|
||||
/* do nothing */
|
||||
} else if (s == externtext) {
|
||||
/* if an external definition */
|
||||
externalbraces = braces;
|
||||
external = YES;
|
||||
} else if (templateparens == parens && template == YES) {
|
||||
/* keyword doesn't start a function
|
||||
* template */
|
||||
templateparens = -1;
|
||||
template = NO;
|
||||
} else {
|
||||
/* identifier after typedef was a
|
||||
* keyword */
|
||||
oldtype = NO;
|
||||
}
|
||||
} else {
|
||||
/* not a keyword --> found an identifier */
|
||||
/* last = yyleng; */
|
||||
|
||||
/* if a class/enum/struct/union tag definition */
|
||||
/* FIXME HBB 20001001: why reject "class"? */
|
||||
if (tagdef && strnotequal(my_yytext + first, "class")) {
|
||||
token = tagdef;
|
||||
tagdef = '\0';
|
||||
if (braces == 0) {
|
||||
esudef = YES;
|
||||
}
|
||||
} else if (braces == typedefbraces && oldtype == NO &&
|
||||
arraydimension == NO) {
|
||||
/* if a typedef name */
|
||||
token = TYPEDEF;
|
||||
} else {
|
||||
oldtype = NO;
|
||||
}
|
||||
/* my_yymore(); */
|
||||
return(token);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\[ { /* array dimension (don't worry or about subscripts) */
|
||||
arraydimension = YES;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
\] {
|
||||
arraydimension = NO;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
\\\n { /* preprocessor statement is continued on next line */
|
||||
/* save the '\\' to the output file, but not the '\n': */
|
||||
yyleng = 1;
|
||||
my_yymore();
|
||||
goto eol;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
\n { /* end of the line */
|
||||
if (ppdefine == YES) { /* end of a #define */
|
||||
ppdefine = NO;
|
||||
yyless(yyleng - 1);
|
||||
last = first;
|
||||
my_yymore();
|
||||
return(DEFINEEND);
|
||||
}
|
||||
/* skip the first 8 columns of a breakpoint listing line */
|
||||
/* and skip the file path in the page header */
|
||||
if (bplisting == YES) {
|
||||
int c, i;
|
||||
|
||||
/* FIXME HBB 20001007: should call input() instead */
|
||||
switch (input()) { /* tab and EOF just fall through */
|
||||
case ' ': /* breakpoint number line */
|
||||
case '[':
|
||||
for (i = 1; i < 8 && input() > LEXEOF; ++i)
|
||||
;
|
||||
break;
|
||||
case '.': /* header line */
|
||||
case '/':
|
||||
/* skip to the end of the line */
|
||||
while ((c = input()) > LEXEOF) {
|
||||
if (c == '\n') {
|
||||
unput(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '\n': /* empty line */
|
||||
unput('\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
eol:
|
||||
++myylineno;
|
||||
first = 0;
|
||||
last = 0;
|
||||
if (symbols > 0) {
|
||||
/* no my_yymore(): \n doesn't need to be in my_yytext */
|
||||
return(NEWLINE);
|
||||
}
|
||||
/* line ended --> flush my_yytext */
|
||||
if (my_yytext)
|
||||
*my_yytext = '\0';
|
||||
my_yyleng = 0;
|
||||
lineno = myylineno;
|
||||
}
|
||||
|
||||
\' { /* character constant */
|
||||
if (sdl == NO)
|
||||
BEGIN(IN_SQUOTE);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<IN_SQUOTE>\' {
|
||||
BEGIN(INITIAL);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
\" { /* string constant */
|
||||
BEGIN(IN_DQUOTE);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<IN_DQUOTE>\" {
|
||||
BEGIN(INITIAL);
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
<IN_DQUOTE,IN_SQUOTE>{
|
||||
\n { /* syntax error: unexpected EOL */
|
||||
BEGIN(INITIAL);
|
||||
goto eol;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
\\. |
|
||||
. {
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
\\\n { /* line continuation inside a string! */
|
||||
myylineno++;
|
||||
goto more;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
^{ws}+ { /* don't save leading white space */
|
||||
}
|
||||
|
||||
{ws}+\n { /* eat whitespace at end of line */
|
||||
unput('\n');
|
||||
}
|
||||
|
||||
[\t\r\v\f]+ { /* eat non-blank whitespace sequences, replace
|
||||
* by single blank */
|
||||
unput(' ');
|
||||
}
|
||||
|
||||
{ws}{2,} { /* compress sequential whitespace here, not in putcrossref() */
|
||||
unput(' ');
|
||||
}
|
||||
|
||||
"/*" yy_push_state(COMMENT);
|
||||
<COMMENT>{
|
||||
[^*\n]* |
|
||||
"*"+[^*/\n]* ; /* do nothing */
|
||||
[^*\n]*\n |
|
||||
"*"+[^*/\n]*\n {
|
||||
if (ppdefine == NO) {
|
||||
goto eol;
|
||||
} else {
|
||||
++myylineno;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
"*"+"/" {
|
||||
/* replace the comment by a single blank */
|
||||
unput(' ');
|
||||
yy_pop_state();
|
||||
}
|
||||
}
|
||||
|
||||
"//".*\n? {
|
||||
/* C++-style one-line comment */
|
||||
goto eol;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
{number} | /* number */
|
||||
<SDL>STATE[ \t]+ | /* ... and other syntax error catchers... */
|
||||
. { /* punctuation and operators */
|
||||
more:
|
||||
my_yymore();
|
||||
first = my_yyleng;
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
void
|
||||
initscanner(char *srcfile)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (maxifbraces == NULL) {
|
||||
maxifbraces = malloc(miflevel * sizeof(*maxifbraces));
|
||||
preifbraces = malloc(miflevel * sizeof(*preifbraces));
|
||||
}
|
||||
first = 0; /* buffer index for first char of symbol */
|
||||
last = 0; /* buffer index for last char of symbol */
|
||||
lineno = 1; /* symbol line number */
|
||||
myylineno = 1; /* input line number */
|
||||
arraydimension = NO; /* inside array dimension declaration */
|
||||
bplisting = NO; /* breakpoint listing */
|
||||
braces = 0; /* unmatched left brace count */
|
||||
classdef = NO; /* c++ class definition */
|
||||
elseelif = NO; /* #else or #elif found */
|
||||
esudef = NO; /* enum/struct/union global definition */
|
||||
external = NO; /* external definition */
|
||||
externalbraces = -1; /* external definition outer brace count */
|
||||
fcndef = NO; /* function definition */
|
||||
global = YES; /* file global scope (outside functions) */
|
||||
iflevel = 0; /* #if nesting level */
|
||||
initializer = NO; /* data initializer */
|
||||
initializerbraces = -1; /* data initializer outer brace count */
|
||||
lex = NO; /* lex file */
|
||||
parens = 0; /* unmatched left parenthesis count */
|
||||
ppdefine = NO; /* preprocessor define statement */
|
||||
pseudoelif = NO; /* pseudo-#elif */
|
||||
oldtype = NO; /* next identifier is an old type */
|
||||
rules = NO; /* lex/yacc rules */
|
||||
sdl = NO; /* sdl file */
|
||||
structfield = NO; /* structure field declaration */
|
||||
tagdef = '\0'; /* class/enum/struct/union tag definition */
|
||||
template = NO; /* function template */
|
||||
templateparens = -1; /* function template outer parentheses count */
|
||||
typedefbraces = -1; /* initial typedef braces count */
|
||||
ident_start = 0; /* start of previously found identifier */
|
||||
|
||||
if (my_yytext)
|
||||
*my_yytext = '\0';
|
||||
my_yyleng = 0;
|
||||
|
||||
BEGIN(INITIAL);
|
||||
|
||||
/* if this is not a C file */
|
||||
if ((s = strrchr(srcfile, '.')) != NULL) {
|
||||
switch (*++s) { /* this switch saves time on C files */
|
||||
case 'b':
|
||||
if (strcmp(s, "bp") == 0) { /* breakpoint listing */
|
||||
bplisting = YES;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (strcmp(s, "l") == 0) { /* lex */
|
||||
lex = YES;
|
||||
global = NO;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if (strcmp(s, "sd") == 0) { /* sdl */
|
||||
sdl = YES;
|
||||
BEGIN(SDL);
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
if (strcmp(s, "y") == 0) { /* yacc */
|
||||
global = NO;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MY_YY_ALLOCSTEP 1000
|
||||
static void
|
||||
my_yymore(void)
|
||||
{
|
||||
static size_t yytext_size = 0;
|
||||
|
||||
/* my_yytext is an ever-growing buffer. It will not ever
|
||||
* shrink, nor will it be freed at end of program, for now */
|
||||
while (my_yyleng + yyleng + 1 >= yytext_size) {
|
||||
my_yytext = realloc(my_yytext, yytext_size += MY_YY_ALLOCSTEP);
|
||||
}
|
||||
|
||||
strncpy (my_yytext + my_yyleng, yytext, yyleng+1);
|
||||
my_yyleng += yyleng;
|
||||
}
|
321
src/global.h
Normal file
321
src/global.h
Normal file
@ -0,0 +1,321 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* global type, data, and function definitions
|
||||
*/
|
||||
|
||||
#ifndef CSCOPE_GLOBAL_H
|
||||
#define CSCOPE_GLOBAL_H
|
||||
|
||||
//#include "config.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h> /* isalpha, isdigit, etc. */
|
||||
#include <signal.h> /* SIGINT and SIGQUIT */
|
||||
#include <stdio.h> /* standard I/O package */
|
||||
#include <stdlib.h> /* standard library functions */
|
||||
|
||||
#include <string.h> /* string functions */
|
||||
|
||||
#include "constants.h" /* misc. constants */
|
||||
#include "invlib.h" /* inverted index library */
|
||||
#include "library.h" /* library function return values */
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
typedef enum { /* boolean data type */
|
||||
NO,
|
||||
YES
|
||||
} BOOL;
|
||||
|
||||
typedef enum { /* findinit return code */
|
||||
NOERROR,
|
||||
NOTSYMBOL,
|
||||
REGCMPERROR
|
||||
} FINDINIT;
|
||||
|
||||
typedef struct { /* mouse action */
|
||||
int button;
|
||||
int percent;
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
int y2;
|
||||
} MOUSE;
|
||||
|
||||
struct cmd { /* command history struct */
|
||||
struct cmd *prev, *next; /* list ptrs */
|
||||
int field; /* input field number */
|
||||
char *text; /* input field text */
|
||||
};
|
||||
|
||||
#ifndef R_OK
|
||||
# define READ R_OK
|
||||
#else
|
||||
# define READ 4
|
||||
#endif
|
||||
#ifdef W_OK
|
||||
# define WRITE W_OK
|
||||
#else
|
||||
# define WRITE 2
|
||||
#endif
|
||||
|
||||
#define O_TEXT 0x00
|
||||
#define O_BINARY 0x00
|
||||
|
||||
#ifndef DFLT_INCDIR
|
||||
# define DFLT_INCDIR "/usr/include"
|
||||
#endif
|
||||
|
||||
/* digraph data for text compression */
|
||||
extern char dichar1[]; /* 16 most frequent first chars */
|
||||
extern char dichar2[]; /* 8 most frequent second chars
|
||||
using the above as first chars */
|
||||
extern char dicode1[]; /* digraph first character code */
|
||||
extern char dicode2[]; /* digraph second character code */
|
||||
|
||||
/* and some macros to help using dicodes: */
|
||||
/* Check if a given pair of chars is compressable as a dicode: */
|
||||
#define IS_A_DICODE(inchar1, inchar2) \
|
||||
(dicode1[(unsigned char)(inchar1)] && dicode2[(unsigned char)(inchar2)])
|
||||
/* Combine the pair into a dicode */
|
||||
#define DICODE_COMPRESS(inchar1, inchar2) \
|
||||
((0200 - 2) + dicode1[(unsigned char)(inchar1)] \
|
||||
+ dicode2[(unsigned char)(inchar2)])
|
||||
|
||||
/* main.c global data */
|
||||
extern char *editor, *home, *shell, *lineflag; /* environment variables */
|
||||
extern char *home; /* Home directory */
|
||||
extern BOOL lineflagafterfile;
|
||||
extern char *argv0; /* command name */
|
||||
extern BOOL compress; /* compress the characters in the crossref */
|
||||
extern BOOL dbtruncated; /* database symbols truncated to 8 chars */
|
||||
extern int dispcomponents; /* file path components to display */
|
||||
#if CCS
|
||||
extern BOOL displayversion; /* display the C Compilation System version */
|
||||
#endif
|
||||
extern BOOL editallprompt; /* prompt between editing files */
|
||||
extern unsigned int fileargc; /* file argument count */
|
||||
extern char **fileargv; /* file argument values */
|
||||
extern int fileversion; /* cross-reference file version */
|
||||
extern BOOL incurses; /* in curses */
|
||||
extern BOOL invertedindex; /* the database has an inverted index */
|
||||
extern BOOL isuptodate; /* consider the crossref up-to-date */
|
||||
extern BOOL kernelmode; /* don't use DFLT_INCDIR - bad for kernels */
|
||||
extern BOOL linemode; /* use line oriented user interface */
|
||||
extern BOOL verbosemode; /* print extra information on line mode */
|
||||
extern BOOL recurse_dir; /* recurse dirs when searching for src files */
|
||||
extern char *namefile; /* file of file names */
|
||||
extern BOOL ogs; /* display OGS book and subsystem names */
|
||||
extern char *prependpath; /* prepend path to file names */
|
||||
extern FILE *refsfound; /* references found file */
|
||||
extern char temp1[]; /* temporary file name */
|
||||
extern char temp2[]; /* temporary file name */
|
||||
extern long totalterms; /* total inverted index terms */
|
||||
extern BOOL trun_syms; /* truncate symbols to 8 characters */
|
||||
extern char tempstring[TEMPSTRING_LEN + 1]; /* global dummy string buffer */
|
||||
extern char *tmpdir; /* temporary directory */
|
||||
|
||||
/* command.c global data */
|
||||
extern BOOL caseless; /* ignore letter case when searching */
|
||||
extern BOOL *change; /* change this line */
|
||||
extern BOOL changing; /* changing text */
|
||||
extern int selecting;
|
||||
extern unsigned int curdispline;
|
||||
extern char newpat[]; /* new pattern */
|
||||
extern char Pattern[]; /* symbol or text pattern */
|
||||
|
||||
/* crossref.c global data */
|
||||
extern long dboffset; /* new database offset */
|
||||
extern BOOL errorsfound; /* prompt before clearing error messages */
|
||||
extern long lineoffset; /* source line database offset */
|
||||
extern long npostings; /* number of postings */
|
||||
extern unsigned long symbols; /* number of symbols */
|
||||
|
||||
/* dir.c global data */
|
||||
extern char currentdir[]; /* current directory */
|
||||
extern char **incdirs; /* #include directories */
|
||||
extern char **srcdirs; /* source directories */
|
||||
extern char **srcfiles; /* source files */
|
||||
extern unsigned long nincdirs; /* number of #include directories */
|
||||
extern unsigned long nsrcdirs; /* number of source directories */
|
||||
extern unsigned long nsrcfiles; /* number of source files */
|
||||
extern unsigned long msrcfiles; /* maximum number of source files */
|
||||
|
||||
/* display.c global data */
|
||||
extern int booklen; /* OGS book name display field length */
|
||||
extern int *displine; /* screen line of displayed reference */
|
||||
extern unsigned int disprefs; /* displayed references */
|
||||
extern int fcnlen; /* function name display field length */
|
||||
extern int field; /* input field */
|
||||
extern int filelen; /* file name display field length */
|
||||
extern unsigned fldcolumn; /* input field column */
|
||||
extern unsigned int mdisprefs; /* maximum displayed references */
|
||||
extern unsigned int nextline; /* next line to be shown */
|
||||
extern FILE *nonglobalrefs; /* non-global references file */
|
||||
extern int numlen; /* line number display field length */
|
||||
extern unsigned int topline; /* top line of page */
|
||||
extern int bottomline; /* bottom line of page */
|
||||
extern long searchcount; /* count of files searched */
|
||||
extern int subsystemlen; /* OGS subsystem name display field length */
|
||||
extern unsigned int totallines; /* total reference lines */
|
||||
extern const char dispchars[]; /* display chars for jumping to lines */
|
||||
|
||||
/* find.c global data */
|
||||
extern char block[]; /* cross-reference file block */
|
||||
extern char blockmark; /* mark character to be searched for */
|
||||
extern long blocknumber; /* block number */
|
||||
extern char *blockp; /* pointer to current character in block */
|
||||
extern int blocklen; /* length of disk block read */
|
||||
|
||||
/* lookup.c global data */
|
||||
extern struct keystruct {
|
||||
char *text;
|
||||
char delim;
|
||||
struct keystruct *next;
|
||||
} keyword[];
|
||||
|
||||
/* mouse.c global data */
|
||||
extern BOOL mouse; /* mouse interface */
|
||||
|
||||
#if UNIXPC
|
||||
extern BOOL unixpcmouse; /* UNIX PC mouse interface */
|
||||
#endif
|
||||
|
||||
/* cscope functions called from more than one function or between files */
|
||||
|
||||
char *filepath(char *file);
|
||||
char *findcalledby(char *pattern);
|
||||
char *findcalling(char *pattern);
|
||||
char *findallfcns(char *dummy);
|
||||
char *finddef(char *pattern);
|
||||
char *findfile(char *dummy);
|
||||
char *findinclude(char *pattern);
|
||||
char *findsymbol(char *pattern);
|
||||
char *findassign(char *pattern);
|
||||
char *findregexp(char *egreppat);
|
||||
char *findstring(char *pattern);
|
||||
char *inviewpath(char *file);
|
||||
char *lookup(char *ident);
|
||||
char *pathcomponents(char *path, int components);
|
||||
char *read_block(void);
|
||||
char *scanpast(char c);
|
||||
|
||||
char ** parse_options(int *argc, char **argv);
|
||||
void error_usage(void);
|
||||
void longusage(void);
|
||||
void usage(void);
|
||||
extern BOOL remove_symfile_onexit;
|
||||
extern BOOL onesearch; /* one search only in line mode */
|
||||
extern char *reflines; /* symbol reference lines file */
|
||||
|
||||
void addcmd(int f, char *s);
|
||||
void addsrcfile(char *path);
|
||||
void askforchar(void);
|
||||
void askforreturn(void);
|
||||
void atchange(void);
|
||||
void atfield(void);
|
||||
void cannotwrite(char *file);
|
||||
void cannotopen(char *file);
|
||||
void clearmsg(void);
|
||||
void clearmsg2(void);
|
||||
void countrefs(void);
|
||||
void crossref(char *srcfile);
|
||||
void dispinit(void);
|
||||
void display(void);
|
||||
void drawscrollbar(int top, int bot);
|
||||
void edit(char *file, char *linenum);
|
||||
void editall(void);
|
||||
void editref(int);
|
||||
void entercurses(void);
|
||||
void exitcurses(void);
|
||||
void findcleanup(void);
|
||||
void freesrclist(void);
|
||||
void freeinclist(void);
|
||||
void freecrossref(void);
|
||||
void freefilelist(void);
|
||||
void help(void);
|
||||
void incfile(char *file, char *type);
|
||||
void includedir(char *_dirname);
|
||||
void initsymtab(void);
|
||||
void makefilelist(void);
|
||||
void mousecleanup(void);
|
||||
void mousemenu(void);
|
||||
void mouseinit(void);
|
||||
void mousereinit(void);
|
||||
void myexit(int sig);
|
||||
void myperror(char *text);
|
||||
void ogsnames(char *file, char **subsystem, char **book);
|
||||
void progress(char *what, long current, long max);
|
||||
void putfilename(char *srcfile);
|
||||
void postmsg(char *msg);
|
||||
void postmsg2(char *msg);
|
||||
void posterr(char *msg,...);
|
||||
void postfatal(const char *msg,...);
|
||||
void putposting(char *term, int type);
|
||||
void fetch_string_from_dbase(char *, size_t);
|
||||
void resetcmd(void);
|
||||
void seekline(unsigned int line);
|
||||
void setfield(void);
|
||||
void shellpath(char *out, int limit, char *in);
|
||||
void sourcedir(char *dirlist);
|
||||
void myungetch(int c);
|
||||
void warning(char *text);
|
||||
void writestring(char *s);
|
||||
|
||||
BOOL command(int commandc);
|
||||
BOOL infilelist(char *file);
|
||||
BOOL readrefs(char *filename);
|
||||
BOOL search(void);
|
||||
BOOL writerefsfound(void);
|
||||
|
||||
FINDINIT findinit(char *pattern);
|
||||
MOUSE *getmouseaction(char leading_char);
|
||||
struct cmd *currentcmd(void);
|
||||
struct cmd *prevcmd(void);
|
||||
struct cmd *nextcmd(void);
|
||||
|
||||
int egrep(char *file, FILE *output, char *format);
|
||||
int mygetline(char p[], char s[], unsigned size, int firstchar, BOOL iscaseless);
|
||||
int mygetch(void);
|
||||
int hash(char *ss);
|
||||
int execute(char *a, ...);
|
||||
long dbseek(long offset);
|
||||
|
||||
|
||||
#endif /* CSCOPE_GLOBAL_H */
|
1
src/gscope.c
Normal file
1
src/gscope.c
Normal file
@ -0,0 +1 @@
|
||||
/* Placeholder file --- replace by real gscope.c if you have it */
|
209
src/help.c
Normal file
209
src/help.c
Normal file
@ -0,0 +1,209 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* display help
|
||||
*
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
|
||||
#include <ncurses.h>
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
/*
|
||||
max num of lines of help screen -
|
||||
this number needs to be increased if more than n help items are needed
|
||||
*/
|
||||
#define MAXHELP 50 /* maximum number of help strings */
|
||||
|
||||
void
|
||||
help(void)
|
||||
{
|
||||
char **ep, *s, **tp, *text[MAXHELP];
|
||||
int ln;
|
||||
|
||||
tp = text;
|
||||
if (changing == NO) {
|
||||
if (mouse) {
|
||||
*tp++ = "Point with the mouse and click button 1 to move to the desired input field,\n";
|
||||
*tp++ = "type the pattern to search for, and then press the RETURN key. For the first 4\n";
|
||||
*tp++ = "and last 2 input fields, the pattern can be a regcomp(3) regular expression.\n";
|
||||
*tp++ = "If the search is successful, you can edit the file containing a displayed line\n";
|
||||
*tp++ = "by pointing with the mouse and clicking button 1.\n";
|
||||
*tp++ = "\nYou can either use the button 2 menu or these single-character commands:\n\n";
|
||||
} else {
|
||||
*tp++ = "Press the RETURN key repeatedly to move to the desired input field, type the\n";
|
||||
*tp++ = "pattern to search for, and then press the RETURN key. For the first 4 and\n";
|
||||
*tp++ = "last 2 input fields, the pattern can be a regcomp(3) regular expression.\n";
|
||||
*tp++ = "If the search is successful, you can use these single-character commands:\n\n";
|
||||
*tp++ = "0-9a-zA-Z\tEdit the file containing the displayed line.\n";
|
||||
}
|
||||
*tp++ = "space bar\tDisplay next set of matching lines.\n";
|
||||
*tp++ = "+\t\tDisplay next set of matching lines.\n";
|
||||
*tp++ = "^V\t\tDisplay next set of matching lines.\n";
|
||||
*tp++ = "-\t\tDisplay previous set of matching lines.\n";
|
||||
*tp++ = "^E\t\tEdit all lines.\n";
|
||||
*tp++ = ">\t\tWrite the list of lines being displayed to a file.\n";
|
||||
*tp++ = ">>\t\tAppend the list of lines being displayed to a file.\n";
|
||||
*tp++ = "<\t\tRead lines from a file.\n";
|
||||
*tp++ = "^\t\tFilter all lines through a shell command.\n";
|
||||
*tp++ = "|\t\tPipe all lines to a shell command.\n";
|
||||
if (!mouse) {
|
||||
*tp++ = "\nAt any time you can use these single-character commands:\n\n";
|
||||
*tp++ = "TAB\t\tSwap positions between input and output areas.\n";
|
||||
*tp++ = "RETURN\t\tMove to the next input field.\n";
|
||||
*tp++ = "^N\t\tMove to the next input field.\n";
|
||||
*tp++ = "^P\t\tMove to the previous input field.\n";
|
||||
}
|
||||
*tp++ = "^Y / ^A\t\tSearch with the last pattern typed.\n";
|
||||
*tp++ = "^B\t\tRecall previous input field and search pattern.\n";
|
||||
*tp++ = "^F\t\tRecall next input field and search pattern.\n";
|
||||
if(caseless)
|
||||
*tp++ = "^C\t\tToggle ignore/use letter case when searching (IGNORE).\n";
|
||||
else
|
||||
*tp++ = "^C\t\tToggle ignore/use letter case when searching (USE).\n";
|
||||
*tp++ = "^R\t\tRebuild the cross-reference.\n";
|
||||
*tp++ = "!\t\tStart an interactive shell (type ^D to return to cscope).\n";
|
||||
*tp++ = "^L\t\tRedraw the screen.\n";
|
||||
*tp++ = "?\t\tDisplay this list of commands.\n";
|
||||
*tp++ = "^D\t\tExit cscope.\n";
|
||||
*tp++ = "\nNote: If the first character of the pattern you want to search for matches\n";
|
||||
*tp++ = "a command, type a \\ character first.\n";
|
||||
*tp++ = "Note: Some ctrl keys may be occupied by your terminal configuration.\n";
|
||||
} else {
|
||||
if (mouse) {
|
||||
*tp++ = "Point with the mouse and click button 1 to mark or unmark the line to be\n";
|
||||
*tp++ = "changed. You can also use the button 2 menu or these single-character\n";
|
||||
*tp++ = "commands:\n\n";
|
||||
}
|
||||
else {
|
||||
*tp++ = "When changing text, you can use these single-character commands:\n\n";
|
||||
*tp++ = "0-9a-zA-Z\tMark or unmark the line to be changed.\n";
|
||||
}
|
||||
*tp++ = "*\t\tMark or unmark all displayed lines to be changed.\n";
|
||||
*tp++ = "space bar\tDisplay next set of lines.\n";
|
||||
*tp++ = "+\t\tDisplay next set of lines.\n";
|
||||
*tp++ = "-\t\tDisplay previous set of lines.\n";
|
||||
*tp++ = "^A\t\tMark or unmark all lines to be changed.\n";
|
||||
*tp++ = "^D\t\tChange the marked lines and exit.\n";
|
||||
*tp++ = "ESC\t\tExit without changing the marked lines.\n";
|
||||
*tp++ = "!\t\tStart an interactive shell (type ^D to return to cscope).\n";
|
||||
*tp++ = "^L\t\tRedraw the screen.\n";
|
||||
*tp++ = "?\t\tDisplay this list of commands.\n";
|
||||
}
|
||||
/* print help, a screen at a time */
|
||||
ep = tp;
|
||||
ln = 0;
|
||||
for (tp = text; tp < ep; ) {
|
||||
if (ln < LINES - 1) {
|
||||
for (s = *tp; *s != '\0'; ++s) {
|
||||
if (*s == '\n') {
|
||||
++ln;
|
||||
}
|
||||
}
|
||||
(void) addstr(*tp++);
|
||||
}
|
||||
else {
|
||||
(void) addstr("\n");
|
||||
askforchar();
|
||||
(void) clear();
|
||||
ln = 0;
|
||||
}
|
||||
}
|
||||
if (ln) {
|
||||
(void) addstr("\n");
|
||||
askforchar();
|
||||
}
|
||||
}
|
||||
|
||||
/* error exit including short usage information */
|
||||
void
|
||||
error_usage(void)
|
||||
{
|
||||
usage();
|
||||
fprintf(stderr, "Try the -h option for more information.\n");
|
||||
myexit(1);
|
||||
}
|
||||
|
||||
/* normal usage message */
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: cscope [-bcCdehklLqRTuUvV] [-f file] [-F file] [-i file] [-I dir] [-s dir]\n");
|
||||
fprintf(stderr, " [-p number] [-P path] [-[0-8] pattern] [source files]\n");
|
||||
}
|
||||
|
||||
|
||||
/* long usage message */
|
||||
void
|
||||
longusage(void)
|
||||
{
|
||||
usage();
|
||||
fprintf(stderr, "\
|
||||
\n\
|
||||
-b Build the cross-reference only.\n\
|
||||
-C Ignore letter case when searching.\n\
|
||||
-c Use only ASCII characters in the cross-ref file (don't compress).\n\
|
||||
-d Do not update the cross-reference.\n\
|
||||
-e Suppress the <Ctrl>-e command prompt between files.\n\
|
||||
-F symfile Read symbol reference lines from symfile.\n\
|
||||
-f reffile Use reffile as cross-ref file name instead of %s.\n",
|
||||
REFFILE);
|
||||
fprintf(stderr, "\
|
||||
-h This help screen.\n\
|
||||
-I incdir Look in incdir for any #include files.\n\
|
||||
-i namefile Browse through files listed in namefile, instead of %s\n",
|
||||
NAMEFILE);
|
||||
fprintf(stderr, "\
|
||||
-k Kernel Mode - don't use %s for #include files.\n",
|
||||
DFLT_INCDIR);
|
||||
fputs("\
|
||||
-L Do a single search with line-oriented output.\n\
|
||||
-l Line-oriented interface.\n\
|
||||
-num pattern Go to input field num (counting from 0) and find pattern.\n\
|
||||
-P path Prepend path to relative file names in pre-built cross-ref file.\n\
|
||||
-p n Display the last n file path components.\n\
|
||||
-q Build an inverted index for quick symbol searching.\n\
|
||||
-R Recurse directories for files.\n\
|
||||
-s dir Look in dir for additional source files.\n\
|
||||
-T Use only the first eight characters to match against C symbols.\n\
|
||||
-U Check file time stamps.\n\
|
||||
-u Unconditionally build the cross-reference file.\n\
|
||||
-v Be more verbose in line mode.\n\
|
||||
-V Print the version number.\n\
|
||||
\n\
|
||||
Please see the manpage for more information.\n",
|
||||
stderr);
|
||||
}
|
103
src/history.c
Normal file
103
src/history.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol or text cross-reference
|
||||
*
|
||||
* command history
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
|
||||
static struct cmd *tail, *current;
|
||||
|
||||
/* add a cmd to the history list */
|
||||
void
|
||||
addcmd(int f, char *s) /* field number and command text */
|
||||
{
|
||||
struct cmd *h;
|
||||
|
||||
h = malloc(sizeof(struct cmd));
|
||||
if( tail) {
|
||||
tail->next = h;
|
||||
h->next = 0;
|
||||
h->prev = tail;
|
||||
tail = h;
|
||||
} else {
|
||||
tail = h;
|
||||
h->next = h->prev = 0;
|
||||
}
|
||||
h->field = f;
|
||||
h->text = strdup( s);
|
||||
current = 0;
|
||||
}
|
||||
|
||||
/* return previous history item */
|
||||
struct cmd *
|
||||
prevcmd(void)
|
||||
{
|
||||
if( current) {
|
||||
if( current->prev) /* stay on first item */
|
||||
return current = current->prev;
|
||||
else
|
||||
return current;
|
||||
} else if( tail)
|
||||
return current = tail;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* return next history item */
|
||||
struct cmd *
|
||||
nextcmd(void)
|
||||
{
|
||||
if( current) {
|
||||
if( current->next) /* stay on first item */
|
||||
return current = current->next;
|
||||
else
|
||||
return current;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
/* reset current to tail */
|
||||
void
|
||||
resetcmd(void)
|
||||
{
|
||||
current = 0;
|
||||
}
|
||||
|
||||
struct cmd *
|
||||
currentcmd(void)
|
||||
{
|
||||
return current;
|
||||
}
|
333
src/input.c
Normal file
333
src/input.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* terminal input functions
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
|
||||
#include <ncurses.h>
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
#include <setjmp.h> /* jmp_buf */
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#if HAVE_SYS_TERMIOS_H
|
||||
#include <sys/termios.h>
|
||||
#endif
|
||||
|
||||
static jmp_buf env; /* setjmp/longjmp buffer */
|
||||
static int prevchar; /* previous, ungotten character */
|
||||
|
||||
/* Internal prototypes: */
|
||||
static void catchint(int sig);
|
||||
|
||||
/* catch the interrupt signal */
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
catchint(int sig)
|
||||
{
|
||||
(void) sig; /* 'use' it, to avoid a warning */
|
||||
|
||||
signal(SIGINT, catchint);
|
||||
longjmp(env, 1);
|
||||
}
|
||||
|
||||
/* unget a character */
|
||||
void
|
||||
myungetch(int c)
|
||||
{
|
||||
prevchar = c;
|
||||
}
|
||||
|
||||
/* get a character from the terminal */
|
||||
int
|
||||
mygetch(void)
|
||||
{
|
||||
sighandler_t savesig = 0; /* old value of signal */
|
||||
int c;
|
||||
|
||||
/* change an interrupt signal to a break key character */
|
||||
if (setjmp(env) == 0) {
|
||||
savesig = signal(SIGINT, catchint);
|
||||
refresh(); /* update the display */
|
||||
mousereinit(); /* curses can change the menu number */
|
||||
if(prevchar) {
|
||||
c = prevchar;
|
||||
prevchar = 0;
|
||||
} else {
|
||||
c = -1;
|
||||
while (c == -1) {
|
||||
/* get a character from the terminal */
|
||||
c = getch();
|
||||
if ((c == -1) && (errno != EINTR))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else { /* longjmp to here from signal handler */
|
||||
c = KEY_BREAK;
|
||||
}
|
||||
signal(SIGINT, savesig);
|
||||
return(c);
|
||||
}
|
||||
|
||||
|
||||
/* get a line from the terminal in non-canonical mode */
|
||||
int
|
||||
mygetline(char p[], char s[], unsigned size, int firstchar, BOOL iscaseless)
|
||||
{
|
||||
int c;
|
||||
unsigned int i = 0, j;
|
||||
char *sright; /* substring to the right of the cursor */
|
||||
unsigned int ri = 0; /* position in right-string */
|
||||
|
||||
/* Inserts and deletes are always performed on the left-string,
|
||||
* but we'll also have a right-string 'sright' to hold characters
|
||||
* which are on the right of the cursor [insertion point].
|
||||
*
|
||||
* Think of 'sright' as a stack -- we push chars into it when the cursor
|
||||
* moves left, and we pop chars off it when the cursor moves right again.
|
||||
* At the end of the function, we'll pop off any remaining characters
|
||||
* onto the end of 's'
|
||||
*/
|
||||
sright = calloc(size, sizeof(*sright));
|
||||
|
||||
strcpy ( s, p);
|
||||
i += strlen(p);
|
||||
/* if a character already has been typed */
|
||||
if (firstchar != '\0') {
|
||||
if(iscaseless == YES) {
|
||||
firstchar = tolower(firstchar);
|
||||
}
|
||||
addch(firstchar); /* display it */
|
||||
s[i++] = firstchar; /* save it */
|
||||
}
|
||||
/* until the end of the line is reached */
|
||||
while ((c = mygetch()) != '\r' && c != '\n' && c != KEY_ENTER) {
|
||||
if (c == KEY_LEFT || c == ctrl('B')) { /* left */
|
||||
if (i > 0) {
|
||||
addch('\b');
|
||||
/* move this char into the second (rhs) string */
|
||||
sright[ri++] = s[--i];
|
||||
}
|
||||
} else if (c == KEY_RIGHT || c == ctrl('F')) { /* right */
|
||||
if (i < size && ri > 0) {
|
||||
/* move this char to the left of the cursor */
|
||||
s[i++] = sright[--ri];
|
||||
addch(s[i-1]);
|
||||
}
|
||||
} else if (
|
||||
#ifdef KEY_HOME
|
||||
c == KEY_HOME ||
|
||||
#endif
|
||||
c == ctrl('A') ) {
|
||||
while (i > 0) {
|
||||
sright[ri++] = s[--i];
|
||||
addch('\b');
|
||||
addch(s[i]);
|
||||
addch('\b');
|
||||
}
|
||||
} else if (
|
||||
#ifdef KEY_END
|
||||
c == KEY_END ||
|
||||
#endif
|
||||
c == ctrl('E') ) {
|
||||
while (ri > 0) {
|
||||
s[i++] = sright[--ri];
|
||||
addch(s[i-1]);
|
||||
}
|
||||
} else if (c == erasechar() || c == KEY_BACKSPACE
|
||||
|| c == DEL || c == ctrl('H') ) {
|
||||
/* erase */
|
||||
if (i > 0) {
|
||||
if (ri == 0) {
|
||||
addstr("\b \b");
|
||||
} else {
|
||||
addch('\b');
|
||||
delch();
|
||||
}
|
||||
s[i] = '\0';
|
||||
--i;
|
||||
}
|
||||
} else if (c == killchar() || c == KEY_BREAK) {
|
||||
/* kill */
|
||||
for (j = 0; j < i; ++j) {
|
||||
addch('\b');
|
||||
}
|
||||
for (j = 0; j < i; ++j) {
|
||||
addch(' ');
|
||||
}
|
||||
for (j = 0; j < i; ++j) {
|
||||
addch('\b');
|
||||
}
|
||||
i = 0;
|
||||
} else if (isprint(c) || c == '\t') {
|
||||
/* printable */
|
||||
if(iscaseless == YES) {
|
||||
c = tolower(c);
|
||||
}
|
||||
/* if it will fit on the line */
|
||||
if (i < size) {
|
||||
s[i++] = c; /* save it */
|
||||
if (ri == 0) {
|
||||
addch(c); /* display it */
|
||||
} else {
|
||||
insch(c); /* display it */
|
||||
addch(c); /* advance cursor */
|
||||
}
|
||||
}
|
||||
#if UNIXPC
|
||||
} else if (unixpcmouse == YES && c == ESC) { /* mouse */
|
||||
getmouseaction(ESC); /* ignore it */
|
||||
#endif
|
||||
} else if (mouse == YES && c == ctrl('X')) {
|
||||
getmouseaction(ctrl('X')); /* ignore it */
|
||||
} else if (c == EOF) { /* end-of-file */
|
||||
break;
|
||||
}
|
||||
|
||||
/* return on an empty line to allow a command to be entered */
|
||||
if (firstchar != '\0' && (i+ri) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* move any remaining chars on the rhs of the cursor
|
||||
* onto the end of our string
|
||||
*/
|
||||
while (ri > 0) {
|
||||
s[i++] = sright[--ri];
|
||||
}
|
||||
free(sright);
|
||||
|
||||
s[i] = '\0';
|
||||
return(i);
|
||||
}
|
||||
|
||||
/* ask user to enter a character after reading the message */
|
||||
|
||||
void
|
||||
askforchar(void)
|
||||
{
|
||||
addstr("Type any character to continue: ");
|
||||
mygetch();
|
||||
}
|
||||
|
||||
/* ask user to press the RETURN key after reading the message */
|
||||
|
||||
void
|
||||
askforreturn(void)
|
||||
{
|
||||
fprintf(stderr, "Press the RETURN key to continue: ");
|
||||
getchar();
|
||||
/* HBB 20060419: message probably messed up the screen --- redraw */
|
||||
if (incurses == YES) {
|
||||
redrawwin(curscr);
|
||||
}
|
||||
}
|
||||
|
||||
/* expand the ~ and $ shell meta characters in a path */
|
||||
|
||||
void
|
||||
shellpath(char *out, int limit, char *in)
|
||||
{
|
||||
char *lastchar;
|
||||
char *s, *v;
|
||||
|
||||
/* skip leading white space */
|
||||
while (isspace((unsigned char)*in)) {
|
||||
++in;
|
||||
}
|
||||
lastchar = out + limit - 1;
|
||||
|
||||
/* a tilde (~) by itself represents $HOME; followed by a name it
|
||||
represents the $LOGDIR of that login name */
|
||||
if (*in == '~') {
|
||||
*out++ = *in++; /* copy the ~ because it may not be expanded */
|
||||
|
||||
/* get the login name */
|
||||
s = out;
|
||||
while (s < lastchar && *in != '/' && *in != '\0' && !isspace((unsigned char)*in)) {
|
||||
*s++ = *in++;
|
||||
}
|
||||
*s = '\0';
|
||||
|
||||
/* if the login name is null, then use $HOME */
|
||||
if (*out == '\0') {
|
||||
v = getenv("HOME");
|
||||
} else { /* get the home directory of the login name */
|
||||
v = logdir(out);
|
||||
}
|
||||
/* copy the directory name if it isn't too big */
|
||||
if (v != NULL && strlen(v) < (lastchar - out)) {
|
||||
strcpy(out - 1, v);
|
||||
out += strlen(v) - 1;
|
||||
} else {
|
||||
/* login not found, so ~ must be part of the file name */
|
||||
out += strlen(out);
|
||||
}
|
||||
}
|
||||
/* get the rest of the path */
|
||||
while (out < lastchar && *in != '\0' && !isspace((unsigned char)*in)) {
|
||||
|
||||
/* look for an environment variable */
|
||||
if (*in == '$') {
|
||||
*out++ = *in++; /* copy the $ because it may not be expanded */
|
||||
|
||||
/* get the variable name */
|
||||
s = out;
|
||||
while (s < lastchar && *in != '/' && *in != '\0' &&
|
||||
!isspace((unsigned char)*in)) {
|
||||
*s++ = *in++;
|
||||
}
|
||||
*s = '\0';
|
||||
|
||||
/* get its value, but only it isn't too big */
|
||||
if ((v = getenv(out)) != NULL && strlen(v) < (lastchar - out)) {
|
||||
strcpy(out - 1, v);
|
||||
out += strlen(v) - 1;
|
||||
} else {
|
||||
/* var not found, or too big, so assume $ must be part of the
|
||||
* file name */
|
||||
out += strlen(out);
|
||||
}
|
||||
}
|
||||
else { /* ordinary character */
|
||||
*out++ = *in++;
|
||||
}
|
||||
}
|
||||
*out = '\0';
|
||||
}
|
1204
src/invlib.c
Normal file
1204
src/invlib.c
Normal file
File diff suppressed because it is too large
Load Diff
114
src/invlib.h
Normal file
114
src/invlib.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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 CSCOPE_INVLIB_H
|
||||
#define CSCOPE_INVLIB_H
|
||||
|
||||
#include <stdio.h> /* need definition of FILE* */
|
||||
#include <limits.h> /* need definition of CHAR_MAX */
|
||||
|
||||
/* inverted index definitions */
|
||||
|
||||
/* postings temporary file long number coding into characters */
|
||||
#if CHAR_MAX==255
|
||||
# define BASE 223 /* 255 - ' ' */
|
||||
# define PRECISION 4 /* maximum digits after converting a long */
|
||||
#else
|
||||
# if CHAR_MAX==127 /* assume sign-extension of a char when converted to an int */
|
||||
# define BASE 95 /* 127 - ' ' */
|
||||
# define PRECISION 5 /* maximum digits after converting a long */
|
||||
# else
|
||||
#error Need a platform with 8 bits in a char value
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* inverted index access parameters */
|
||||
#define INVAVAIL 0
|
||||
#define INVBUSY 1
|
||||
#define INVALONE 2
|
||||
|
||||
/* boolean set operations */
|
||||
#define BOOL_OR 3
|
||||
#define AND 4
|
||||
#define NOT 5
|
||||
#define REVERSENOT 6
|
||||
|
||||
/* note that the entire first block is for parameters */
|
||||
typedef struct {
|
||||
long version; /* inverted index format version */
|
||||
long filestat; /* file status word */
|
||||
long sizeblk; /* size of logical block in bytes */
|
||||
long startbyte; /* first byte of superfinger */
|
||||
long supsize; /* size of superfinger in bytes */
|
||||
long cntlsize; /* size of max cntl space (should be a multiple of BUFSIZ) */
|
||||
long share; /* flag whether to use shared memory */
|
||||
} PARAM;
|
||||
|
||||
typedef struct {
|
||||
FILE *invfile; /* the inverted file ptr */
|
||||
FILE *postfile; /* posting file ptr */
|
||||
PARAM param; /* control parameters for the file */
|
||||
char *iindex; /* ptr to space for superindex */
|
||||
union logicalblk *logblk; /* ptr to space for a logical block */
|
||||
long numblk; /* number of block presently at *logblk */
|
||||
long keypnt; /* number item in present block found */
|
||||
} INVCONTROL;
|
||||
|
||||
typedef struct {
|
||||
short offset; /* offset in this logical block */
|
||||
unsigned char size; /* size of term */
|
||||
unsigned char space; /* number of longs of growth space */
|
||||
long post; /* number of postings for this entry */
|
||||
} ENTRY;
|
||||
|
||||
typedef struct {
|
||||
long lineoffset; /* source line database offset */
|
||||
long fcnoffset; /* function name database offset */
|
||||
long fileindex : 24; /* source file name index */
|
||||
long type : 8; /* reference type (mark character) */
|
||||
} POSTING;
|
||||
|
||||
extern long *srcoffset; /* source file name database offsets */
|
||||
extern int nsrcoffset; /* number of file name database offsets */
|
||||
|
||||
|
||||
void boolclear(void);
|
||||
POSTING *boolfile(INVCONTROL *invcntl, long *num, int boolarg);
|
||||
void invclose(INVCONTROL *invcntl);
|
||||
void invdump(INVCONTROL *invcntl, char *term);
|
||||
long invfind(INVCONTROL *invcntl, char *searchterm);
|
||||
int invforward(INVCONTROL *invcntl);
|
||||
int invopen(INVCONTROL *invcntl, char *invname, char *invpost, int status);
|
||||
long invmake(char *invname, char *invpost, FILE *infile);
|
||||
long invterm(INVCONTROL *invcntl, char *term);
|
||||
|
||||
#endif /* CSCOPE_INVLIB_H */
|
51
src/library.h
Normal file
51
src/library.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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 CSCOPE_LIBRARY_H
|
||||
#define CSCOPE_LIBRARY_H
|
||||
|
||||
#include <stdio.h> /* need FILE* type def. */
|
||||
|
||||
/* private library */
|
||||
char *compath(char *pathname);
|
||||
char *egrepinit(char *egreppat);
|
||||
char *logdir(char *name);
|
||||
char *basename(char *path);
|
||||
FILE *myfopen(char *path, char *mode);
|
||||
char *mygetenv(char *variable, char *deflt);
|
||||
int myopen(char *path, int flag, int mode);
|
||||
FILE *mypopen(char *cmd, char *mode);
|
||||
int mypclose(FILE *ptr);
|
||||
FILE *vpfopen(char *filename, char *type);
|
||||
void egrepcaseless(int i);
|
||||
|
||||
#endif /* CSCOPE_LIBRARY_H */
|
100
src/logdir.c
Normal file
100
src/logdir.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/*
|
||||
* logdir()
|
||||
*
|
||||
* This routine does not use the getpwent(3) library routine
|
||||
* because the latter uses the stdio package. The allocation of
|
||||
* storage in this package destroys the integrity of the shell's
|
||||
* storage allocation.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "global.h"
|
||||
|
||||
#define OURBUFSIZ 160 /* renamed: avoid conflict with <stdio.h> */
|
||||
|
||||
static char line[OURBUFSIZ+1];
|
||||
|
||||
/* Internal prototypes: */
|
||||
static char *nextfield(char *p);
|
||||
|
||||
|
||||
static char *
|
||||
nextfield(char *p)
|
||||
{
|
||||
while (*p && *p != ':')
|
||||
++p;
|
||||
if (*p) *p++ = 0;
|
||||
return(p);
|
||||
}
|
||||
|
||||
char *
|
||||
logdir(char *name)
|
||||
{
|
||||
char *p;
|
||||
int i, j;
|
||||
int pwf;
|
||||
|
||||
/* attempt to open the password file */
|
||||
if ((pwf = myopen("/etc/passwd", 0, 0)) == -1)
|
||||
return(0);
|
||||
|
||||
/* find the matching password entry */
|
||||
do {
|
||||
/* get the next line in the password file */
|
||||
i = read(pwf, line, OURBUFSIZ);
|
||||
for (j = 0; j < i; j++)
|
||||
if (line[j] == '\n')
|
||||
break;
|
||||
/* return a null pointer if the whole file has been read */
|
||||
if (j >= i)
|
||||
return(0);
|
||||
line[++j] = 0; /* terminate the line */
|
||||
(void) lseek(pwf, (long) (j - i), 1); /* point at the next line */
|
||||
p = nextfield(line); /* get the logname */
|
||||
} while (*name != *line || /* fast pretest */
|
||||
strcmp(name, line) != 0);
|
||||
(void) close(pwf);
|
||||
|
||||
/* skip the intervening fields */
|
||||
p = nextfield(p);
|
||||
p = nextfield(p);
|
||||
p = nextfield(p);
|
||||
p = nextfield(p);
|
||||
|
||||
/* return the login directory */
|
||||
(void) nextfield(p);
|
||||
return(p);
|
||||
}
|
149
src/lookup.c
Normal file
149
src/lookup.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* keyword look-up routine for the C symbol scanner
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "lookup.h"
|
||||
|
||||
/* keyword text for fast testing of keywords in the scanner */
|
||||
char enumtext[] = "enum";
|
||||
char externtext[] = "extern";
|
||||
char structtext[] = "struct";
|
||||
char typedeftext[] = "typedef";
|
||||
char uniontext[] = "union";
|
||||
|
||||
/* This keyword table is also used for keyword text compression. Keywords
|
||||
* with an index less than the numeric value of a space are replaced with the
|
||||
* control character corresponding to the index, so they cannot be moved
|
||||
* without changing the database file version and adding compatibility code
|
||||
* for old databases.
|
||||
*/
|
||||
struct keystruct keyword[] = {
|
||||
{"", '\0', NULL}, /* dummy entry */
|
||||
{"#define", ' ', NULL}, /* must be table entry 1 */
|
||||
{"#include", ' ', NULL}, /* must be table entry 2 */
|
||||
{"break", '\0', NULL}, /* rarely in cross-reference */
|
||||
{"case", ' ', NULL},
|
||||
{"char", ' ', NULL},
|
||||
{"continue", '\0', NULL}, /* rarely in cross-reference */
|
||||
{"default", '\0', NULL}, /* rarely in cross-reference */
|
||||
{"double", ' ', NULL},
|
||||
{"\t", '\0', NULL}, /* must be the table entry 9 */
|
||||
{"\n", '\0', NULL}, /* must be the table entry 10 */
|
||||
{"else", ' ', NULL},
|
||||
{enumtext, ' ', NULL},
|
||||
{externtext, ' ', NULL},
|
||||
{"float", ' ', NULL},
|
||||
{"for", '(', NULL},
|
||||
{"goto", ' ', NULL},
|
||||
{"if", '(', NULL},
|
||||
{"int", ' ', NULL},
|
||||
{"long", ' ', NULL},
|
||||
{"register", ' ', NULL},
|
||||
{"return", '\0', NULL},
|
||||
{"short", ' ', NULL},
|
||||
{"sizeof", '\0', NULL},
|
||||
{"static", ' ', NULL},
|
||||
{structtext, ' ', NULL},
|
||||
{"switch", '(', NULL},
|
||||
{typedeftext, ' ', NULL},
|
||||
{uniontext, ' ', NULL},
|
||||
{"unsigned", ' ', NULL},
|
||||
{"void", ' ', NULL},
|
||||
{"while", '(', NULL},
|
||||
|
||||
/* these keywords are not compressed */
|
||||
{"do", '\0', NULL},
|
||||
{"auto", ' ', NULL},
|
||||
{"fortran", ' ', NULL},
|
||||
{"const", ' ', NULL},
|
||||
{"signed", ' ', NULL},
|
||||
{"volatile", ' ', NULL},
|
||||
};
|
||||
#define KEYWORDS (sizeof(keyword) / sizeof(keyword[0]))
|
||||
|
||||
#define HASHMOD (KEYWORDS * 2 + 1)
|
||||
|
||||
static struct keystruct *hashtab[HASHMOD]; /* pointer table */
|
||||
|
||||
/* put the keywords into the symbol table */
|
||||
|
||||
void
|
||||
initsymtab(void)
|
||||
{
|
||||
unsigned int i, j;
|
||||
struct keystruct *p;
|
||||
|
||||
for (i = 1; i < KEYWORDS; ++i) {
|
||||
p = keyword + i;
|
||||
j = hash(p->text) % HASHMOD;
|
||||
p->next = hashtab[j];
|
||||
hashtab[j] = p;
|
||||
}
|
||||
}
|
||||
|
||||
/* see if this identifier is a keyword */
|
||||
|
||||
char *
|
||||
lookup(char *ident)
|
||||
{
|
||||
struct keystruct *p;
|
||||
int c;
|
||||
|
||||
/* look up the identifier in the keyword table */
|
||||
for (p = hashtab[hash(ident) % HASHMOD]; p != NULL; p = p->next) {
|
||||
if (strequal(ident, p->text)) {
|
||||
if (compress == YES && (c = p - keyword) < ' ') {
|
||||
ident[0] = c; /* compress the keyword */
|
||||
}
|
||||
return(p->text);
|
||||
}
|
||||
}
|
||||
/* this is an identifier */
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* form hash value for string */
|
||||
int
|
||||
hash(char *ss)
|
||||
{
|
||||
int i;
|
||||
unsigned char *s = (unsigned char *)ss;
|
||||
|
||||
for (i = 0; *s != '\0'; )
|
||||
i += *s++; /* += is faster than <<= for cscope */
|
||||
return(i);
|
||||
}
|
45
src/lookup.h
Normal file
45
src/lookup.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 2001, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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 CSCOPE_LOOKUP_H
|
||||
#define CSCOPE_LOOKUP_H
|
||||
|
||||
/* declarations for objects defined in lookup.c */
|
||||
|
||||
/* keyword text for fast testing of keywords in the scanner */
|
||||
extern char enumtext[];
|
||||
extern char externtext[];
|
||||
extern char structtext[];
|
||||
extern char typedeftext[];
|
||||
extern char uniontext[];
|
||||
|
||||
#endif /* CSCOPE_LOOKUP_H */
|
674
src/main.c
Normal file
674
src/main.c
Normal file
@ -0,0 +1,674 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* main functions
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "build.h"
|
||||
#include "vp.h"
|
||||
#include "version.h" /* FILEVERSION and FIXVERSION */
|
||||
#include "scanner.h"
|
||||
|
||||
#include <stdlib.h> /* atoi */
|
||||
#include <ncurses.h>
|
||||
#include <sys/types.h> /* needed by stat.h */
|
||||
#include <sys/stat.h> /* stat */
|
||||
#include <signal.h>
|
||||
#include <getopt.h>
|
||||
|
||||
/* defaults for unset environment variables */
|
||||
#define EDITOR "vi"
|
||||
#define HOME "/" /* no $HOME --> use root directory */
|
||||
#define SHELL "sh"
|
||||
#define LINEFLAG "+%s" /* default: used by vi and emacs */
|
||||
#define TMPDIR "/tmp"
|
||||
|
||||
/* note: these digraph character frequencies were calculated from possible
|
||||
printable digraphs in the cross-reference for the C compiler */
|
||||
char dichar1[] = " teisaprnl(of)=c"; /* 16 most frequent first chars */
|
||||
char dichar2[] = " tnerpla"; /* 8 most frequent second chars
|
||||
using the above as first chars */
|
||||
char dicode1[256]; /* digraph first character code */
|
||||
char dicode2[256]; /* digraph second character code */
|
||||
|
||||
char *editor, *shell, *lineflag; /* environment variables */
|
||||
char *home; /* Home directory */
|
||||
BOOL lineflagafterfile;
|
||||
char *argv0; /* command name */
|
||||
BOOL compress = YES; /* compress the characters in the crossref */
|
||||
BOOL dbtruncated; /* database symbols are truncated to 8 chars */
|
||||
int dispcomponents = 1; /* file path components to display */
|
||||
#if CCS
|
||||
BOOL displayversion; /* display the C Compilation System version */
|
||||
#endif
|
||||
BOOL editallprompt = YES; /* prompt between editing files */
|
||||
unsigned int fileargc; /* file argument count */
|
||||
char **fileargv; /* file argument values */
|
||||
int fileversion; /* cross-reference file version */
|
||||
BOOL incurses = NO; /* in curses */
|
||||
BOOL invertedindex; /* the database has an inverted index */
|
||||
BOOL isuptodate; /* consider the crossref up-to-date */
|
||||
BOOL kernelmode; /* don't use DFLT_INCDIR - bad for kernels */
|
||||
BOOL linemode = NO; /* use line oriented user interface */
|
||||
BOOL verbosemode = NO; /* print extra information on line mode */
|
||||
BOOL recurse_dir = NO; /* recurse dirs when searching for src files */
|
||||
char *namefile; /* file of file names */
|
||||
BOOL ogs; /* display OGS book and subsystem names */
|
||||
char *prependpath; /* prepend path to file names */
|
||||
FILE *refsfound; /* references found file */
|
||||
char temp1[PATHLEN + 1]; /* temporary file name */
|
||||
char temp2[PATHLEN + 1]; /* temporary file name */
|
||||
char tempdirpv[PATHLEN + 1]; /* private temp directory */
|
||||
long totalterms; /* total inverted index terms */
|
||||
BOOL trun_syms; /* truncate symbols to 8 characters */
|
||||
char tempstring[TEMPSTRING_LEN + 1]; /* use this as a buffer, instead of 'yytext',
|
||||
* which had better be left alone */
|
||||
char *tmpdir; /* temporary directory */
|
||||
|
||||
|
||||
/* Internal prototypes: */
|
||||
static void skiplist(FILE *oldrefs);
|
||||
static void initcompress(void);
|
||||
static inline void readenv(void);
|
||||
|
||||
#if defined(KEY_RESIZE) && !defined(__DJGPP__)
|
||||
void
|
||||
sigwinch_handler(int sig, siginfo_t *info, void *unused)
|
||||
{
|
||||
if(incurses == YES){
|
||||
ungetch(KEY_RESIZE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
FILE *names; /* name file pointer */
|
||||
int oldnum; /* number in old cross-ref */
|
||||
char path[PATHLEN + 1]; /* file path */
|
||||
FILE *oldrefs; /* old cross-reference file */
|
||||
char *s;
|
||||
int c;
|
||||
unsigned int i;
|
||||
pid_t pid;
|
||||
struct stat stat_buf;
|
||||
#if defined(KEY_RESIZE) && !defined(__DJGPP__)
|
||||
struct sigaction winch_action;
|
||||
#endif
|
||||
mode_t orig_umask;
|
||||
|
||||
yyin = stdin;
|
||||
yyout = stdout;
|
||||
/* save the command name for messages */
|
||||
argv0 = argv[0];
|
||||
|
||||
/* set the options */
|
||||
argv = parse_options(&argc, argv);
|
||||
|
||||
/* read the environment */
|
||||
readenv();
|
||||
|
||||
/* XXX remove if/when clearerr() in dir.c does the right thing. */
|
||||
if (namefile && strcmp(namefile, "-") == 0 && !buildonly) {
|
||||
postfatal("cscope: Must use -b if file list comes from stdin\n");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* make sure that tmpdir exists */
|
||||
if (lstat (tmpdir, &stat_buf)) {
|
||||
fprintf (stderr,
|
||||
"cscope: Temporary directory %s does not exist or cannot be accessed\n",
|
||||
tmpdir);
|
||||
fprintf (stderr,
|
||||
"cscope: Please create the directory or set the environment variable\n"
|
||||
"cscope: TMPDIR to a valid directory\n");
|
||||
myexit(1);
|
||||
}
|
||||
|
||||
/* create the temporary file names */
|
||||
orig_umask = umask(S_IRWXG|S_IRWXO);
|
||||
pid = getpid();
|
||||
snprintf(tempdirpv, sizeof(tempdirpv), "%s/cscope.%d", tmpdir, pid);
|
||||
if(mkdir(tempdirpv,S_IRWXU)) {
|
||||
fprintf(stderr,
|
||||
"cscope: Could not create private temp dir %s\n",
|
||||
tempdirpv);
|
||||
myexit(1);
|
||||
}
|
||||
umask(orig_umask);
|
||||
|
||||
snprintf(temp1, sizeof(temp1), "%s/cscope.1", tempdirpv);
|
||||
snprintf(temp2, sizeof(temp2), "%s/cscope.2", tempdirpv);
|
||||
|
||||
/* if running in the foreground */
|
||||
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
|
||||
/* cleanup on the interrupt and quit signals */
|
||||
signal(SIGINT, myexit);
|
||||
signal(SIGQUIT, myexit);
|
||||
}
|
||||
/* cleanup on the hangup signal */
|
||||
signal(SIGHUP, myexit);
|
||||
|
||||
/* ditto the TERM signal */
|
||||
signal(SIGTERM, myexit);
|
||||
|
||||
/* ignore PIPE signal, so myexit() will have a chance to clean up in
|
||||
* linemode, while in curses mode the "|" command can cause a pipe signal
|
||||
* too
|
||||
*/
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/* if the database path is relative and it can't be created */
|
||||
if (reffile[0] != '/' && access(".", WRITE) != 0) {
|
||||
|
||||
/* put it in the home directory if the database may not be
|
||||
* up-to-date or doesn't exist in the relative directory,
|
||||
* so a database in the current directory will be
|
||||
* used instead of failing to open a non-existant database in
|
||||
* the home directory
|
||||
*/
|
||||
snprintf(path, sizeof(path), "%s/%s", home, reffile);
|
||||
if (isuptodate == NO || access(path, READ) == 0) {
|
||||
reffile = strdup(path);
|
||||
snprintf(path, sizeof(path), "%s/%s", home, invname);
|
||||
invname = strdup(path);
|
||||
snprintf(path, sizeof(path), "%s/%s", home, invpost);
|
||||
invpost = strdup(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (linemode == NO) {
|
||||
signal(SIGINT, SIG_IGN); /* ignore interrupts */
|
||||
|
||||
#if defined(KEY_RESIZE) && !defined(__DJGPP__)
|
||||
winch_action.sa_sigaction = sigwinch_handler;
|
||||
sigemptyset(&winch_action.sa_mask);
|
||||
winch_action.sa_flags = SA_SIGINFO;
|
||||
sigaction(SIGWINCH,&winch_action,NULL);
|
||||
#endif
|
||||
|
||||
dispinit(); /* initialize display parameters */
|
||||
setfield(); /* set the initial cursor position */
|
||||
clearmsg(); /* clear any build progress message */
|
||||
display(); /* display the version number and input fields */
|
||||
}
|
||||
|
||||
|
||||
/* if the cross-reference is to be considered up-to-date */
|
||||
if (isuptodate == YES) {
|
||||
if ((oldrefs = vpfopen(reffile, "rb")) == NULL) {
|
||||
postfatal("cscope: cannot open file %s\n", reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/* get the crossref file version but skip the current directory */
|
||||
if (fscanf(oldrefs, "cscope %d %*s", &fileversion) != 1) {
|
||||
postfatal("cscope: cannot read file version from file %s\n",
|
||||
reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
if (fileversion >= 8) {
|
||||
|
||||
/* override these command line options */
|
||||
compress = YES;
|
||||
invertedindex = NO;
|
||||
|
||||
/* see if there are options in the database */
|
||||
for (;;) {
|
||||
getc(oldrefs); /* skip the blank */
|
||||
if ((c = getc(oldrefs)) != '-') {
|
||||
ungetc(c, oldrefs);
|
||||
break;
|
||||
}
|
||||
switch (getc(oldrefs)) {
|
||||
case 'c': /* ASCII characters only */
|
||||
compress = NO;
|
||||
break;
|
||||
case 'q': /* quick search */
|
||||
invertedindex = YES;
|
||||
fscanf(oldrefs, "%ld", &totalterms);
|
||||
break;
|
||||
case 'T': /* truncate symbols to 8 characters */
|
||||
dbtruncated = YES;
|
||||
trun_syms = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
initcompress();
|
||||
seek_to_trailer(oldrefs);
|
||||
}
|
||||
/* skip the source and include directory lists */
|
||||
skiplist(oldrefs);
|
||||
skiplist(oldrefs);
|
||||
|
||||
/* get the number of source files */
|
||||
if (fscanf(oldrefs, "%lu", &nsrcfiles) != 1) {
|
||||
postfatal(
|
||||
"cscope: cannot read source file size from file %s\n",
|
||||
reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/* get the source file list */
|
||||
srcfiles = malloc(nsrcfiles * sizeof(*srcfiles));
|
||||
if (fileversion >= 9) {
|
||||
|
||||
/* allocate the string space */
|
||||
if (fscanf(oldrefs, "%d", &oldnum) != 1) {
|
||||
postfatal(
|
||||
"cscope: cannot read string space size from file %s\n",
|
||||
reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
s = malloc(oldnum);
|
||||
getc(oldrefs); /* skip the newline */
|
||||
|
||||
/* read the strings */
|
||||
if (fread(s, oldnum, 1, oldrefs) != 1) {
|
||||
postfatal(
|
||||
"cscope: cannot read source file names from file %s\n",
|
||||
reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/* change newlines to nulls */
|
||||
for (i = 0; i < nsrcfiles; ++i) {
|
||||
srcfiles[i] = s;
|
||||
for (++s; *s != '\n'; ++s) {
|
||||
;
|
||||
}
|
||||
*s = '\0';
|
||||
++s;
|
||||
}
|
||||
/* if there is a file of source file names */
|
||||
if ((namefile != NULL && (names = vpfopen(namefile, "r")) != NULL)
|
||||
|| (names = vpfopen(NAMEFILE, "r")) != NULL) {
|
||||
|
||||
/* read any -p option from it */
|
||||
while (fgets(path, sizeof(path), names) != NULL && *path == '-') {
|
||||
i = path[1];
|
||||
s = path + 2; /* for "-Ipath" */
|
||||
if (*s == '\0') { /* if "-I path" */
|
||||
fgets(path, sizeof(path), names);
|
||||
s = path;
|
||||
}
|
||||
switch (i) {
|
||||
case 'p': /* file path components to display */
|
||||
if (*s < '0' || *s > '9') {
|
||||
posterr("cscope: -p option in file %s: missing or invalid numeric value\n", namefile);
|
||||
|
||||
}
|
||||
dispcomponents = atoi(s);
|
||||
}
|
||||
}
|
||||
fclose(names);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < nsrcfiles; ++i) {
|
||||
if (!fgets(path, sizeof(path), oldrefs) ) {
|
||||
postfatal(
|
||||
"cscope: cannot read source file name from file %s\n",
|
||||
reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
srcfiles[i] = strdup(path);
|
||||
}
|
||||
}
|
||||
fclose(oldrefs);
|
||||
} else {
|
||||
/* save the file arguments */
|
||||
fileargc = argc;
|
||||
fileargv = argv;
|
||||
|
||||
/* get source directories from the environment */
|
||||
if ((s = getenv("SOURCEDIRS")) != NULL) {
|
||||
sourcedir(s);
|
||||
}
|
||||
/* make the source file list */
|
||||
srcfiles = malloc(msrcfiles * sizeof(*srcfiles));
|
||||
makefilelist();
|
||||
if (nsrcfiles == 0) {
|
||||
postfatal("cscope: no source files found\n");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/* get include directories from the environment */
|
||||
if ((s = getenv("INCLUDEDIRS")) != NULL) {
|
||||
includedir(s);
|
||||
}
|
||||
/* add /usr/include to the #include directory list,
|
||||
but not in kernelmode... kernels tend not to use it. */
|
||||
if (kernelmode == NO) {
|
||||
if (NULL != (s = getenv("INCDIR"))) {
|
||||
includedir(s);
|
||||
} else {
|
||||
includedir(DFLT_INCDIR);
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize the C keyword table */
|
||||
initsymtab();
|
||||
|
||||
/* Tell build.c about the filenames to create: */
|
||||
setup_build_filenames(reffile);
|
||||
|
||||
/* build the cross-reference */
|
||||
initcompress();
|
||||
if (linemode == NO || verbosemode == YES) /* display if verbose as well */
|
||||
postmsg("Building cross-reference...");
|
||||
build();
|
||||
if (linemode == NO )
|
||||
clearmsg(); /* clear any build progress message */
|
||||
if (buildonly == YES) {
|
||||
myexit(0);
|
||||
}
|
||||
}
|
||||
opendatabase();
|
||||
|
||||
/* if using the line oriented user interface so cscope can be a
|
||||
subprocess to emacs or samuel */
|
||||
if (linemode == YES) {
|
||||
if (*Pattern != '\0') { /* do any optional search */
|
||||
if (search() == YES) {
|
||||
/* print the total number of lines in
|
||||
* verbose mode */
|
||||
if (verbosemode == YES)
|
||||
printf("cscope: %d lines\n",
|
||||
totallines);
|
||||
|
||||
while ((c = getc(refsfound)) != EOF)
|
||||
putchar(c);
|
||||
}
|
||||
}
|
||||
if (onesearch == YES)
|
||||
myexit(0);
|
||||
|
||||
for (;;) {
|
||||
char buf[PATLEN + 2];
|
||||
|
||||
printf(">> ");
|
||||
fflush(stdout);
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
myexit(0);
|
||||
}
|
||||
/* remove any trailing newline character */
|
||||
if (*(s = buf + strlen(buf) - 1) == '\n') {
|
||||
*s = '\0';
|
||||
}
|
||||
switch (*buf) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9': /* samuel only */
|
||||
field = *buf - '0';
|
||||
strcpy(Pattern, buf + 1);
|
||||
if (search() == NO) {
|
||||
printf("Unable to search database\n");
|
||||
} else {
|
||||
printf("cscope: %d lines\n", totallines);
|
||||
while ((c = getc(refsfound)) != EOF) {
|
||||
putchar(c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c': /* toggle caseless mode */
|
||||
case ctrl('C'):
|
||||
if (caseless == NO) {
|
||||
caseless = YES;
|
||||
} else {
|
||||
caseless = NO;
|
||||
}
|
||||
egrepcaseless(caseless);
|
||||
break;
|
||||
|
||||
case 'r': /* rebuild database cscope style */
|
||||
case ctrl('R'):
|
||||
freefilelist();
|
||||
makefilelist();
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 'R': /* rebuild database samuel style */
|
||||
rebuild();
|
||||
putchar('\n');
|
||||
break;
|
||||
|
||||
case 'C': /* clear file names */
|
||||
freefilelist();
|
||||
putchar('\n');
|
||||
break;
|
||||
|
||||
case 'F': /* add a file name */
|
||||
strcpy(path, buf + 1);
|
||||
if (infilelist(path) == NO &&
|
||||
(s = inviewpath(path)) != NULL) {
|
||||
addsrcfile(s);
|
||||
}
|
||||
putchar('\n');
|
||||
break;
|
||||
|
||||
case 'q': /* quit */
|
||||
case ctrl('D'):
|
||||
case ctrl('Z'):
|
||||
myexit(0);
|
||||
|
||||
default:
|
||||
fprintf(stderr, "cscope: unknown command '%s'\n", buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/* pause before clearing the screen if there have been error messages */
|
||||
if (errorsfound == YES) {
|
||||
errorsfound = NO;
|
||||
askforreturn();
|
||||
}
|
||||
/* do any optional search */
|
||||
if (*Pattern != '\0') {
|
||||
atfield(); /* move to the input field */
|
||||
command(ctrl('Y')); /* search */
|
||||
} else if (reflines != NULL) {
|
||||
/* read any symbol reference lines file */
|
||||
readrefs(reflines);
|
||||
}
|
||||
display(); /* update the display */
|
||||
|
||||
for (;;) {
|
||||
c = mygetch();
|
||||
|
||||
/* exit if the quit command is entered */
|
||||
if (c == EOF || c == ctrl('D')) {
|
||||
break;
|
||||
}
|
||||
if (c == ctrl('Z')) {
|
||||
kill(0, SIGTSTP);
|
||||
continue;
|
||||
}
|
||||
|
||||
command(c);
|
||||
display();
|
||||
}
|
||||
/* cleanup and exit */
|
||||
myexit(0);
|
||||
/* NOTREACHED */
|
||||
return 0; /* avoid warning... */
|
||||
}
|
||||
|
||||
void
|
||||
cannotopen(char *file)
|
||||
{
|
||||
posterr("Cannot open file %s", file);
|
||||
}
|
||||
|
||||
/* FIXME MTE - should use postfatal here */
|
||||
void
|
||||
cannotwrite(char *file)
|
||||
{
|
||||
char msg[MSGLEN + 1];
|
||||
|
||||
snprintf(msg, sizeof(msg), "Removed file %s because write failed", file);
|
||||
|
||||
myperror(msg); /* display the reason */
|
||||
|
||||
unlink(file);
|
||||
myexit(1); /* calls exit(2), which closes files */
|
||||
}
|
||||
|
||||
|
||||
/* set up the digraph character tables for text compression */
|
||||
static void
|
||||
initcompress(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (compress == YES) {
|
||||
for (i = 0; i < 16; ++i) {
|
||||
dicode1[(unsigned char) (dichar1[i])] = i * 8 + 1;
|
||||
}
|
||||
for (i = 0; i < 8; ++i) {
|
||||
dicode2[(unsigned char) (dichar2[i])] = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* skip the list in the cross-reference file */
|
||||
|
||||
static void
|
||||
skiplist(FILE *oldrefs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (fscanf(oldrefs, "%d", &i) != 1) {
|
||||
postfatal("cscope: cannot read list size from file %s\n", reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
while (--i >= 0) {
|
||||
if (fscanf(oldrefs, "%*s") != 0) {
|
||||
postfatal("cscope: cannot read list name from file %s\n", reffile);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* enter curses mode */
|
||||
void
|
||||
entercurses(void)
|
||||
{
|
||||
incurses = YES;
|
||||
#ifndef __MSDOS__ /* HBB 20010313 */
|
||||
nonl(); /* don't translate an output \n to \n\r */
|
||||
#endif
|
||||
raw(); /* single character input */
|
||||
noecho(); /* don't echo input characters */
|
||||
clear(); /* clear the screen */
|
||||
mouseinit(); /* initialize any mouse interface */
|
||||
drawscrollbar(topline, nextline);
|
||||
}
|
||||
|
||||
|
||||
/* exit curses mode */
|
||||
void
|
||||
exitcurses(void)
|
||||
{
|
||||
/* clear the bottom line */
|
||||
move(LINES - 1, 0);
|
||||
clrtoeol();
|
||||
refresh();
|
||||
|
||||
/* exit curses and restore the terminal modes */
|
||||
endwin();
|
||||
incurses = NO;
|
||||
|
||||
/* restore the mouse */
|
||||
mousecleanup();
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* cleanup and exit */
|
||||
void
|
||||
myexit(int sig)
|
||||
{
|
||||
/* HBB 20010313; close file before unlinking it. Unix may not care
|
||||
* about that, but DOS absolutely needs it */
|
||||
if (refsfound != NULL)
|
||||
fclose(refsfound);
|
||||
|
||||
/* remove any temporary files */
|
||||
if (temp1[0] != '\0') {
|
||||
unlink(temp1);
|
||||
unlink(temp2);
|
||||
rmdir(tempdirpv);
|
||||
}
|
||||
/* restore the terminal to its original mode */
|
||||
if (incurses == YES) {
|
||||
exitcurses();
|
||||
}
|
||||
/* dump core for debugging on the quit signal */
|
||||
if (sig == SIGQUIT) {
|
||||
abort();
|
||||
}
|
||||
/* HBB 20000421: be nice: free allocated data */
|
||||
freefilelist();
|
||||
freeinclist();
|
||||
freesrclist();
|
||||
freecrossref();
|
||||
free_newbuildfiles();
|
||||
|
||||
if( remove_symfile_onexit == YES ) {
|
||||
unlink( reffile );
|
||||
unlink( invname );
|
||||
unlink( invpost );
|
||||
}
|
||||
|
||||
exit(sig);
|
||||
}
|
||||
|
||||
static inline void readenv(void){
|
||||
editor = mygetenv("EDITOR", EDITOR);
|
||||
editor = mygetenv("VIEWER", editor); /* use viewer if set */
|
||||
editor = mygetenv("CSCOPE_EDITOR", editor); /* has last word */
|
||||
home = mygetenv("HOME", HOME);
|
||||
shell = mygetenv("SHELL", SHELL);
|
||||
lineflag = mygetenv("CSCOPE_LINEFLAG", LINEFLAG);
|
||||
lineflagafterfile = getenv("CSCOPE_LINEFLAG_AFTER_FILE") ? 1 : 0;
|
||||
tmpdir = mygetenv("TMPDIR", TMPDIR);
|
||||
}
|
431
src/mouse.c
Normal file
431
src/mouse.c
Normal file
@ -0,0 +1,431 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* mouse functions
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
BOOL mouse = NO; /* mouse interface */
|
||||
|
||||
#ifdef UNIXPC /* build command requires #ifdef instead of #if */
|
||||
#include <sys/window.h>
|
||||
BOOL unixpcmouse = NO; /* running with a mouse on the Unix PC? */
|
||||
static int uw_hs, uw_vs; /* character height and width */
|
||||
#endif
|
||||
|
||||
typedef struct { /* menu */
|
||||
char *text;
|
||||
char *value;
|
||||
} MENU;
|
||||
|
||||
static MENU mainmenu[] = { /* main menu */
|
||||
{"Send", "##\033s##\r"},
|
||||
{"Repeat", "\031"},
|
||||
{"Edit All", "\05"},
|
||||
{"Rebuild", "\022"},
|
||||
{"Shell", "!"},
|
||||
{"Redraw", "\f"},
|
||||
{"Help", "?"},
|
||||
{"Exit", "\04"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static MENU changemenu[] = { /* change mode menu */
|
||||
{"Mark Screen", "*"},
|
||||
{"Mark All", "a"},
|
||||
{"Change", "\04"},
|
||||
{"No Change", "\033"},
|
||||
{"Shell", "!"},
|
||||
{"Redraw", "\f"},
|
||||
{"Help", "?"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static MENU *loaded; /* menu loaded */
|
||||
static BOOL emacsviterm = NO; /* terminal type */
|
||||
|
||||
static void loadmenu(MENU *menu);
|
||||
static int getcoordinate(void);
|
||||
static int getpercent(void);
|
||||
|
||||
/* see if there is a mouse interface */
|
||||
|
||||
void
|
||||
mouseinit(void)
|
||||
{
|
||||
char *term;
|
||||
|
||||
/* see if this is emacsterm or viterm */
|
||||
term = mygetenv("TERM", "");
|
||||
if (strcmp(term, "emacsterm") == 0 ||
|
||||
strcmp(term, "viterm") == 0) {
|
||||
emacsviterm = YES;
|
||||
mouse = YES;
|
||||
}
|
||||
/* the MOUSE enviroment variable is for 5620 terminal programs that have
|
||||
mouse support but the TERM environment variable is the same as a
|
||||
terminal without a mouse, such as myx */
|
||||
else if (strcmp(mygetenv("MOUSE", ""), "myx") == 0) {
|
||||
mouse = YES;
|
||||
}
|
||||
#if UNIXPC
|
||||
else if (strcmp(term,"s4") == 0 ||
|
||||
strcmp(term,"s120") == 0 ||
|
||||
strcmp(term,"s90") == 0) {
|
||||
int retval;
|
||||
struct uwdata uwd; /* Window data structure */
|
||||
struct umdata umd; /* Mouse data structure */
|
||||
|
||||
/* Ask for character size info */
|
||||
|
||||
retval = ioctl(1,WIOCGETD,&uwd);
|
||||
if(retval || uwd.uw_hs <= 0 || uwd.uw_vs <= 0) {
|
||||
/**************************************************
|
||||
* something wrong with the kernel, so fake it...
|
||||
**************************************************/
|
||||
if(!strcmp(term,"s4")) {
|
||||
uw_hs = 9;
|
||||
uw_vs = 12;
|
||||
}
|
||||
else {
|
||||
uw_hs = 6;
|
||||
uw_vs = 10;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Kernel is working and knows about this font */
|
||||
uw_hs = uwd.uw_hs;
|
||||
uw_vs = uwd.uw_vs;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Now turn on mouse reporting so we can actually
|
||||
* make use of all this stuff.
|
||||
**************************************************/
|
||||
if((retval = ioctl(1,WIOCGETMOUSE,&umd)) != -1) {
|
||||
umd.um_flags= MSDOWN+MSUP;
|
||||
ioctl(1,WIOCSETMOUSE,&umd);
|
||||
}
|
||||
unixpcmouse = YES;
|
||||
}
|
||||
#endif
|
||||
if (mouse == YES) {
|
||||
loadmenu(mainmenu);
|
||||
}
|
||||
}
|
||||
|
||||
/* load the correct mouse menu */
|
||||
|
||||
void
|
||||
mousemenu(void)
|
||||
{
|
||||
if (mouse == YES) {
|
||||
if (changing == YES) {
|
||||
loadmenu(changemenu);
|
||||
}
|
||||
else {
|
||||
loadmenu(mainmenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* download a menu */
|
||||
|
||||
static void
|
||||
loadmenu(MENU *menu)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (emacsviterm == YES) {
|
||||
mousereinit();
|
||||
(void) printf("\033V1"); /* display the scrollbar */
|
||||
(void) printf("\033M0@%s@%s@", menu[0].text, menu[0].value);
|
||||
for (i = 1; menu[i].text != NULL; ++i) {
|
||||
(void) printf("\033M@%s@%s@", menu[i].text, menu[i].value);
|
||||
}
|
||||
}
|
||||
else { /* myx */
|
||||
int len;
|
||||
|
||||
mousecleanup();
|
||||
(void) printf("\033[6;1X\033[9;1X");
|
||||
for (i = 0; menu[i].text != NULL; ++i) {
|
||||
len = strlen(menu[i].text);
|
||||
(void) printf("\033[%d;%dx%s%s", len,
|
||||
(int) (len + strlen(menu[i].value)),
|
||||
menu[i].text, menu[i].value);
|
||||
}
|
||||
loaded = menu;
|
||||
}
|
||||
(void) fflush(stdout);
|
||||
}
|
||||
|
||||
/* reinitialize the mouse in case curses changed the attributes */
|
||||
|
||||
void
|
||||
mousereinit(void)
|
||||
{
|
||||
if (emacsviterm == YES) {
|
||||
|
||||
/* enable the mouse click and sweep coordinate control sequence */
|
||||
/* and switch to menu 2 */
|
||||
(void) printf("\033{2\033#2");
|
||||
(void) fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
/* restore the mouse attributes */
|
||||
|
||||
void
|
||||
mousecleanup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (loaded != NULL) { /* only true for myx */
|
||||
|
||||
/* remove the mouse menu */
|
||||
(void) printf("\033[6;0X\033[9;0X");
|
||||
for (i = 0; loaded[i].text != NULL; ++i) {
|
||||
(void) printf("\033[0;0x");
|
||||
}
|
||||
loaded = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* draw the scrollbar */
|
||||
|
||||
void
|
||||
drawscrollbar(int top, int bot)
|
||||
{
|
||||
int p1, p2;
|
||||
|
||||
if (emacsviterm == YES) {
|
||||
if (bot > top) {
|
||||
p1 = 16 + (top - 1) * 100 / totallines;
|
||||
p2 = 16 + (bot - 1) * 100 / totallines;
|
||||
if (p2 > 116) {
|
||||
p2 = 116;
|
||||
}
|
||||
if (p1 < 16) {
|
||||
p1 = 16;
|
||||
}
|
||||
/* don't send ^S or ^Q because it will hang a layer using cu(1) */
|
||||
if (p1 == ctrl('Q') || p1 == ctrl('S')) {
|
||||
++p1;
|
||||
}
|
||||
if (p2 == ctrl('Q') || p2 == ctrl('S')) {
|
||||
++p2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
p1 = p2 = 16;
|
||||
}
|
||||
(void) printf("\033W%c%c", p1, p2);
|
||||
}
|
||||
}
|
||||
|
||||
/* get the mouse information */
|
||||
|
||||
MOUSE *
|
||||
getmouseaction(char leading_char)
|
||||
{
|
||||
static MOUSE m;
|
||||
|
||||
#if UNIXPC
|
||||
|
||||
if(unixpcmouse == YES && leading_char == ESC) {
|
||||
|
||||
/* Called if cscope received an ESC character. See if it is
|
||||
* a mouse report and if so, decipher it. A mouse report
|
||||
* looks like: "<ESC>[?xx;yy;b;rM"
|
||||
*/
|
||||
int x = 0, y = 0, button = 0, reason = 0;
|
||||
int i;
|
||||
|
||||
/* Get a mouse report. The form is: XX;YY;B;RM where
|
||||
* XX is 1,2, or 3 decimal digits with the X pixel position.
|
||||
* Similarly for YY. B is a single decimal digit with the
|
||||
* button number (4 for one, 2 for two, and 1 for three).
|
||||
* R is the reason for the mouse report.
|
||||
*
|
||||
* In general, the input is read until the mouse report has
|
||||
* been completely read in or we have discovered that this
|
||||
* escape sequence is NOT a mouse report. In the latter case
|
||||
* return the last character read to the input stream with
|
||||
* myungetch().
|
||||
*/
|
||||
|
||||
/* Check for "[?" being next 2 chars */
|
||||
if(((i = mygetch()) != '[') || ((i = mygetch()) != '?')) {
|
||||
myungetch(i);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Grab the X position (in pixels) */
|
||||
while(isdigit(i = mygetch())) {
|
||||
x = (x*10) + (i - '0');
|
||||
}
|
||||
if(i != ';') {
|
||||
myungetch(i);
|
||||
return(NULL); /* not a mouse report after all */
|
||||
}
|
||||
|
||||
/* Grab the Y position (in pixels) */
|
||||
while(isdigit(i = mygetch())) {
|
||||
y = (y*10) + (i - '0');
|
||||
}
|
||||
if(i != ';') {
|
||||
myungetch(i);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Get which button */
|
||||
if((button = mygetch()) > '4') {
|
||||
myungetch(button);
|
||||
return(NULL);
|
||||
}
|
||||
if((i = mygetch()) != ';') {
|
||||
myungetch(i);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Get the reason for this mouse report */
|
||||
if((reason = mygetch()) > '8') {
|
||||
myungetch(reason);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* sequence should terminate with an 'M' */
|
||||
if((i = mygetch()) != 'M') {
|
||||
myungetch(i);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/* OK. We get a mouse report whenever a button is depressed
|
||||
* or released. Let's ignore the report whenever the button
|
||||
* is depressed until when I am ready to implement sweeping.
|
||||
*/
|
||||
if(reason != '2') {
|
||||
return(NULL); /* '2' means button is released */
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* Always indicate button 1 irregardless of which button was
|
||||
* really pushed.
|
||||
************************************************************/
|
||||
m.button = 1;
|
||||
|
||||
/************************************************************
|
||||
* Convert pixel coordinates to line and column coords.
|
||||
* The height and width are obtained using an ioctl() call
|
||||
* in mouseinit(). This assumes that variable width chars
|
||||
* are not being used ('though it would probably work anyway).
|
||||
************************************************************/
|
||||
|
||||
m.x1 = x/uw_hs; /* pixel/horizontal_spacing */
|
||||
m.y1 = y/uw_vs; /* pixel/vertical_spacing */
|
||||
|
||||
/* "null" out the other fields */
|
||||
m.percent = m.x2 = m.y2 = -1;
|
||||
}
|
||||
else
|
||||
#endif /* not UNIXPC */
|
||||
|
||||
if (mouse == YES && leading_char == ctrl('X')) {
|
||||
|
||||
switch (mygetch()) {
|
||||
case ctrl('_'): /* click */
|
||||
if ((m.button = mygetch()) == '0') { /* if scrollbar */
|
||||
m.percent = getpercent();
|
||||
}
|
||||
else {
|
||||
m.x1 = getcoordinate();
|
||||
m.y1 = getcoordinate();
|
||||
m.x2 = m.y2 = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ctrl(']'): /* sweep */
|
||||
m.button = mygetch();
|
||||
m.x1 = getcoordinate();
|
||||
m.y1 = getcoordinate();
|
||||
m.x2 = getcoordinate();
|
||||
m.y2 = getcoordinate();
|
||||
break;
|
||||
default:
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
else return(NULL);
|
||||
|
||||
return(&m);
|
||||
}
|
||||
|
||||
/* get a row or column coordinate from a mouse button click or sweep */
|
||||
|
||||
static int
|
||||
getcoordinate(void)
|
||||
{
|
||||
int c, next;
|
||||
|
||||
c = mygetch();
|
||||
next = 0;
|
||||
if (c == ctrl('A')) {
|
||||
next = 95;
|
||||
c = mygetch();
|
||||
}
|
||||
if (c < ' ') {
|
||||
return (0);
|
||||
}
|
||||
return (next + c - ' ');
|
||||
}
|
||||
|
||||
/* get a percentage */
|
||||
|
||||
static int
|
||||
getpercent(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = mygetch();
|
||||
if (c < 16) {
|
||||
return(0);
|
||||
}
|
||||
if (c > 120) {
|
||||
return(100);
|
||||
}
|
||||
return(c - 16);
|
||||
}
|
49
src/mygetenv.c
Normal file
49
src/mygetenv.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
#include "library.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* return the non-null environment value or the default argument */
|
||||
|
||||
char *
|
||||
mygetenv(char *variable, char *deflt)
|
||||
{
|
||||
char *value;
|
||||
|
||||
value = getenv(variable);
|
||||
if (value == NULL || *value == '\0') {
|
||||
return(deflt);
|
||||
}
|
||||
return(value);
|
||||
}
|
208
src/mypopen.c
Normal file
208
src/mypopen.c
Normal file
@ -0,0 +1,208 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include "global.h" /* pid_t, shell, and basename() */
|
||||
|
||||
#define tst(a,b) (*mode == 'r'? (b) : (a))
|
||||
#define RDR 0
|
||||
#define WTR 1
|
||||
|
||||
/* HBB 20010312: make this a bit safer --- don't blindly assume it's 1 */
|
||||
#ifdef FD_CLOEXEC
|
||||
# define CLOSE_ON_EXEC FD_CLOEXEC
|
||||
#else
|
||||
# define CLOSE_ON_EXEC 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IO_H
|
||||
# include <io.h> /* for setmode() */
|
||||
#endif
|
||||
|
||||
static pid_t popen_pid[20];
|
||||
static void (*tstat)(int);
|
||||
|
||||
int
|
||||
myopen(char *path, int flag, int mode)
|
||||
{
|
||||
/* opens a file descriptor and then sets close-on-exec for the file */
|
||||
int fd;
|
||||
|
||||
/* 20020103: if file is not explicitly in Binary mode, make
|
||||
* sure we override silly Cygwin behaviour of automatic binary
|
||||
* mode for files in "binary mounted" paths */
|
||||
#if O_BINARY != O_TEXT
|
||||
if (! (flag | O_BINARY))
|
||||
flag |= O_TEXT;
|
||||
#endif
|
||||
if(mode)
|
||||
fd = open(path, flag, mode);
|
||||
else
|
||||
fd = open(path, flag);
|
||||
|
||||
#ifdef __DJGPP__ /* FIXME: test feature, not platform */
|
||||
/* HBB 20010312: DOS GCC doesn't have FD_CLOEXEC (yet), so it
|
||||
* always fails this call. Have to skip that step */
|
||||
if(fd != -1)
|
||||
return(fd);
|
||||
#endif
|
||||
if(fd != -1 && (fcntl(fd, F_SETFD, CLOSE_ON_EXEC) != -1))
|
||||
return(fd);
|
||||
|
||||
else
|
||||
{
|
||||
/* Ensure that if the fcntl fails and fd is valid, then
|
||||
the file is closed properly. In general this should
|
||||
not happen. */
|
||||
if (fd != -1)
|
||||
{
|
||||
close (fd);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
FILE *
|
||||
myfopen(char *path, char *mode)
|
||||
{
|
||||
/* opens a file pointer and then sets close-on-exec for the file */
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(path, mode);
|
||||
|
||||
#ifdef SETMODE
|
||||
if (fp && ! strchr(mode, 'b')) {
|
||||
SETMODE(fileno(fp), O_TEXT);
|
||||
}
|
||||
#endif /* SETMODE */
|
||||
|
||||
#ifdef __DJGPP__ /* FIXME: test feature, not platform */
|
||||
/* HBB 20010312: DOS GCC doesn't have FD_CLOEXEC (yet), so it
|
||||
* always fails this call. Have to skip that step */
|
||||
if(fp)
|
||||
#else
|
||||
if(fp && (fcntl(fileno(fp), F_SETFD, CLOSE_ON_EXEC) != -1))
|
||||
#endif
|
||||
return(fp);
|
||||
|
||||
else {
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
FILE *
|
||||
mypopen(char *cmd, char *mode)
|
||||
{
|
||||
#ifdef __DJGPP__
|
||||
/* HBB 20010312: Has its own implementation of popen(), which
|
||||
* is better suited to the platform than cscope's */
|
||||
return (popen)(cmd, mode);
|
||||
#else
|
||||
int p[2];
|
||||
pid_t *poptr;
|
||||
int myside, yourside;
|
||||
pid_t pid;
|
||||
|
||||
if(pipe(p) < 0)
|
||||
return(NULL);
|
||||
myside = tst(p[WTR], p[RDR]);
|
||||
yourside = tst(p[RDR], p[WTR]);
|
||||
if((pid = fork()) == 0) {
|
||||
/* myside and yourside reverse roles in child */
|
||||
int stdio;
|
||||
|
||||
/* close all pipes from other popen's */
|
||||
for (poptr = popen_pid; poptr < popen_pid+20; poptr++) {
|
||||
if(*poptr)
|
||||
(void) close(poptr - popen_pid);
|
||||
}
|
||||
stdio = tst(0, 1);
|
||||
close(myside);
|
||||
close(stdio);
|
||||
#if V9
|
||||
dup2(yourside, stdio);
|
||||
#else
|
||||
fcntl(yourside, F_DUPFD, stdio);
|
||||
#endif
|
||||
close(yourside);
|
||||
execlp(shell, basename(shell), "-c", cmd, (void *)0);
|
||||
_exit(1);
|
||||
} else if (pid > 0)
|
||||
tstat = signal(SIGTSTP, SIG_DFL);
|
||||
if(pid == -1)
|
||||
return(NULL);
|
||||
popen_pid[myside] = pid;
|
||||
(void) close(yourside);
|
||||
return(fdopen(myside, mode));
|
||||
#endif /* DJGPP */
|
||||
}
|
||||
|
||||
/* HBB 20010705: renamed from 'pclose', which would collide with
|
||||
* system-supplied function of same name */
|
||||
int
|
||||
mypclose(FILE *ptr)
|
||||
{
|
||||
#ifdef __DJGPP__
|
||||
/* HBB 20010705: This system has its own pclose(), which we
|
||||
* don't want to replace */
|
||||
return (pclose)(ptr);
|
||||
#else
|
||||
int f;
|
||||
pid_t r;
|
||||
int status = -1;
|
||||
sighandler_t hstat, istat, qstat;
|
||||
|
||||
f = fileno(ptr);
|
||||
(void) fclose(ptr);
|
||||
istat = signal(SIGINT, SIG_IGN);
|
||||
qstat = signal(SIGQUIT, SIG_IGN);
|
||||
hstat = signal(SIGHUP, SIG_IGN);
|
||||
while((r = wait(&status)) != popen_pid[f] && r != -1)
|
||||
; /* nothing */
|
||||
if(r == -1)
|
||||
status = -1;
|
||||
(void) signal(SIGINT, istat);
|
||||
(void) signal(SIGQUIT, qstat);
|
||||
(void) signal(SIGHUP, hstat);
|
||||
(void) signal(SIGTSTP, tstat);
|
||||
/* mark this pipe closed */
|
||||
popen_pid[f] = 0;
|
||||
return(status);
|
||||
#endif /* DJGPP */
|
||||
}
|
159
src/opt.c
Normal file
159
src/opt.c
Normal file
@ -0,0 +1,159 @@
|
||||
#include "global.h"
|
||||
|
||||
#include "build.h"
|
||||
#include "vp.h"
|
||||
#include "version.h" /* FILEVERSION and FIXVERSION */
|
||||
#include "scanner.h"
|
||||
|
||||
#include <stdlib.h> /* atoi */
|
||||
#include <getopt.h>
|
||||
|
||||
BOOL remove_symfile_onexit = NO;
|
||||
BOOL onesearch; /* one search only in line mode */
|
||||
char *reflines; /* symbol reference lines file */
|
||||
|
||||
char ** parse_options(int *argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
int longind;
|
||||
char path[PATHLEN + 1]; /* file path */
|
||||
char *s;
|
||||
int argcc = *argc;
|
||||
|
||||
struct option lopts[] = {
|
||||
{"help", 0, NULL, 'h'},
|
||||
{"version", 0, NULL, 'V'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argcc, argv,
|
||||
"hVbcCdeF:f:I:i:kLl0:1:2:3:4:5:6:7:8:9:P:p:qRs:TUuvX",
|
||||
lopts, &longind)) != -1) {
|
||||
switch(opt) {
|
||||
|
||||
case '?':
|
||||
usage();
|
||||
myexit(1);
|
||||
break;
|
||||
case 'X':
|
||||
remove_symfile_onexit = YES;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
/* The input fields numbers for line mode operation */
|
||||
field = opt - '0';
|
||||
if (strlen(optarg) > PATHLEN) {
|
||||
postfatal("\
|
||||
cscope: pattern too long, cannot be > \
|
||||
%d characters\n", PATLEN);
|
||||
}
|
||||
strcpy(Pattern, optarg);
|
||||
break;
|
||||
case 'b': /* only build the cross-reference */
|
||||
buildonly = YES;
|
||||
linemode = YES;
|
||||
break;
|
||||
case 'c': /* ASCII characters only in crossref */
|
||||
compress = NO;
|
||||
break;
|
||||
case 'C': /* turn on caseless mode for symbol searches */
|
||||
caseless = YES;
|
||||
egrepcaseless(caseless); /* simulate egrep -i flag */
|
||||
break;
|
||||
case 'd': /* consider crossref up-to-date */
|
||||
isuptodate = YES;
|
||||
break;
|
||||
case 'e': /* suppress ^E prompt between files */
|
||||
editallprompt = NO;
|
||||
break;
|
||||
case 'h':
|
||||
longusage();
|
||||
myexit(1);
|
||||
break;
|
||||
case 'k': /* ignore DFLT_INCDIR */
|
||||
kernelmode = YES;
|
||||
break;
|
||||
case 'L':
|
||||
onesearch = YES;
|
||||
/* FALLTHROUGH */
|
||||
case 'l':
|
||||
linemode = YES;
|
||||
break;
|
||||
case 'v':
|
||||
verbosemode = YES;
|
||||
break;
|
||||
case 'V':
|
||||
fprintf(stderr, "%s: version %d%s\n", argv0,
|
||||
FILEVERSION, FIXVERSION);
|
||||
myexit(0);
|
||||
break;
|
||||
case 'q': /* quick search */
|
||||
invertedindex = YES;
|
||||
break;
|
||||
case 'T': /* truncate symbols to 8 characters */
|
||||
trun_syms = YES;
|
||||
break;
|
||||
case 'u': /* unconditionally build the cross-reference */
|
||||
unconditional = YES;
|
||||
break;
|
||||
case 'U': /* assume some files have changed */
|
||||
fileschanged = YES;
|
||||
break;
|
||||
case 'R':
|
||||
recurse_dir = YES;
|
||||
break;
|
||||
case 'f': /* alternate cross-reference file */
|
||||
reffile = optarg;
|
||||
if (strlen(reffile) > sizeof(path) - 3) {
|
||||
postfatal("\
|
||||
cscope: reffile too long, cannot \
|
||||
be > %d characters\n", sizeof(path) - 3);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
strcpy(path, reffile);
|
||||
|
||||
s = path + strlen(path);
|
||||
strcpy(s, ".in");
|
||||
/*coverity[overwrite_var]*/
|
||||
invname = strdup(path);
|
||||
strcpy(s, ".po");
|
||||
/*coverity[overwrite_var]*/
|
||||
invpost = strdup(path);
|
||||
break;
|
||||
|
||||
case 'F': /* symbol reference lines file */
|
||||
reflines = optarg;
|
||||
break;
|
||||
case 'i': /* file containing file names */
|
||||
namefile = optarg;
|
||||
break;
|
||||
case 'I': /* #include file directory */
|
||||
includedir(optarg);
|
||||
break;
|
||||
case 'p': /* file path components to display */
|
||||
dispcomponents = atoi(optarg);
|
||||
break;
|
||||
case 'P': /* prepend path to file names */
|
||||
prependpath = optarg;
|
||||
break;
|
||||
case 's': /* additional source file directory */
|
||||
sourcedir(optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This adjusts argv so that we only see the remaining
|
||||
* args. Its ugly, but we need to do it so that the rest
|
||||
* of the main routine doesn't get all confused
|
||||
*/
|
||||
*argc = *argc - optind;
|
||||
return argv + optind;
|
||||
}
|
94
src/scanner.h
Normal file
94
src/scanner.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 2001, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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 CSCOPE_SCANNER_H
|
||||
#define CSCOPE_SCANNER_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#undef YYLMAX
|
||||
#define YYLMAX STMTMAX + PATLEN + 1 /* scanner line buffer size */
|
||||
|
||||
/* cross-reference database mark characters (when new ones are added,
|
||||
* update the cscope.out format description in cscope.1)
|
||||
*/
|
||||
#define CLASSDEF 'c'
|
||||
#define DEFINE '#'
|
||||
#define DEFINEEND ')'
|
||||
#define ENUMDEF 'e'
|
||||
#define FCNCALL '`'
|
||||
#define FCNDEF '$'
|
||||
#define FCNEND '}'
|
||||
#define GLOBALDEF 'g'
|
||||
#define INCLUDE '~'
|
||||
#define MEMBERDEF 'm'
|
||||
#define NEWFILE '@'
|
||||
#define STRUCTDEF 's'
|
||||
#define TYPEDEF 't'
|
||||
#define UNIONDEF 'u'
|
||||
|
||||
/* other scanner token types */
|
||||
#define LEXEOF 0
|
||||
#define LEXERR 1
|
||||
#define IDENT 2
|
||||
#define NEWLINE 3
|
||||
|
||||
/* scanner.l global data */
|
||||
extern int first; /* buffer index for first char of symbol */
|
||||
extern int last; /* buffer index for last char of symbol */
|
||||
extern int lineno; /* symbol line number */
|
||||
extern FILE *yyin; /* input file descriptor */
|
||||
extern FILE *yyout; /* output file */
|
||||
extern int myylineno; /* input line number */
|
||||
|
||||
#ifdef USING_LEX
|
||||
/* HBB 20010430: if lex is used instead of flex, have to simulate the
|
||||
* private copies of yytext and yytext for the world outside scanner.l: */
|
||||
/* FIXME: there should be a feature test for this! */
|
||||
#if defined(__OSF1__) || defined(__sun) || defined(_AIX)
|
||||
extern char yytext[];
|
||||
#else
|
||||
extern unsigned char yytext[];
|
||||
#endif
|
||||
extern int yyleng;
|
||||
# define my_yytext yytext
|
||||
# define my_yyleng yyleng
|
||||
#else
|
||||
extern char *my_yytext; /* private copy of input line */
|
||||
extern size_t my_yyleng; /* ... and current length of it */
|
||||
#endif
|
||||
|
||||
/* The master function exported by scanner.l */
|
||||
int yylex(void);
|
||||
void initscanner(char *srcfile);
|
||||
|
||||
#endif /* CSCOPE_SCANNER_H ends */
|
45
src/version.h
Normal file
45
src/version.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* cscope - interactive C symbol cross-reference
|
||||
*
|
||||
* Changing the cross-reference file part of the program version
|
||||
* forces rebuilding of the cross-reference.
|
||||
*/
|
||||
|
||||
#ifndef CSCOPE_VERSION_H
|
||||
#define CSCOPE_VERSION_H
|
||||
|
||||
#define FILEVERSION 15 /* Initial Open Source and Linux Port */
|
||||
#define FIXVERSION ".9" /* feature and bug fix version */
|
||||
|
||||
#endif /* CSCOPE_VERSION_H */
|
70
src/vp.h
Normal file
70
src/vp.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/*
|
||||
* VPATH assumptions:
|
||||
* VPATH is the environment variable containing the view path
|
||||
* where each path name is followed by ':', '\n', or '\0'.
|
||||
* Embedded blanks are considered part of the path.
|
||||
*/
|
||||
|
||||
#ifndef CSCOPE_VP_H
|
||||
#define CSCOPE_VP_H
|
||||
|
||||
#define MAXPATH 200 /* max length for entire name */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#else
|
||||
# define HAVE_FCNTL_H 1 /* in case of doubt, assume it's there */
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h> /* needed for O_... open flags */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !NOMALLOC
|
||||
extern char **vpdirs; /* directories (including current) in view path */
|
||||
#else
|
||||
#define MAXDIR 25 /* same as libVP */
|
||||
#define DIRLEN 80 /* same as libVP */
|
||||
extern char vpdirs[MAXDIR][DIRLEN + 1];
|
||||
#endif
|
||||
extern int vpndirs; /* number of directories in view path */
|
||||
|
||||
void vpinit(char *current_dir);
|
||||
int vpopen(char *path, int oflag);
|
||||
int vpaccess(char *path, mode_t amode);
|
||||
|
||||
#endif /* CSCOPE_VP_H */
|
57
src/vpaccess.c
Normal file
57
src/vpaccess.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* vpaccess - view path version of the access system call */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "vp.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
int
|
||||
vpaccess(char *path, mode_t amode)
|
||||
{
|
||||
char buf[MAXPATH + 1];
|
||||
int returncode;
|
||||
int i;
|
||||
|
||||
if ((returncode = access(path, amode)) == -1 && path[0] != '/') {
|
||||
vpinit(NULL);
|
||||
for (i = 1; i < vpndirs; i++) {
|
||||
(void) snprintf(buf, sizeof(buf), "%s/%s", vpdirs[i], path);
|
||||
if ((returncode = access(buf, amode)) != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(returncode);
|
||||
}
|
62
src/vpfopen.c
Normal file
62
src/vpfopen.c
Normal file
@ -0,0 +1,62 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* vpfopen - view path version of the fopen library function */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "vp.h"
|
||||
#include "global.h"
|
||||
|
||||
FILE *
|
||||
vpfopen(char *filename, char *type)
|
||||
{
|
||||
char buf[MAXPATH + 1];
|
||||
FILE *returncode;
|
||||
int i;
|
||||
|
||||
if ((returncode = myfopen(filename, type)) == NULL
|
||||
&& filename[0] != '/'
|
||||
/* && strcmp(type, "r") == 0 */ /* HBB: this breaks if type=="rb" */
|
||||
&& type[0] == 'r'
|
||||
) {
|
||||
vpinit(NULL);
|
||||
for (i = 1; i < vpndirs; i++) {
|
||||
(void) snprintf(buf, sizeof(buf), "%s/%s", vpdirs[i], filename);
|
||||
if ((returncode = myfopen(buf, type)) != NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return(returncode);
|
||||
}
|
169
src/vpinit.c
Normal file
169
src/vpinit.c
Normal file
@ -0,0 +1,169 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
/* vpinit - initialize vpdirs or update vpdirs based on currentdir */
|
||||
|
||||
#include <stdio.h> /* stderr */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "vp.h"
|
||||
|
||||
#include "library.h"
|
||||
#include "global.h"
|
||||
#include "constants.h"
|
||||
|
||||
#if !NOMALLOC
|
||||
char **vpdirs; /* directories (including current) in view path */
|
||||
#else
|
||||
char vpdirs[MAXDIR][DIRLEN + 1];
|
||||
#define MAXVPATH (MAXDIR * (DIRLEN + 1))
|
||||
#endif
|
||||
int vpndirs; /* number of directories in view path */
|
||||
|
||||
void
|
||||
vpinit(char *current_dir)
|
||||
{
|
||||
char *suffix; /* path from view path node */
|
||||
char *vpath; /* VPATH environment variable value */
|
||||
char buf[MAXPATH + 1];
|
||||
int i;
|
||||
char *s;
|
||||
#if NOMALLOC
|
||||
char *node; /* view path node */
|
||||
char vpathbuf[MAXVPATH + 1];
|
||||
#endif
|
||||
|
||||
/* if an existing directory list is to be updated, free it */
|
||||
if (current_dir != NULL && vpndirs > 0) {
|
||||
#if !NOMALLOC
|
||||
for (i = 0; i < vpndirs; ++i) {
|
||||
free(vpdirs[i]);
|
||||
}
|
||||
free(vpdirs);
|
||||
#endif
|
||||
vpndirs = 0;
|
||||
}
|
||||
/* return if the directory list has been computed */
|
||||
/* or there isn't a view path environment variable */
|
||||
if (vpndirs > 0 || (vpath = getenv("VPATH")) == NULL ||
|
||||
*vpath == '\0') {
|
||||
return;
|
||||
}
|
||||
/* if not given, get the current directory name */
|
||||
if (current_dir == NULL && (current_dir = getcwd(buf, MAXPATH)) == NULL) {
|
||||
(void) fprintf(stderr, "%s: cannot get current directory name\n", argv0);
|
||||
return;
|
||||
}
|
||||
/* see if this directory is in the first view path node */
|
||||
for (i = 0; vpath[i] == current_dir[i] && vpath[i] != '\0'; ++i) {
|
||||
;
|
||||
}
|
||||
if ((vpath[i] != ':' && vpath[i] != '\0') ||
|
||||
(current_dir[i] != '/' && current_dir[i] != '\0')) {
|
||||
return;
|
||||
}
|
||||
suffix = ¤t_dir[i];
|
||||
#if !NOMALLOC
|
||||
|
||||
/* count the nodes in the view path */
|
||||
vpndirs = 1;
|
||||
for (i = 0; vpath[i] != '\0'; ++i) {
|
||||
if (vpath[i] == ':' && vpath[i + 1]) {
|
||||
++vpndirs;
|
||||
}
|
||||
}
|
||||
/* create the source directory list */
|
||||
vpdirs = malloc(vpndirs * sizeof(*vpdirs));
|
||||
|
||||
/* don't change VPATH in the environment */
|
||||
vpath = strdup(vpath);
|
||||
|
||||
/* split the view path into nodes */
|
||||
for (i = 0, s = vpath; *s != '\0'; ++i) {
|
||||
vpdirs[i] = s;
|
||||
while (*s != '\0' && *++s != ':') {
|
||||
if (*s == '\n') {
|
||||
*s = '\0';
|
||||
}
|
||||
}
|
||||
if (*s != '\0') {
|
||||
*s++ = '\0';
|
||||
}
|
||||
}
|
||||
/* convert the view path nodes to directories */
|
||||
for (i = 0; i < vpndirs; ++i) {
|
||||
s = malloc(strlen(vpdirs[i]) + strlen(suffix) + 1);
|
||||
(void) strcpy(s, vpdirs[i]);
|
||||
(void) strcat(s, suffix);
|
||||
vpdirs[i] = s;
|
||||
}
|
||||
free(vpath);
|
||||
#else
|
||||
/* don't change VPATH in the environment */
|
||||
if (strlen(vpath) > MAXVPATH) {
|
||||
(void) fprintf(stderr, "%s: VPATH is longer than %d characters: %s\n", argv0, MAXVPATH, vpath);
|
||||
return;
|
||||
}
|
||||
(void) strcpy(vpathbuf, vpath);
|
||||
s = vpathbuf;
|
||||
|
||||
/* convert the view path nodes to directories */
|
||||
while (*s != '\0') {
|
||||
|
||||
/* get the next node */
|
||||
node = s;
|
||||
while (*s != '\0' && *++s != ':') {
|
||||
if (*s == '\n') {
|
||||
*s = '\0';
|
||||
}
|
||||
}
|
||||
if (*s != '\0') {
|
||||
*s++ = '\0';
|
||||
}
|
||||
/* ignore a directory that is too long */
|
||||
if (strlen(node) + strlen(suffix) > DIRLEN) {
|
||||
(void) fprintf(stderr, "%s: VPATH directory is longer than %d characters: %s%s\n", argv0, DIRLEN, node, suffix);
|
||||
}
|
||||
else if (vpndirs >= MAXDIR) {
|
||||
(void) fprintf(stderr, "%s: VPATH has more than %d nodes\n", argv0, vpndirs);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* create the view path directory */
|
||||
(void) strcpy(vpdirs[vpndirs], node);
|
||||
(void) strcat(vpdirs[vpndirs], suffix);
|
||||
++vpndirs;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
60
src/vpopen.c
Normal file
60
src/vpopen.c
Normal file
@ -0,0 +1,60 @@
|
||||
/*===========================================================================
|
||||
Copyright (c) 1998-2000, The Santa Cruz Operation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
*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.
|
||||
|
||||
*Neither name of The Santa Cruz Operation 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 COPYRIGHT HOLDERS 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.
|
||||
=========================================================================*/
|
||||
|
||||
|
||||
/* vpopen - view path version of the open system call */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "global.h"
|
||||
#include "vp.h"
|
||||
|
||||
#define OPENFLAG_READ 0
|
||||
|
||||
int
|
||||
vpopen(char *path, int oflag)
|
||||
{
|
||||
char buf[MAXPATH + 1];
|
||||
int returncode;
|
||||
int i;
|
||||
|
||||
if ((returncode = myopen(path, oflag, 0666)) == -1 && path[0] != '/' &&
|
||||
oflag == OPENFLAG_READ) {
|
||||
vpinit(NULL);
|
||||
for (i = 1; i < vpndirs; i++) {
|
||||
(void) snprintf(buf, sizeof(buf), "%s/%s", vpdirs[i], path);
|
||||
if ((returncode = myopen(buf, oflag, 0666)) != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(returncode);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user