Compare commits

..

1 Commits

Author SHA1 Message Date
Frank Lanitz
40fcc7984c Add a meta file for funding 2020-10-29 13:37:00 +01:00
996 changed files with 76004 additions and 161539 deletions

View File

@ -1,228 +0,0 @@
#
# Copyright: 2021, The Geany contributors
# License: GNU GPL v2 or later
name: CI Build
on:
push:
branches:
- master
pull_request:
branches:
- master
# cancel already running builds of the same branch or pull request
concurrency:
group: ci-${{ github.head_ref }} || concat(${{ github.ref }}
cancel-in-progress: true
env:
CFLAGS: -g -O2 -Werror=pointer-arith -Werror=implicit-function-declaration
CCACHE_DIR: ${{ github.workspace }}/.ccache
CCACHE_COMPRESS: true
CCACHE_MAXSIZE: 1G
PYTHON: python3
DEBUG: 0
jobs:
linux:
name: Linux Build (BINRELOC=${{ matrix.binreloc }})
runs-on: ubuntu-18.04
strategy:
fail-fast: false
matrix:
include:
- binreloc: no
- binreloc: yes
env:
CONFIGURE_FLAGS: --enable-binreloc=${{ matrix.binreloc }}
CC: ccache gcc
CXX: ccache g++
steps:
- uses: actions/checkout@v2
# create and use a timestamp for the cache key: GH Actions will never update a cache
# only use an existing cache item or create a new one. To use an existing cache *and*
# push back the the updated cache after build, we use a always new cache key (to force
# the creation of the cache item at the end) in combination with "restore-keys" as fallback
- name: Prepare ccache timestamp
id: ccache_cache_timestamp
run: echo "::set-output name=timestamp::$(date +%Y-%m-%d-%H-%M)"
- name: Configure ccache
uses: actions/cache@v2
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ runner.os }}-${{ github.job }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }}
restore-keys: ${{ runner.os }}-${{ github.job }}-ccache-
- name: Show environment
run: env | sort
if: ${{ env.DEBUG == '1' }}
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install --assume-yes --no-install-recommends \
ccache \
gettext autopoint \
libtool \
libgtk-3-dev \
doxygen \
python3-docutils \
python3-lxml \
rst2pdf
- name: Configure
run: |
NOCONFIGURE=1 ./autogen.sh
mkdir _build
cd _build
{ ../configure $CONFIGURE_FLAGS || { cat config.log; exit 1; } ; }
- name: Build
run: |
cd _build
make
- name: Run Tests
run: |
cd _build
make -j2 check
- name: Run distcheck
run: |
cd _build
make -j2 distcheck DISTCHECK_CONFIGURE_FLAGS="$CONFIGURE_FLAGS";
- name: ccache statistics
run: ccache --show-stats
if: ${{ env.DEBUG == '1' }}
linux-meson:
name: Linux Meson Build
runs-on: ubuntu-20.04
strategy:
fail-fast: false
env:
CC: ccache gcc
CXX: ccache g++
steps:
- uses: actions/checkout@v2
# create and use a timestamp for the cache key: GH Actions will never update a cache
# only use an existing cache item or create a new one. To use an existing cache *and*
# push back the the updated cache after build, we use a always new cache key (to force
# the creation of the cache item at the end) in combination with "restore-keys" as fallback
- name: Prepare ccache timestamp
id: ccache_cache_timestamp
run: echo "::set-output name=timestamp::$(date +%Y-%m-%d-%H-%M)"
- name: Configure ccache
uses: actions/cache@v2
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ runner.os }}-${{ github.job }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }}
restore-keys: ${{ runner.os }}-${{ github.job }}-ccache-
- name: Show environment
run: env | sort
if: ${{ env.DEBUG == '1' }}
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install --assume-yes --no-install-recommends \
ccache \
gettext autopoint \
libtool \
libgtk-3-dev \
doxygen \
python3-docutils \
python3-lxml \
rst2pdf \
meson
- name: Configuration
run: |
meson _build
- name: Build
run: |
ninja -C _build
- name: Run Tests
run: |
ninja -C _build test
# distcheck not applicable, meson exports the source tree per git-archive
- name: ccache statistics
run: ccache --show-stats
if: ${{ env.DEBUG == '1' }}
mingw:
name: Mingw Build
# i686-w64-mingw32-pkg-config fails with weird error message on 20.04
runs-on: ubuntu-18.04
env:
CC: ccache i686-w64-mingw32-gcc
CXX: ccache i686-w64-mingw32-g++
steps:
- uses: actions/checkout@v2
# create and use a timestamp for the cache key: GH Actions will never update a cache
# only use an existing cache item or create a new one. To use an existing cache *and*
# push back the the updated cache after build, we use a always new cache key (to force
# the creation of the cache item at the end) in combination with "restore-keys" as fallback
- name: Prepare ccache timestamp
id: ccache_cache_timestamp
run: echo "::set-output name=timestamp::$(date +%Y-%m-%d-%H-%M)"
- name: Configure ccache
uses: actions/cache@v2
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ runner.os }}-${{ github.job }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }}
restore-keys: ${{ runner.os }}-${{ github.job }}-ccache-
- name: Show environment
run: env | sort
if: ${{ env.DEBUG == '1' }}
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install --assume-yes --no-install-recommends \
ccache \
gettext autopoint \
libtool \
mingw-w64-tools \
g++-mingw-w64-i686 \
gcc-mingw-w64-i686 \
binutils-mingw-w64-i686 \
doxygen \
python3-docutils \
python3-lxml \
rst2pdf
# fix broken pkg-config-crosswrapper, see https://bugs.launchpad.net/ubuntu/+source/mingw-w64/+bug/1327242
sudo sed -e 's/PKG_CONFIG_PATH=/&$PKG_CONFIG_PATH:/' -i /usr/bin/i686-w64-mingw32-pkg-config
- name: Run autogen.sh
run: |
NOCONFIGURE=1 ./autogen.sh
- name: Build
run: |
sh ./scripts/cross-build-mingw.sh;
- name: ccache statistics
run: ccache --show-stats
if: ${{ env.DEBUG == '1' }}

46
.gitignore vendored
View File

@ -17,12 +17,8 @@ Makefile.in
#-----------------------------------------------------------------------
# / (root)
#-----------------------------------------------------------------------
/ABOUT-NLS
/aclocal.m4
/autom4te.cache
/build/
/builddir/
/build-*/
/build-aux/
/build-stamp
/codenames
@ -34,7 +30,6 @@ Makefile.in
/config.status
/config.sub
/configure
/data/filedefs/filetypes.python
/debian
/depcomp
/geany.1
@ -45,43 +40,14 @@ Makefile.in
/geany.nsi
/global.tags.old
/install-sh
/intltool
/intltool-*
/libtool
/localwin32.mk
/ltmain.sh
/m4/lt*.m4
/m4/intltool.m4
/m4/libtool.m4
/m4/codeset.m4
/m4/extern-inline.m4
/m4/fcntl-o.m4
/m4/gettext.m4
/m4/glibc2.m4
/m4/glibc21.m4
/m4/iconv.m4
/m4/intdiv0.m4
/m4/intl.m4
/m4/intldir.m4
/m4/intlmacosx.m4
/m4/intmax.m4
/m4/inttypes-pri.m4
/m4/inttypes_h.m4
/m4/lcmessage.m4
/m4/lib-ld.m4
/m4/lib-link.m4
/m4/lib-prefix.m4
/m4/lock.m4
/m4/longlong.m4
/m4/nls.m4
/m4/po.m4
/m4/printf-posix.m4
/m4/progtest.m4
/m4/size_max.m4
/m4/stdint_h.m4
/m4/threadlib.m4
/m4/uintmax_t.m4
/m4/visibility.m4
/m4/wchar_t.m4
/m4/wint_t.m4
/m4/xsize.m4
/make_deb.sh
/missing
/mkinstalldirs
@ -98,8 +64,10 @@ Makefile.in
/po/ChangeLog.save
/po/*.gmo
/po/*.header
/po/.intltool-merge-cache
/po/LINGUAS
/po/Makefile.in.in
/po/Makevars.template
/po/Makevars
/po/*.mo
/po/*.pot
/po/POTFILES
@ -110,7 +78,7 @@ Makefile.in
/po/*.sed
/po/*.sin
/po/stamp-it
/po/stamp-po
/po/.intlcache
#-----------------------------------------------------------------------
# /src/

43
.travis.yml Normal file
View File

@ -0,0 +1,43 @@
# we use both C and C++, so advertize C++
language: cpp
cache: ccache
dist: trusty
compiler:
- gcc
env:
- GTK2=no BINRELOC=no
- GTK2=yes BINRELOC=no
- GTK2=no BINRELOC=yes
- GTK2=yes BINRELOC=yes
- GTK2=no MINGW=yes
- GTK2=yes MINGW=yes
before_install:
- sudo apt-get update -qq
install:
- sudo apt-get install -y intltool libtool
- test -n "$MINGW" || sudo apt-get install -y libgtk2.0-dev libgtk-3-dev
- test -z "$MINGW" || sudo apt-get install -y mingw-w64-tools g++-mingw-w64-i686 gcc-mingw-w64-i686 binutils-mingw-w64-i686
# fix broken pkg-config-crosswrapper, see https://bugs.launchpad.net/ubuntu/+source/mingw-w64/+bug/1327242
- test -z "$MINGW" || sudo sed -e 's/PKG_CONFIG_PATH=/&$PKG_CONFIG_PATH:/' -i /usr/bin/i686-w64-mingw32-pkg-config
- sudo apt-get install -y python-docutils rst2pdf
# try not to install doxygen-latex because we don't need it and it's huge
- sudo apt-get install -y --no-install-recommends doxygen
- sudo apt-get install -y python-lxml
before_script:
- export CFLAGS="-g -O2 -Werror=pointer-arith -Werror=implicit-function-declaration"
script:
- NOCONFIGURE=1 ./autogen.sh
- >
if [ -n "$MINGW" ]; then
arg=-3; [ "$GTK2" = yes ] && arg=-2;
unset CC CXX;
sh ./scripts/cross-build-mingw.sh $arg;
else
CONFIGURE_FLAGS="--enable-gtk2=$GTK2 --enable-binreloc=$BINRELOC";
mkdir _build &&
cd _build &&
{ ../configure $CONFIGURE_FLAGS || { cat config.log; exit 1; } ; } &&
make -j2 &&
make -j2 check &&
make -j2 distcheck DISTCHECK_CONFIGURE_FLAGS="$CONFIGURE_FLAGS";
fi

2
FUNDING.yml Normal file
View File

@ -0,0 +1,2 @@
# These are supported funding model platforms
liberapay: Geany

88
HACKING
View File

@ -113,7 +113,7 @@ it's for.
Plugin API code
---------------
Please be aware that anything with a doc-comment (a comment with an
extra asterisk: ``/**``) is something in the plugin API. Things like
extra asterix: ``/**``) is something in the plugin API. Things like
enums and structs can usually still be appended to, ensuring that all
the existing elements stay in place - this will keep the ABI stable.
@ -126,18 +126,10 @@ the existing elements stay in place - this will keep the ABI stable.
Keeping the plugin ABI stable
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In general the ABI changes as little as we can manage. The ABI number
must match exactly between Geany and plugins, so an ABI change breaks
all plugins until they are re-compiled. But sometimes it is absolutely
necessary. Removing a feature or significantly changing the semantics
of an existing feature require an ABI change since existing plugins may
no longer work with the modified version of Geany.
The API identifying number is increased whenever anything is added to
the API so plugins can test if the feature is available. The API number
required by a plugin needs only to be lower than the API Geany provides,
so an increase in API number without a change in ABI will not stop
plugins that need a lower number from working.
Before the 1.0 release series, the ABI can change when necessary, and
even the API can change. An ABI change just means that all plugins will
not load and they must be rebuilt. An API change means that some plugins
might not build correctly.
If you're reordering or changing existing elements of structs that are
used as part of the plugin API, you must increment GEANY_ABI_VERSION
@ -175,11 +167,11 @@ unmanageable diffs.
GTK versions & API documentation
--------------------------------
Geany requires GTK >= 3.0 and GLib >= 2.32. API symbols from newer GTK/GLib
versions should be avoided or made optional to keep the source code building
on older systems.
Geany requires GTK >= 2.24 or GTK 3 (with the --enable-gtk3 configure option)
and GLib >= 2.32. API symbols from newer GTK/GLib versions should be
avoided or made optional to keep the source code building on older systems.
It is recommended to use the 3.0 API documentation of the GTK
It is recommended to use the 2.24 API documentation of the GTK
libs (including GLib, GDK and Pango) has the advantages
that you don't get confused by any newer API additions and you
don't have to take care about whether you can use them or not.
@ -204,8 +196,8 @@ Coding
them down into smaller static functions where possible. This makes code
much easier to read and maintain.
* Use GLib types and functions - gint not int, g_free() not free().
* Your code should build against GLib 2.32 and GTK 3.0. At least for the
moment, we want to keep the minimum requirement for GTK at 3.0 (of
* Your code should build against GLib 2.32 and GTK 2.24. At least for the
moment, we want to keep the minimum requirement for GTK at 2.24 (of
course, you can use the GTK_CHECK_VERSION macro to protect code using
later versions).
* Variables should be declared (and initialized) as close as practical
@ -500,13 +492,13 @@ other changes should be passed on to the maintainers at
http://scintilla.org. We normally update to a new Scintilla release
shortly after one is made. See also scintilla/README.
We use an unmodified subset of universal-ctags sources
(https://github.com/universal-ctags/ctags) to parse open documents. We
also use the great majority of unmodified universal-ctags parsers except
a few outliers that are maintained by us (those whose file names start
with `geany_`). We normally update to the latest version of
universal-ctags shortly after making a Geany release and keep this
version during the rest of the development cycle.
Tagmanager was originally taken from Anjuta 1.2.2, and parts of it
(notably c.c) have been merged from later versions of Anjuta and
CTags. The independent Tagmanager library itself ceased development
before Geany was started. It's source code parsing is mostly taken from
Exuberant CTags (see http://ctags.sf.net). If appropriate it's good to
pass language parser changes back to the CTags project.
Notes
=====
@ -650,40 +642,53 @@ indentation after ':' is done from on_new_line_added().
If the Scintilla lexer supports user type keyword highlighting (e.g.
SCLEX_CPP), update document_update_tags() in document.c.
Adding a CTags parser
^^^^^^^^^^^^^^^^^^^^^
Adding a TagManager parser
^^^^^^^^^^^^^^^^^^^^^^^^^^
This assumes the filetype for Geany already exists.
First write or find a CTags compatible parser, foo.c. Check this fork:
https://github.com/universal-ctags/ctags
There may be some unmerged language patches for CTags at:
http://sf.net/projects/ctags - see the tracker.
(You can also try the Anjuta project's anjuta-tags codebase.)
.. note::
From Geany 1.22 GLib's GRegex engine is used instead of POSIX
regex, unlike CTags. It should be close enough to POSIX to work
OK.
We no longer support regex parsers with the "b" regex flag
option set and Geany will print debug warnings if it's used.
CTags supports it but doesn't currently (2011) include any
parsers that use it. It should be easy to convert to extended
regex syntax anyway.
Method
``````
* Add foo.c to SRCS in Makefile.am.
* Add Foo to src/tagmanager/tm_parsers.h
* Add Foo to parsers.h
* Add TM_PARSER_FOO to src/tagmanager/tm_parser.h. The list here must follow
exactly the order in src/tagmanager/tm_parsers.h.
exactly the order in parsers.h.
In src/tagmanager/tm_parser.c:
Add a map_FOO TMParserMapEntry mapping each kind's letter from foo.c's
FooKinds to the appropriate TMTagType, and add the corresponding
MAP_ENTRY(FOO) to parser_map.
(You may want to make the symbols.c change before doing this).
In src/tagmanager/tm_parser.c:
Add a group_FOO TMParserMapGroup defining root nodes of the symbol tree,
used icons and TMTagType values grouped under the specified root.
Multiple TMTagType values can be combined under a single root using |
(bitwise OR).
In src/tagmanager/tm_parser.c:
Update various functions at the end of tm_parser.c to adjust Geany
behavior to the behavior of the added parser. In particular, update
tm_parser_scope_separator() and tm_parser_has_full_scope() so
scope-related functionality works correctly.
Update tm_parser_context_separator() and tm_parser_has_full_context() to
handle the new parser if applicable, by adding a TM_PARSER_FOO case entry.
In filetypes.c, init_builtin_filetypes():
Set the 2nd argument of the FT_INIT() macro for this filetype to FOO.
In symbols.c:
Unless your parser uses C-like tag type kinds, update
add_top_level_items() for foo, calling tag_list_add_groups(). See
get_tag_type_iter() for which tv_iters fields to use.
Tests
`````
The tag parser tests checks if the proper tags are emitted
@ -786,6 +791,9 @@ Building Plugins
The geany-plugins autotools script automatically detects the
installed system Geany and builds the plugins against that.
Plugins will build with either GTK2 or GTK3, whichever the detected
Geany was built with.
To use plugins with a development version of Geany built with
a different prefix, the plugins will need to be compiled against
that version if the ABI has changed.

404
INSTALL
View File

@ -1,368 +1,182 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free
Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell command './configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the 'README' file for
instructions specific to this package. Some packages provide this
'INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
These are generic installation instructions.
The 'configure' shell script attempts to guess correct values for
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a 'Makefile' in each directory of the package.
It may also create one or more '.h' files containing system-dependent
definitions. Finally, it creates a shell script 'config.status' that
you can run in the future to recreate the current configuration, and a
file 'config.log' containing compiler output (useful mainly for
debugging 'configure').
It can also use an optional file (typically called 'config.cache' and
enabled with '--cache-file=config.cache' or simply '-C') that saves the
results of its tests to speed up reconfiguring. Caching is disabled by
default to prevent problems with accidental use of stale cache files.
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how 'configure' could check whether to do them, and mail
diffs or instructions to the address given in the 'README' so they can
be considered for the next release. If you are using the cache, and at
some point 'config.cache' contains results you don't want to keep, you
may remove or edit it.
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file 'configure.ac' (or 'configure.in') is used to create
'configure' by a program called 'autoconf'. You need 'configure.ac' if
you want to change it or regenerate 'configure' using a newer version of
'autoconf'.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
The simplest way to compile this package is:
1. 'cd' to the directory containing the package's source code and type
'./configure' to configure the package for your system.
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running 'configure' might take a while. While running, it prints
some messages telling which features it is checking for.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type 'make' to compile the package.
2. Type `make' to compile the package.
3. Optionally, type 'make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type 'make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the 'make install' phase executed with root
privileges.
4. Type `make install' to install the programs and any data files and
documentation.
5. Optionally, type 'make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior 'make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing 'make clean'. To also remove the
files that 'configure' created (so you can compile the package for
a different kind of computer), type 'make distclean'. There is
also a 'make maintainer-clean' target, but that is intended mainly
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type 'make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide 'make
distcheck', which can by used by developers to test that all other
targets like 'make install' and 'make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the 'configure' script does not know about. Run './configure --help'
for details on some of the pertinent environment variables.
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
You can give 'configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here is
an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU 'make'. 'cd' to the
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the 'configure' script. 'configure' automatically checks for the source
code in the directory that 'configure' is in and in '..'. This is known
as a "VPATH" build.
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
With a non-GNU 'make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use 'make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple '-arch' options to the
compiler but only a single '-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the 'lipo' tool if you have problems.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, 'make install' installs the package's commands under
'/usr/local/bin', include files under '/usr/local/include', etc. You
can specify an installation prefix other than '/usr/local' by giving
'configure' the option '--prefix=PREFIX', where PREFIX must be an
absolute file name.
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like '--bindir=DIR' to specify different values for particular
kinds of files. Run 'configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the default
for these options is expressed in terms of '${prefix}', so that
specifying just '--prefix' will affect all of the other directory
specifications that were not explicitly provided.
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
The most portable way to affect installation locations is to pass the
correct locations to 'configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
'make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, 'make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
'${prefix}'. Any directories that were specified during 'configure',
but not in terms of '${prefix}', must each be overridden at install time
for the entire installation to be relocated. The approach of makefile
variable overrides for each directory variable is required by the GNU
Coding Standards, and ideally causes no recompilation. However, some
platforms have known limitations with the semantics of shared libraries
that end up requiring recompilation when using this method, particularly
noticeable in packages that use GNU Libtool.
The second method involves providing the 'DESTDIR' variable. For
example, 'make install DESTDIR=/alternate/directory' will prepend
'/alternate/directory' before all installation names. The approach of
'DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of '${prefix}'
at 'configure' time.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving 'configure' the
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
Some packages pay attention to '--enable-FEATURE' options to
'configure', where FEATURE indicates an optional part of the package.
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
is something like 'gnu-as' or 'x' (for the X Window System). The
'README' should mention any '--enable-' and '--with-' options that the
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, 'configure' can usually
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the 'configure' options '--x-includes=DIR' and
'--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of 'make' will be. For these packages, running './configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with 'make V=1'; while running './configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with 'make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX 'make' updates targets which have the same timestamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
workaround. If GNU CC is not installed, it is therefore recommended to
try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
in your 'PATH', put it _after_ '/usr/bin'.
On Haiku, software installed for all users goes in '/boot/common',
not '/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features 'configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, 'configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
'--build=TYPE' option. TYPE can either be a short name for the system
type, such as 'sun4', or a canonical name which has the form:
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
OS
KERNEL-OS
See the file 'config.sub' for the possible values of each field. If
'config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option '--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with '--host=TYPE'.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for 'configure' scripts to share,
you can create a site shell script called 'config.site' that gives
default values for variables like 'CC', 'cache_file', and 'prefix'.
'configure' looks for 'PREFIX/share/config.site' if it exists, then
'PREFIX/etc/config.site' if it exists. Or, you can set the
'CONFIG_SITE' environment variable to the location of the site script.
A warning: not all 'configure' scripts look for a site script.
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
Operation Controls
==================
Variables not defined in a site shell script can be set in the
environment passed to 'configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the 'configure' command line, using 'VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified 'gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
Autoconf limitation. Until the limitation is lifted, you can use this
workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
'configure' Invocation
======================
'configure' recognizes the following options to control how it
`configure' recognizes the following options to control how it
operates.
'--help'
'-h'
Print a summary of all of the options to 'configure', and exit.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
'--help=short'
'--help=recursive'
Print a summary of the options unique to this package's
'configure', and exit. The 'short' variant lists options used only
in the top level, while the 'recursive' variant lists options also
present in any nested packages.
`--help'
Print a summary of the options to `configure', and exit.
'--version'
'-V'
Print the version of Autoconf used to generate the 'configure'
script, and exit.
'--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally 'config.cache'. FILE defaults to '/dev/null' to
disable caching.
'--config-cache'
'-C'
Alias for '--cache-file=config.cache'.
'--quiet'
'--silent'
'-q'
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to '/dev/null' (any error
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
'--srcdir=DIR'
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
'configure' can determine that directory automatically.
`configure' can determine that directory automatically.
'--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names:: for
more details, including other options available for fine-tuning the
installation locations.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
'--no-create'
'-n'
Run the configure checks, but stop before creating any output
files.
'configure' also accepts some other, not widely useful, options. Run
'configure --help' for more details.
`configure' also accepts some other, not widely useful, options.

View File

@ -15,18 +15,22 @@ WIN32_BUILD_FILES = \
EXTRA_DIST = \
autogen.sh \
scripts/gen-api-gtkdoc.py \
scripts/gen-signallist.sh \
scripts/print-tags.py \
geany.desktop.in \
geany.pc.in \
ChangeLog.pre-1-22 \
HACKING \
README.I18N \
README.Packagers \
intltool-extract.in \
intltool-merge.in \
intltool-update.in \
$(WIN32_BUILD_FILES)
DISTCLEANFILES = \
geany.desktop
geany.desktop \
intltool-extract \
intltool-merge \
intltool-update
uninstall-local:
rm -rf $(DESTDIR)$(pkgdatadir);
@ -75,8 +79,6 @@ pkgconfig_DATA = geany.pc
pkgconfigdir = $(libdir)/pkgconfig
desktopdir = $(datadir)/applications
desktop_in_files = geany.desktop.in
desktop_in_files = geany.desktop
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
$(desktop_DATA): $(desktop_in_files) $(wildcard $(top_srcdir)/po/*.po)
$(AM_V_GEN)$(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@
@INTLTOOL_DESKTOP_RULE@

44
NEWS
View File

@ -1,46 +1,4 @@
Geany 1.39 (unreleased)
Interface
* The document list in the sidebar has a new tree view. This mode is the
new default and existing installations automatically use it (PR#1813).
Geany 1.38 (October 09, 2021)
General
* Increase speed when opening documents, especially on startup
(Justin Blanchard, Issue#2883, Issue#2649, Issue#2791, PR#2884, PR#2747).
* Synchronize Geany's Ctags implementation with Universal Ctags, this
leads to updated symbol parsers (Jiří Techet, PR#2666).
* Remove GTK+2 Support (PR#2602).
* Geany needs a C++17 compiler to build (PR#2862).
Bug fixes
* Workaround crashes when pasting into VTE without having focus
(Issue#2813, PR#2843).
Interface
* Add keybinding to reload all open documents (David Yang, PR#2859).
Filetypes
* Add Julia filetype (getzze, Issue#434, PR#2584).
* Add Meson filetype (Andy Alt, PR#2850).
Plugins
* SaveActions: add configurable target directory for instantly saved files
(Issue#640, PR#2769).
Windows
* Fix message window height after restart (Issue#2591, PR#2892).
* Switch Windows builds to GTK3 and x86_64 (PR#2590).
Internationalization
* Updated translations: da, de, el, es, et, fr, it, ja, nl pt, pt BR,
sk, tr, uk, zh_CN
Geany 1.37.1 (November 08, 2020)
Windows
* Fix crash on first startup (Issue#2639, PR#2645).
Geany 1.38 (unreleased)
Geany 1.37 (October 25, 2020)

48
README
View File

@ -49,10 +49,10 @@ Installation from sources
Requirements
++++++++++++
For compiling Geany yourself, you will need the GTK3 libraries and
header files. You will also need its dependency libraries and header
files, such as Pango, Glib and ATK. All these files are available at
https://www.gtk.org.
For compiling Geany yourself, you will need the GTK2 (>= 2.24) or
GTK3 libraries and header files. You will also need its dependency libraries
and header files, such as Pango, Glib and ATK. All these files are
available at https://www.gtk.org.
Furthermore you need, of course, a C compiler and the Make tool; a C++
compiler is also needed for the required Scintilla library included. The
@ -78,42 +78,10 @@ and open the online version instead when requested.
Installing from a Git clone
+++++++++++++++++++++++++++
Using the Meson build system
++++++++++++++++++++++++++++
N.B. Meson support is still incomplete and a work-in-progress.
Meson requires to chose a separate build directory. Either create
one, or let meson do it:
`meson build` or `mkdir build; cd build; meson ..`
Either command will configure the build system. The system is probed
in many ways and system-dependant build files are created. This includes
location of dependencies and compiler and linker flags required for them.
To build Geany, follow with a `meson compile -C build`
To install Geany, follow the build with a `sudo meson install -C build`.
By default, meson will install Geany to `/usr/local`. A different
prefix can be selected at the initial command or via reconfiguration:
`meson --prefix /opt build` or `meson configure --prefix /opt build`
Geany has some selectable features that may reduce the required
build and runtime dependencies. See meson_optionts.txt for a full list.
To turn a feature off, use `-D<feature>=false` when configuring the build,
for example: `meson configure -Dvte=false build`
Using Autotools
+++++++++++++++
Install Autotools (*autopoint*, *automake*, *autoconf* and *libtool*),
*gettext*, and the GLib development files **before** running any of the
following commands, as well as *rst2html* from Docutils (see above for
details). Then, run ``./autogen.sh`` and then follow the instructions for
Install Autotools (*automake*, *autoconf* and *libtool*), *intltool*,
and the GLib development files **before** running any of the following
commands, as well as *rst2html* from Docutils (see above for details).
Then, run ``./autogen.sh`` and then follow the instructions for
`installing from a release tarball`_.
Installing from a release tarball

3
THANKS
View File

@ -143,9 +143,6 @@ Jacek Wolszczak <shutdownrunner(at)o2(dot)pl> - pl_PL
Jarosław Foksa <jfoksa(at)gmail(dot)com> - pl_PL
Krzysztof Troska <elleander86(at)gmail(dot)com> - pl_PL
Wojciech Świderski <woj.swiderski@gmail.com> - pl_PL
André Glória <gloria(dot)andre(at)gmail(dot)com> - pt
Pedro Albuquerque <pmra@protonmail.com> - pt
Hugo Carvalho <hugokarvalho@hotmail.com> - pt
Alexandre Moreira <alexandream(at)gmail(dot)com> - pt_BR
Adrovane Marques Kade <adrovane(at)gmail(dot)com> - pt_BR
Rafael Peregrino da Silva <rperegrino(at)linuxnewmedia(dot)com(dot)br> - pt_BR

View File

@ -1,8 +1,6 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
set -e
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
@ -13,6 +11,39 @@ DIE=0
exit 1
}
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`autoconf' installed."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
(intltoolize --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`intltool' installed."
echo "You can get it from:"
echo " ftp://ftp.gnome.org/pub/GNOME/"
DIE=1
}
(glib-gettextize --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`glib' installed."
echo "You can get it from: ftp://ftp.gtk.org/pub/gtk"
DIE=1
}
(libtoolize --version) < /dev/null > /dev/null 2>&1 || {
(glibtoolize --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`libtool' installed."
echo "You can get it from:"
echo " http://www.gnu.org/software/libtool/"
DIE=1
}
}
(pkg-config --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have pkg-config installed to compile $package."
@ -21,6 +52,28 @@ DIE=0
DIE=1
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`automake' (1.7 or later) installed."
echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
DIE=1
NO_AUTOMAKE=yes
}
# if no automake, don't bother testing for aclocal
test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: Missing \`aclocal'. The version of \`automake'"
echo "installed doesn't appear recent enough."
echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
if test "$DIE" -eq 1; then
exit 1
fi
if test -z "$*" -a "$NOCONFIGURE" != 1; then
echo "**Warning**: I am going to run \`configure' with no arguments."
echo "If you wish to pass any to it, please specify them on the"
@ -30,7 +83,14 @@ fi
echo "Processing configure.ac"
(cd $srcdir; autoreconf --install --verbose)
test -d build-aux || mkdir build-aux
echo "no" | glib-gettextize --force --copy
intltoolize --copy --force --automake
libtoolize --copy --force || glibtoolize --copy --force
aclocal -I m4
autoheader
automake --add-missing --copy --gnu
autoconf
if [ "$NOCONFIGURE" = 1 ]; then
echo "Done. configure skipped."
@ -38,3 +98,4 @@ if [ "$NOCONFIGURE" = 1 ]; then
fi
echo "Running $srcdir/configure $@ ..."
$srcdir/configure "$@" && echo "Now type 'make' to compile." || exit 1

View File

@ -1,7 +1,7 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.60])
AC_INIT([Geany], [1.39],
AC_INIT([Geany], [1.38],
[https://github.com/geany/geany/issues])
AC_CONFIG_SRCDIR([src/geany.h])
AC_CONFIG_AUX_DIR([build-aux])
@ -9,13 +9,6 @@ AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.11 -Wall parallel-tests subdir-objects])
AC_CONFIG_HEADERS([config.h])
# Silence "AC_LINK_IFELSE before AC_USE_SYSTEM_EXTENSIONS" warnings
# Note: Enables _GNU_SOURCE on Linux
AC_USE_SYSTEM_EXTENSIONS
AM_GNU_GETTEXT_VERSION([0.19.8])
AM_GNU_GETTEXT([external])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
GEANY_PREFIX
@ -27,39 +20,31 @@ if test -n "${build}" -a -n "${target}"; then
GEANY_STATUS_ADD([Building Geany for], [${target}])
fi
# why do we use this?
AC_USE_SYSTEM_EXTENSIONS
m4_ifdef([AM_PROG_AR],[AM_PROG_AR])
LT_INIT([disable-static])
AC_PROG_CC
AC_PROG_CC_C99
AM_PROG_CC_C_O
AC_PROG_CXX
GEANY_PROG_CXX
AX_CXX_COMPILE_STDCXX_17
AX_CXX_COMPILE_STDCXX_11
AC_PROG_INSTALL
AC_PROG_LN_S
if test "$ac_cv_prog_cc_c99" = "no"; then
AC_MSG_ERROR([Need a C99 compiler])
fi
# autoscan start
# Checks for header files.
AC_CHECK_HEADERS([fcntl.h stdlib.h sys/time.h errno.h limits.h])
AC_CHECK_HEADERS([fcntl.h glob.h stdlib.h sys/time.h errno.h limits.h])
# Checks for dependencies needed by ctags
AC_CHECK_HEADERS([dirent.h fnmatch.h direct.h io.h sys/dir.h])
AC_DEFINE([HAVE_STDBOOL_H], [1], [whether or not to use <stdbool.h>.])
AC_CHECK_FUNC([regcomp],
[have_regcomp=yes],
[have_regcomp=no
dnl various stuff for ctags/gnu_regex/
AC_CHECK_HEADERS([langinfo.h locale.h libintl.h wctype.h wchar.h])
AC_CHECK_FUNCS([memcpy isblank wcrtomb mbrtowc wcscoll])
AC_FUNC_ALLOCA])
AM_CONDITIONAL([USE_BUNDLED_REGEX], [test "xno" = "x$have_regcomp"])
AC_CHECK_FUNC([fnmatch], [have_fnmatch=yes], [have_fnmatch=no])
AM_CONDITIONAL([USE_BUNDLED_FNMATCH], [test "xno" = "x$have_fnmatch"])
AC_CHECK_HEADERS([fnmatch.h direct.h io.h sys/dir.h])
AC_DEFINE([USE_STDBOOL_H], [1], [whether or not to use <stdbool.h>.])
AC_DEFINE([CTAGS_LIB], [1], [compile ctags as a library.])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_OFF_T
@ -67,11 +52,9 @@ AC_TYPE_SIZE_T
AC_STRUCT_TM
# Checks for library functions.
AC_CHECK_FUNCS([realpath])
AC_CHECK_FUNCS([fgetpos fnmatch mkstemp strerror strstr realpath])
# Function checks for u-ctags
AC_CHECK_FUNCS([strerror strstr asprintf])
AC_CHECK_FUNCS([mkstemp tempnam], [break])
AC_CHECK_FUNCS([strcasecmp stricmp], [break])
AC_CHECK_FUNCS([strncasecmp strnicmp], [break])
AC_CHECK_FUNCS([truncate ftruncate chsize], [break])
@ -88,8 +71,45 @@ AC_CHECK_DECLS([_NSGetEnviron],,,[[#include <crt_externs.h>]])
GEANY_CHECK_REVISION([dnl force debug mode for a VCS working copy
CFLAGS="-g -DGEANY_DEBUG $CFLAGS"])
GEANY_CHECK_GTK
GEANY_CHECK_GTK_FUNCS([g_strv_equal])
# GTK version check
AC_ARG_ENABLE([gtk2],
[AS_HELP_STRING([--enable-gtk2],
[compile against deprecated GTK2 [default=no]])],
[enable_gtk2=$enableval],
[enable_gtk2=no])
gtk2_package=gtk+-2.0
gtk2_min_version=2.24
gtk3_package=gtk+-3.0
gtk3_min_version=3.0
AS_IF([test "x$enable_gtk2" = "xyes"],
[gtk_package=$gtk2_package
gtk_min_version=$gtk2_min_version],
[gtk_package=$gtk3_package
gtk_min_version=$gtk3_min_version])
AM_CONDITIONAL([GTK3], [test "x$gtk_package" = "x$gtk3_package"])
# GTK/GLib/GIO checks
gtk_modules="$gtk_package >= $gtk_min_version glib-2.0 >= 2.32"
gtk_modules_private="gio-2.0 >= 2.32 gmodule-no-export-2.0"
PKG_CHECK_MODULES([GTK], [$gtk_modules $gtk_modules_private])
AC_SUBST([DEPENDENCIES], [$gtk_modules])
AS_VAR_APPEND([GTK_CFLAGS], [" -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_32"])
dnl Disable all GTK deprecations on 3.x so long as we want to keep 2.x support and only require 3.0.
dnl No need on 2.x as we target the latest version.
AM_COND_IF([GTK3], [AS_VAR_APPEND([GTK_CFLAGS], [" -DGDK_DISABLE_DEPRECATION_WARNINGS"])])
AC_SUBST([GTK_CFLAGS])
AC_SUBST([GTK_LIBS])
GTK_VERSION=`$PKG_CONFIG --modversion $gtk_package`
AC_SUBST([GTK_VERSION])
GEANY_STATUS_ADD([Using GTK version], [${GTK_VERSION}])
# GTHREAD checks
gthread_modules="gthread-2.0"
PKG_CHECK_MODULES([GTHREAD], [$gthread_modules])
AC_SUBST([GTHREAD_CFLAGS])
AC_SUBST([GTHREAD_LIBS])
# --disable-deprecated switch for GTK purification
AC_ARG_ENABLE([deprecated],
@ -112,14 +132,13 @@ GEANY_CHECK_VTE
GEANY_CHECK_MAC_INTEGRATION
GEANY_CHECK_THE_FORCE dnl hehe
AC_SUBST([GETTEXT_PACKAGE],[$PACKAGE])
AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$PACKAGE"], [Gettext package.])
# i18n
GEANY_I18N
# double eval since datarootdir is usually defined as ${prefix}/share
AM_COND_IF([MINGW],
[pkgdatadir='${prefix}/data'],
[pkgdatadir='${datarootdir}/geany'])
AM_COND_IF([MINGW],[LIBS="$LIBS -liconv"])
AC_SUBST([GEANY_DATA_DIR], [$(eval echo $(eval echo $pkgdatadir))])
AC_SUBST([pkgdatadir])
@ -158,6 +177,7 @@ AC_CONFIG_FILES([
icons/tango/scalable/Makefile
ctags/Makefile
scintilla/Makefile
scintilla/include/Makefile
src/Makefile
src/tagmanager/Makefile
plugins/Makefile
@ -168,6 +188,7 @@ AC_CONFIG_FILES([
doc/geany.1
geany.pc
geany.nsi
doc/Doxyfile
tests/Makefile
tests/ctags/Makefile
])

View File

@ -1,8 +1,6 @@
AM_CPPFLAGS = \
-I$(srcdir)/main \
-I$(srcdir)/parsers \
-I$(srcdir)/dsl \
-DEXTERNAL_PARSER_LIST_FILE=\"$(top_srcdir)/src/tagmanager/tm_parsers.h\" \
-DG_LOG_DOMAIN=\"CTags\"
AM_CFLAGS = \
$(GTK_CFLAGS) \
@ -11,155 +9,88 @@ AM_CFLAGS = \
noinst_LTLIBRARIES = libctags.la
parsers = \
parsers/cxx/cxx.c \
parsers/cxx/cxx_debug.c \
parsers/cxx/cxx_debug.h \
parsers/cxx/cxx_debug_type.c \
parsers/cxx/cxx_keyword.c \
parsers/cxx/cxx_keyword.h \
parsers/cxx/cxx_parser_block.c \
parsers/cxx/cxx_parser.c \
parsers/cxx/cxx_parser_function.c \
parsers/cxx/cxx_parser.h \
parsers/cxx/cxx_parser_internal.h \
parsers/cxx/cxx_parser_lambda.c \
parsers/cxx/cxx_parser_namespace.c \
parsers/cxx/cxx_parser_template.c \
parsers/cxx/cxx_parser_tokenizer.c \
parsers/cxx/cxx_parser_typedef.c \
parsers/cxx/cxx_parser_using.c \
parsers/cxx/cxx_parser_variable.c \
parsers/cxx/cxx_qtmoc.c \
parsers/cxx/cxx_scope.c \
parsers/cxx/cxx_scope.h \
parsers/cxx/cxx_subparser.c \
parsers/cxx/cxx_subparser.h \
parsers/cxx/cxx_subparser_internal.h \
parsers/cxx/cxx_tag.c \
parsers/cxx/cxx_tag.h \
parsers/cxx/cxx_token.c \
parsers/cxx/cxx_token_chain.c \
parsers/cxx/cxx_token_chain.h \
parsers/cxx/cxx_token.h \
parsers/cpreprocessor.c \
parsers/cpreprocessor.h \
parsers/abaqus.c \
parsers/abc.c \
parsers/ada.c \
parsers/asciidoc.c \
parsers/asm.c \
parsers/basic.c \
parsers/bibtex.c \
parsers/geany_c.c \
parsers/clojure.c \
parsers/c.c \
parsers/cobol.c \
parsers/iniconf.c \
parsers/iniconf.h \
parsers/css.c \
parsers/diff.c \
parsers/geany_docbook.c \
parsers/docbook.c \
parsers/erlang.c \
parsers/flex.c \
parsers/fortran.c \
parsers/gdscript.c \
parsers/go.c \
parsers/haskell.c \
parsers/haxe.c \
parsers/html.c \
parsers/jscript.c \
parsers/json.c \
parsers/julia.c \
parsers/geany_lcpp.c \
parsers/geany_lcpp.h \
parsers/lisp.c \
parsers/lua.c \
parsers/make.c \
parsers/make.h \
parsers/markdown.c \
parsers/markdown.h \
parsers/geany_matlab.c \
parsers/matlab.c \
parsers/nsis.c \
parsers/objc.c \
parsers/pascal.c \
parsers/perl.c \
parsers/perl.h \
parsers/php.c \
parsers/powershell.c \
parsers/python.c \
parsers/r.c \
parsers/r.h \
parsers/rst.c \
parsers/ruby.c \
parsers/rust.c \
parsers/sh.c \
parsers/sql.c \
parsers/tcl.c \
parsers/tcl.h \
parsers/tcloo.c \
parsers/tex.c \
parsers/tex.h \
parsers/txt2tags.c \
parsers/typescript.c \
parsers/verilog.c \
parsers/vhdl.c
# skip cmd.c and mini-geany.c which define main()
# also skip lregex-pcre2.c which we don't use
libctags_la_SOURCES = \
dsl/optscript.c \
dsl/optscript.h \
dsl/es.c \
dsl/es.h \
main/args.c \
main/args_p.h \
main/colprint.c \
main/colprint_p.h \
main/CommonPrelude.c \
main/args.h \
main/ctags.h \
main/debug.c \
main/ctags-api.c \
main/ctags-api.h \
main/debug.h \
main/dependency.c \
main/debug.c \
main/dependency.h \
main/dependency_p.h \
main/dependency.c \
main/e_msoft.h \
main/entry.c \
main/entry.h \
main/entry_p.h \
main/entry_private.c \
main/error.c \
main/error_p.h \
main/error.h \
main/field.c \
main/field.h \
main/field_p.h \
main/flags.c \
main/flags_p.h \
main/flags.h \
main/fmt.c \
main/fmt_p.h \
main/fmt.h \
main/gcc-attr.h \
main/general.h \
main/gvars.h \
main/htable.c \
main/htable.h \
main/inline.h \
main/interactive_p.h \
main/keyword.c \
main/keyword.h \
main/keyword_p.h \
main/kind.c \
main/kind.h \
main/kind_p.h \
main/lcpp.c \
main/lcpp.h \
main/lregex.c \
main/lregex.h \
main/lregex_p.h \
main/lregex-default.c \
main/lxcmd.c \
main/lxpath.c \
main/lxpath.h \
main/lxpath_p.h \
main/main.c \
main/main_p.h \
main/mbcs.c \
main/main.h \
main/mbcs.h \
main/mbcs_p.h \
main/mio.c \
main/mio.h \
main/nestlevel.c \
@ -170,100 +101,37 @@ libctags_la_SOURCES = \
main/objpool.h \
main/options.c \
main/options.h \
main/options_p.h \
main/param.c \
main/param.h \
main/param_p.h \
main/output-ctags.c \
main/output.h \
main/parse.c \
main/parse.h \
main/parse_p.h \
main/parsers_p.h \
main/portable-dirent_p.h \
main/portable-scandir.c \
main/parsers.h \
main/pcoproc.c \
main/pcoproc.h \
main/promise.c \
main/promise.h \
main/promise_p.h \
main/ptag.c \
main/ptag_p.h \
main/ptag.h \
main/ptrarray.c \
main/ptrarray.h \
main/rbtree.c \
main/rbtree.h \
main/read.c \
main/read.h \
main/read_p.h \
main/repoinfo.c \
main/repoinfo.h \
main/routines.c \
main/routines.h \
main/routines_p.h \
main/script.c \
main/script_p.h \
main/seccomp.c \
main/selectors.c \
main/selectors.h \
main/sort.c \
main/sort_p.h \
main/stats.c \
main/stats_p.h \
main/sort.h \
main/strlist.c \
main/strlist.h \
main/subparser.h \
main/subparser_p.h \
main/tokeninfo.c \
main/tokeninfo.h \
main/trace.c \
main/trace.h \
main/trashbox.c \
main/trashbox.h \
main/trashbox_p.h \
main/types.h \
main/unwindi.c \
main/unwindi.h \
main/vstring.c \
main/vstring.h \
main/writer-ctags.c \
main/writer-etags.c \
main/writer-json.c \
main/writer-xref.c \
main/writer.c \
main/writer_p.h \
main/xtag.c \
main/xtag.h \
main/xtag_p.h \
main/xtag.c \
$(parsers)
libctags_la_LIBADD =
# build bundled GNU regex if needed
if USE_BUNDLED_REGEX
noinst_LTLIBRARIES += libgnu_regex.la
libgnu_regex_la_SOURCES = \
gnu_regex/regex.c \
gnu_regex/regex.h
# regex.c includes other sources we have to distribute
EXTRA_libgnu_regex_la_SOURCES = \
gnu_regex/regcomp.c \
gnu_regex/regex.c \
gnu_regex/regex.h \
gnu_regex/regex_internal.c \
gnu_regex/regex_internal.h \
gnu_regex/regexec.c
libgnu_regex_la_CPPFLAGS = -D__USE_GNU
EXTRA_DIST = \
gnu_regex/README.txt
libctags_la_LIBADD += libgnu_regex.la
AM_CPPFLAGS += -I$(srcdir)/gnu_regex
endif
# build bundled fnmatch if needed
if USE_BUNDLED_FNMATCH
noinst_LTLIBRARIES += libfnmatch.la
libfnmatch_la_SOURCES = \
fnmatch/fnmatch.c \
fnmatch/fnmatch.h
libctags_la_LIBADD += libfnmatch.la
AM_CPPFLAGS += -I$(srcdir)/fnmatch
endif

File diff suppressed because it is too large Load Diff

View File

@ -1,274 +0,0 @@
/*
Copyright (c) 2009 Masatake YAMATO
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */
#ifndef __ES_LANG_C_STDC99_H__
#define __ES_LANG_C_STDC99_H__
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include "mio.h"
#ifdef __cplusplus
extern "C" {
#endif
enum _EsType {
ES_TYPE_NIL,
ES_TYPE_INTEGER,
ES_TYPE_REAL,
ES_TYPE_BOOLEAN,
ES_TYPE_SYMBOL,
ES_TYPE_STRING,
ES_TYPE_CONS,
ES_TYPE_REGEX,
/* ... */
ES_TYPE_ERROR,
/* ... */
ES_TYPE_BUILTIN_LAST = ES_TYPE_ERROR,
ES_TYPE_FOREIGNER_START,
};
typedef enum _EsType EsType;
struct _EsObject;
typedef struct _EsObject EsObject;
const char* es_type_get_name (int t);
EsType es_object_get_type (const EsObject* object);
EsObject* es_object_ref (EsObject* object);
void es_object_unref (EsObject* object);
void es_object_unref_batch (EsObject* array[],
unsigned int count);
EsObject* es_object_autounref (EsObject* object);
int es_object_equal (const EsObject* self,
const EsObject* other);
int es_atom (const EsObject* object);
#define ES_ERROR_MEMORY es_error_intern("MEMORY-EXHAUSTED")
#define ES_ERROR_REGEX es_error_intern("WRONG-REGEX-SYNTAX")
/*
* Nil
*/
#define es_nil ((EsObject*)0)
int es_null (const EsObject* object);
/*
* Integer
*/
EsObject* es_integer_new (int value);
int es_integer_p (const EsObject* object);
int es_integer_get (const EsObject* object);
/*
* Real
*/
EsObject* es_real_new (double value);
int es_real_p (const EsObject* object);
double es_real_get (const EsObject* object);
/*
* Use Integer as Real
*/
int es_number_p (const EsObject* object);
double es_number_get (const EsObject* object);
/*
* Boolean
*/
#define es_true (es_boolean_new(1))
#define es_false (es_boolean_new(0))
EsObject* es_boolean_new (int value);
int es_boolean_p (const EsObject* object);
int es_boolean_get (const EsObject* object);
/*
* String
*/
EsObject* es_string_new (const char* value);
EsObject* es_string_newL (const char* value, size_t length);
int es_string_p (const EsObject* object);
const char* es_string_get (const EsObject* object);
/*
* Symbol
*/
EsObject* es_symbol_intern (const char* name);
int es_symbol_p (const EsObject* object);
const char* es_symbol_get (const EsObject* object);
void* es_symbol_set_data (const EsObject* object, void *data);
void* es_symbol_get_data (const EsObject* object);
/*
* Error
*/
EsObject* es_error_intern (const char* name);
int es_error_p (const EsObject* object);
const char* es_error_name (const EsObject* object);
EsObject* es_error_set_object (EsObject* error, EsObject* object);
EsObject* es_error_get_object (const EsObject* error);
/*
* Cons
*/
EsObject* es_cons (EsObject* car, EsObject* cdr);
int es_cons_p (const EsObject* object);
int es_list_p (const EsObject* object);
EsObject* es_car (const EsObject* object);
EsObject* es_cdr (const EsObject* object);
/*
* Regex
*/
EsObject* es_regex_compile (const char* pat,
int case_insensitive);
int es_regex_p (const EsObject* object);
EsObject* es_regex_exec (const EsObject* regex,
const EsObject* str);
/*
* Foreign pointer
*/
EsType es_type_define_pointer (const char *name,
void (* freefn) (void *),
int (* equalfn) (const void*, const void*),
void (* printfn) (const void*, MIO *));
/* If the type has sized fat area, the area is filled with zero. */
EsObject* es_pointer_new (EsType type, void *ptr);
void* es_pointer_get (const EsObject *object);
void* es_pointer_take (EsObject *object);
/*
* Fatptr: Foreign pointer with extra data
*
* init_fat () returns es_true if the initialization ends successfully.
* In failure case, init_fat () returns an error object.
*/
EsType es_type_define_fatptr (const char *name,
size_t fat_size,
EsObject *(* initfat_fn) (void *fat, void * ptr, void *extra),
void (* freefn) (void * ptr, void *fat),
int (* equalfn) (const void* ptr_a, const void* fat_a,
const void* ptr_b, const void* fat_b),
void (* printfn) (const void* ptr, const void *fat, MIO *));
/* If initfat_fn is given in the type, the new fat area will is
* initialized with the method.
* If initfat_fn is not given, and extra is not NULL, the contents
* pointed by extra is copied to the fat area.
* If initfat_fn is not given, and extra is NULL, the fat area
* is filled with zero as es_pointer_new does. */
EsObject* es_fatptr_new (EsType type, void *ptr, void *extra);
/* Access to the fat area. Use es_pointer_get to access the pointer. */
void* es_fatptr_get (const EsObject *object);
/*
* Print
*/
void es_print (const EsObject* object,
MIO* out);
char* es_print_to_string (EsObject* object);
/*
* Read
*/
EsObject* es_read (MIO* in);
EsObject* es_read_from_string(const char* in,
const char** saveptr);
#define ES_READER_ERROR es_error_intern("READ-ERROR")
#define ES_READER_EOF es_error_intern("EOF")
/*
* Comment
*/
void es_comment (const char* comment,
MIO* out);
char* es_comment_to_string (const char* comment);
/*
* Autounref pool
*/
void es_autounref_pool_push(void);
void es_autounref_pool_pop (void);
/*
* List builders
*/
EsObject* es_list (EsObject* object,...);
EsObject* es_append (EsObject* list,...);
EsObject* es_reverse (EsObject* cons);
#define ES_PROC_UNIMPLEMENTED es_error_intern("PROC-UNIMPLEMENTED")
EsObject* es_realize (EsObject* fmt_object,...);
EsObject* es_srealize (const char* fmt,...);
/* The value returned from FN treated as if it is returned from
* a *_new function. es_map may call es_object_unref() for the value.
* The value returned from es_map should be treated as if it is
* returned from a *_new function. The caller must free the returned
* value.
*/
EsObject* es_map (EsObject * (*fn) (EsObject *, void *),
EsObject *list, void *user_data);
/* Unlike es_map, the value returnd from FN is not accumulated.
* If FN returns a value other than #f, es_foreach stops the
* iteration immediately and returns the value.
*/
EsObject* es_foreach (EsObject * (*fn) (EsObject *, void *),
EsObject *list, void *user_data);
/* The memory management of es_map is also applicable to es_fold. */
EsObject* es_fold (EsObject * (*kons) (EsObject *, EsObject *, void *),
EsObject * knil, EsObject * list, void *user_data);
/*
* Rich element accessors
*/
int es_match (EsObject* input, EsObject* fmt_object,...);
int es_smatch (EsObject* input, const char* fmt,...);
EsObject* es_pget (EsObject* plist, EsObject* key, EsObject* default_value);
#ifdef __cplusplus
}
#endif
#endif /* Not def: __ES_LANG_C_STDC_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,88 +0,0 @@
/*
* Copyright (c) 2020, Masatake YAMATO
* Copyright (c) 2020, Red Hat, Inc.
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*/
#ifndef OPTSCRIPT_H
#define OPTSCRIPT_H
#include "general.h"
#include "es.h"
#include "mio.h"
#include "ptrarray.h"
typedef struct sOptVM OptVM;
typedef EsObject* (* OptOperatorFn) (OptVM *, EsObject *);
struct OptHelpExtender {
void (* add) (ptrArray *, void *);
const char* (* get_help_str) (EsObject *, void *);
};
int opt_init (void);
OptVM *opt_vm_new (MIO *in, MIO *out, MIO *err);
void opt_vm_delete (OptVM *vm);
EsObject *opt_vm_read (OptVM *vm, MIO *in);
EsObject *opt_vm_eval (OptVM *vm, EsObject *obj);
void opt_vm_report_error (OptVM *vm, EsObject *eobj, MIO *err);
void *opt_vm_set_app_data (OptVM *vm, void *app_data);
void *opt_vm_get_app_data (OptVM *vm);
char *opt_vm_set_prompt (OptVM *vm, char *prompt);
void opt_vm_print_prompt (OptVM *vm);
int opt_vm_help (OptVM *vm, MIO *out,
struct OptHelpExtender *extop, void *data);
void opt_vm_clear (OptVM *vm);
void opt_vm_dstack_push (OptVM *vm, EsObject *dict);
void opt_vm_dstack_pop (OptVM *vm);
EsObject* opt_vm_ostack_top (OptVM *vm);
EsObject* opt_vm_ostack_peek (OptVM *vm, int index_from_top);
EsObject* opt_vm_ostack_pop (OptVM *vm);
void opt_vm_ostack_push (OptVM *vm, EsObject *obj);
unsigned int opt_vm_ostack_count (OptVM *vm);
EsObject *opt_dict_new (unsigned int size);
bool opt_dict_known_and_get_cstr (EsObject *dict, const char* name, EsObject **val);
bool opt_dict_foreach (EsObject *dict, bool (* fn) (EsObject *, EsObject *, void*), void *data);
void opt_dict_def (EsObject *dict, EsObject *sym, EsObject *val);
bool opt_dict_undef (EsObject *dict, EsObject *sym);
void opt_dict_clear (EsObject *dict);
EsObject *opt_array_new (void);
EsObject *opt_array_get (const EsObject *array, unsigned int index);
void opt_array_put (EsObject *array, unsigned int index, EsObject *obj);
void opt_array_add (EsObject *array, EsObject *elt);
unsigned int opt_array_length(const EsObject *array);
EsObject *opt_operator_new (OptOperatorFn op, const char *name, int arity, const char *help_str);
EsObject *opt_string_new_from_cstr (const char *cstr);
const char* opt_string_get_cstr (const EsObject *str);
EsObject *opt_name_new_from_cstr (const char *cstr);
const char* opt_name_get_cstr (const EsObject *name);
extern EsObject *OPT_ERR_TYPECHECK;
extern EsObject *OPT_ERR_QUIT;
extern EsObject *OPT_ERR_RANGECHECK;
extern EsObject *OPT_ERR_UNDERFLOW;
extern int OPT_TYPE_ARRAY;
extern int OPT_TYPE_DICT;
extern int OPT_TYPE_OPERATOR;
extern int OPT_TYPE_STRING;
extern int OPT_TYPE_NAME;
extern int OPT_TYPE_MARK;
#endif

View File

@ -1,190 +0,0 @@
/* Copyright (C) 1992 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details. */
/* Modified slightly by Brian Berliner <berliner@sun.com> and
Jim Blandy <jimb@cyclic.com> for CVS use */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Some file systems are case-insensitive. If FOLD_FN_CHAR is
#defined, it maps the character C onto its "canonical" form. In a
case-insensitive system, it would map all alphanumeric characters
to lower case. Under Windows NT, / and \ are both path component
separators, so FOLD_FN_CHAR would map them both to /. */
#ifndef FOLD_FN_CHAR
#define FOLD_FN_CHAR(c) (c)
#endif
/* IGNORE(@ */
/* #include <ansidecl.h> */
/* @) */
#include <errno.h>
#include <fnmatch.h>
#if !defined(__GNU_LIBRARY__) \
&& !defined(STDC_HEADERS) \
&& !defined(_CRT_ERRNO_DEFINED)
extern int errno;
#endif
/* Match STRING against the filename pattern PATTERN, returning zero if
it matches, nonzero if not. */
int
#if __STDC__
fnmatch (const char *pattern, const char *string, int flags)
#else
fnmatch (pattern, string, flags)
char *pattern;
char *string;
int flags;
#endif
{
register const char *p = pattern, *n = string;
register char c;
if ((flags & ~__FNM_FLAGS) != 0)
{
errno = EINVAL;
return -1;
}
while ((c = *p++) != '\0')
{
switch (c)
{
case '?':
if (*n == '\0')
return FNM_NOMATCH;
else if ((flags & FNM_PATHNAME) && *n == '/')
return FNM_NOMATCH;
else if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return FNM_NOMATCH;
break;
case '\\':
if (!(flags & FNM_NOESCAPE))
c = *p++;
if (*n != c)
return FNM_NOMATCH;
break;
case '*':
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return FNM_NOMATCH;
for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
if (((flags & FNM_PATHNAME) && *n == '/') ||
(c == '?' && *n == '\0'))
return FNM_NOMATCH;
if (c == '\0')
return 0;
{
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
for (--p; *n != '\0'; ++n)
if ((c == '[' || *n == c1) &&
fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
return 0;
return FNM_NOMATCH;
}
case '[':
{
/* Nonzero if the sense of the character class is inverted. */
register int not;
if (*n == '\0')
return FNM_NOMATCH;
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return FNM_NOMATCH;
not = (*p == '!' || *p == '^');
if (not)
++p;
c = *p++;
for (;;)
{
register char cstart = c, cend = c;
if (!(flags & FNM_NOESCAPE) && c == '\\')
cstart = cend = *p++;
if (c == '\0')
/* [ (unterminated) loses. */
return FNM_NOMATCH;
c = *p++;
if ((flags & FNM_PATHNAME) && c == '/')
/* [/] can never match. */
return FNM_NOMATCH;
if (c == '-' && *p != ']')
{
cend = *p++;
if (!(flags & FNM_NOESCAPE) && cend == '\\')
cend = *p++;
if (cend == '\0')
return FNM_NOMATCH;
c = *p++;
}
if (*n >= cstart && *n <= cend)
goto matched;
if (c == ']')
break;
}
if (!not)
return FNM_NOMATCH;
break;
matched:;
/* Skip the rest of the [...] that already matched. */
while (c != ']')
{
if (c == '\0')
/* [... (unterminated) loses. */
return FNM_NOMATCH;
c = *p++;
if (!(flags & FNM_NOESCAPE) && c == '\\')
/* 1003.2d11 is unclear if this is right. %%% */
++p;
}
if (not)
return FNM_NOMATCH;
}
break;
default:
if (FOLD_FN_CHAR (c) != FOLD_FN_CHAR (*n))
return FNM_NOMATCH;
}
++n;
}
if (*n == '\0')
return 0;
return FNM_NOMATCH;
}

View File

@ -1,40 +0,0 @@
/* Copyright (C) 1992 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details. */
#ifndef _FNMATCH_H
#define _FNMATCH_H 1
/* Bits set in the FLAGS argument to `fnmatch'. */
#undef FNM_PATHNAME
#define FNM_PATHNAME (1 << 0)/* No wildcard can ever match `/'. */
#undef FNM_NOESCAPE
#define FNM_NOESCAPE (1 << 1)/* Backslashes don't quote special chars. */
#undef FNM_PERIOD
#define FNM_PERIOD (1 << 2)/* Leading `.' is matched only explicitly. */
#undef __FNM_FLAGS
#define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD)
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
#undef FNM_NOMATCH
#define FNM_NOMATCH 1
/* Match STRING against the filename pattern PATTERN,
returning zero if it matches, FNM_NOMATCH if not. */
#if __STDC__
extern int fnmatch (const char *pattern, const char *string, int flags);
#else
extern int fnmatch ();
#endif
#endif /* fnmatch.h */

View File

@ -1,5 +0,0 @@
These source files were taken from the GNU glibc-2.10.1 package.
ftp://ftp.gnu.org/gnu/glibc/glibc-2.10.1.tar.bz2
Minor changes were made to eliminate compiler errors and warnings.

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +0,0 @@
/* Extended regular expression matching and search library.
Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Make sure no one compiles this code with a C++ compiler. */
#ifdef __cplusplus
# error "This is C code, use a C compiler"
#endif
#ifdef _LIBC
/* We have to keep the namespace clean. */
# define regfree(preg) __regfree (preg)
# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
# define regerror(errcode, preg, errbuf, errbuf_size) \
__regerror(errcode, preg, errbuf, errbuf_size)
# define re_set_registers(bu, re, nu, st, en) \
__re_set_registers (bu, re, nu, st, en)
# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
# define re_match(bufp, string, size, pos, regs) \
__re_match (bufp, string, size, pos, regs)
# define re_search(bufp, string, size, startpos, range, regs) \
__re_search (bufp, string, size, startpos, range, regs)
# define re_compile_pattern(pattern, length, bufp) \
__re_compile_pattern (pattern, length, bufp)
# define re_set_syntax(syntax) __re_set_syntax (syntax)
# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
# include "../locale/localeinfo.h"
#endif
/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
GNU regex allows. Include it before <regex.h>, which correctly
#undefs RE_DUP_MAX and sets it to the right value. */
#include <limits.h>
#include "regex.h"
#include "regex_internal.h"
#include "regex_internal.c"
#include "regcomp.c"
#include "regexec.c"
/* Binary backward compatibility. */
#if _LIBC
# include <shlib-compat.h>
# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
int re_max_failures = 2000;
# endif
#endif

View File

@ -1,575 +0,0 @@
/* Definitions for data structures and routines for the regular
expression library.
Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006,2008
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _REGEX_H
#define _REGEX_H 1
#include <sys/types.h>
/* Allow the use in C++ code. */
#ifdef __cplusplus
extern "C" {
#endif
/* The following two types have to be signed and unsigned integer type
wide enough to hold a value of a pointer. For most ANSI compilers
ptrdiff_t and size_t should be likely OK. Still size of these two
types is 2 for Microsoft C. Ugh... */
typedef long int s_reg_t;
typedef unsigned long int active_reg_t;
/* The following bits are used to determine the regexp syntax we
recognize. The set/not-set meanings are chosen so that Emacs syntax
remains the value 0. The bits are given in alphabetical order, and
the definitions shifted by one from the previous bit; thus, when we
add or remove a bit, only one other definition need change. */
typedef unsigned long int reg_syntax_t;
#ifdef __USE_GNU
/* If this bit is not set, then \ inside a bracket expression is literal.
If set, then such a \ quotes the following character. */
# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
/* If this bit is not set, then + and ? are operators, and \+ and \? are
literals.
If set, then \+ and \? are operators and + and ? are literals. */
# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
/* If this bit is set, then character classes are supported. They are:
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
If not set, then character classes are not supported. */
# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
/* If this bit is set, then ^ and $ are always anchors (outside bracket
expressions, of course).
If this bit is not set, then it depends:
^ is an anchor if it is at the beginning of a regular
expression or after an open-group or an alternation operator;
$ is an anchor if it is at the end of a regular expression, or
before a close-group or an alternation operator.
This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
POSIX draft 11.2 says that * etc. in leading positions is undefined.
We already implemented a previous draft which made those constructs
invalid, though, so we haven't changed the code back. */
# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
/* If this bit is set, then special characters are always special
regardless of where they are in the pattern.
If this bit is not set, then special characters are special only in
some contexts; otherwise they are ordinary. Specifically,
* + ? and intervals are only special when not after the beginning,
open-group, or alternation operator. */
# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
/* If this bit is set, then *, +, ?, and { cannot be first in an re or
immediately after an alternation or begin-group operator. */
# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
/* If this bit is set, then . matches newline.
If not set, then it doesn't. */
# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
/* If this bit is set, then . doesn't match NUL.
If not set, then it does. */
# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
/* If this bit is set, nonmatching lists [^...] do not match newline.
If not set, they do. */
# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
/* If this bit is set, either \{...\} or {...} defines an
interval, depending on RE_NO_BK_BRACES.
If not set, \{, \}, {, and } are literals. */
# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
/* If this bit is set, +, ? and | aren't recognized as operators.
If not set, they are. */
# define RE_LIMITED_OPS (RE_INTERVALS << 1)
/* If this bit is set, newline is an alternation operator.
If not set, newline is literal. */
# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
/* If this bit is set, then `{...}' defines an interval, and \{ and \}
are literals.
If not set, then `\{...\}' defines an interval. */
# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
/* If this bit is set, (...) defines a group, and \( and \) are literals.
If not set, \(...\) defines a group, and ( and ) are literals. */
# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
/* If this bit is set, then \<digit> matches <digit>.
If not set, then \<digit> is a back-reference. */
# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
/* If this bit is set, then | is an alternation operator, and \| is literal.
If not set, then \| is an alternation operator, and | is literal. */
# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
/* If this bit is set, then an ending range point collating higher
than the starting range point, as in [z-a], is invalid.
If not set, then when ending range point collates higher than the
starting range point, the range is ignored. */
# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
/* If this bit is set, then an unmatched ) is ordinary.
If not set, then an unmatched ) is invalid. */
# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
/* If this bit is set, succeed as soon as we match the whole pattern,
without further backtracking. */
# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
/* If this bit is set, do not process the GNU regex operators.
If not set, then the GNU regex operators are recognized. */
# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
/* If this bit is set, turn on internal regex debugging.
If not set, and debugging was on, turn it off.
This only works if regex.c is compiled -DDEBUG.
We define this bit always, so that all that's needed to turn on
debugging is to recompile regex.c; the calling code can always have
this bit set, and it won't affect anything in the normal case. */
# define RE_DEBUG (RE_NO_GNU_OPS << 1)
/* If this bit is set, a syntactically invalid interval is treated as
a string of ordinary characters. For example, the ERE 'a{1' is
treated as 'a\{1'. */
# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
/* If this bit is set, then ignore case when matching.
If not set, then case is significant. */
# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only
for ^, because it is difficult to scan the regex backwards to find
whether ^ should be special. */
# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
/* If this bit is set, then \{ cannot be first in an bre or
immediately after an alternation or begin-group operator. */
# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
/* If this bit is set, then no_sub will be set to 1 during
re_compile_pattern. */
# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
#endif
/* This global variable defines the particular regexp syntax to use (for
some interfaces). When a regexp is compiled, the syntax used is
stored in the pattern buffer, so changing this does not affect
already-compiled regexps. */
extern reg_syntax_t re_syntax_options;
#ifdef __USE_GNU
/* Define combinations of the above bits for the standard possibilities.
(The [[[ comments delimit what gets put into the Texinfo file, so
don't delete them!) */
/* [[[begin syntaxes]]] */
#define RE_SYNTAX_EMACS 0
#define RE_SYNTAX_AWK \
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
| RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
| RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
#define RE_SYNTAX_GNU_AWK \
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
& ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \
| RE_CONTEXT_INVALID_OPS ))
#define RE_SYNTAX_POSIX_AWK \
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
| RE_INTERVALS | RE_NO_GNU_OPS)
#define RE_SYNTAX_GREP \
(RE_BK_PLUS_QM | RE_CHAR_CLASSES \
| RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
| RE_NEWLINE_ALT)
#define RE_SYNTAX_EGREP \
(RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
| RE_NEWLINE_ALT | RE_NO_BK_PARENS \
| RE_NO_BK_VBAR)
#define RE_SYNTAX_POSIX_EGREP \
(RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \
| RE_INVALID_INTERVAL_ORD)
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
/* Syntax bits common to both basic and extended POSIX regex syntax. */
#define _RE_SYNTAX_POSIX_COMMON \
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
#define RE_SYNTAX_POSIX_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
isn't minimal, since other operators, such as \`, aren't disabled. */
#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
#define RE_SYNTAX_POSIX_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_VBAR \
| RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
removed and RE_NO_BK_REFS is added. */
#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* [[[end syntaxes]]] */
/* Maximum number of duplicates an interval can allow. Some systems
(erroneously) define this in other header files, but we want our
value, so remove any previous define. */
# ifdef RE_DUP_MAX
# undef RE_DUP_MAX
# endif
/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
# define RE_DUP_MAX (0x7fff)
#endif
/* POSIX `cflags' bits (i.e., information for `regcomp'). */
/* If this bit is set, then use extended regular expression syntax.
If not set, then use basic regular expression syntax. */
#define REG_EXTENDED 1
/* If this bit is set, then ignore case when matching.
If not set, then case is significant. */
#define REG_ICASE (REG_EXTENDED << 1)
/* If this bit is set, then anchors do not match at newline
characters in the string.
If not set, then anchors do match at newlines. */
#define REG_NEWLINE (REG_ICASE << 1)
/* If this bit is set, then report only success or fail in regexec.
If not set, then returns differ between not matching and errors. */
#define REG_NOSUB (REG_NEWLINE << 1)
/* POSIX `eflags' bits (i.e., information for regexec). */
/* If this bit is set, then the beginning-of-line operator doesn't match
the beginning of the string (presumably because it's not the
beginning of a line).
If not set, then the beginning-of-line operator does match the
beginning of the string. */
#define REG_NOTBOL 1
/* Like REG_NOTBOL, except for the end-of-line. */
#define REG_NOTEOL (1 << 1)
/* Use PMATCH[0] to delimit the start and end of the search in the
buffer. */
#define REG_STARTEND (1 << 2)
/* If any error codes are removed, changed, or added, update the
`re_error_msg' table in regex.c. */
typedef enum
{
#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K
REG_ENOSYS = -1, /* This will never happen for this implementation. */
#endif
REG_NOERROR = 0, /* Success. */
REG_NOMATCH, /* Didn't find a match (for regexec). */
/* POSIX regcomp return error codes. (In the order listed in the
standard.) */
REG_BADPAT, /* Invalid pattern. */
REG_ECOLLATE, /* Inalid collating element. */
REG_ECTYPE, /* Invalid character class name. */
REG_EESCAPE, /* Trailing backslash. */
REG_ESUBREG, /* Invalid back reference. */
REG_EBRACK, /* Unmatched left bracket. */
REG_EPAREN, /* Parenthesis imbalance. */
REG_EBRACE, /* Unmatched \{. */
REG_BADBR, /* Invalid contents of \{\}. */
REG_ERANGE, /* Invalid range end. */
REG_ESPACE, /* Ran out of memory. */
REG_BADRPT, /* No preceding re for repetition op. */
/* Error codes we've added. */
REG_EEND, /* Premature end. */
REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
} reg_errcode_t;
/* This data structure represents a compiled pattern. Before calling
the pattern compiler, the fields `buffer', `allocated', `fastmap',
`translate', and `no_sub' can be set. After the pattern has been
compiled, the `re_nsub' field is available. All other fields are
private to the regex routines. */
#ifndef RE_TRANSLATE_TYPE
# define __RE_TRANSLATE_TYPE unsigned char *
# ifdef __USE_GNU
# define RE_TRANSLATE_TYPE __RE_TRANSLATE_TYPE
# endif
#endif
#ifdef __USE_GNU
# define __REPB_PREFIX(name) name
#else
# define __REPB_PREFIX(name) __##name
#endif
struct re_pattern_buffer
{
/* Space that holds the compiled pattern. It is declared as
`unsigned char *' because its elements are sometimes used as
array indexes. */
unsigned char *__REPB_PREFIX(buffer);
/* Number of bytes to which `buffer' points. */
unsigned long int __REPB_PREFIX(allocated);
/* Number of bytes actually used in `buffer'. */
unsigned long int __REPB_PREFIX(used);
/* Syntax setting with which the pattern was compiled. */
reg_syntax_t __REPB_PREFIX(syntax);
/* Pointer to a fastmap, if any, otherwise zero. re_search uses the
fastmap, if there is one, to skip over impossible starting points
for matches. */
char *__REPB_PREFIX(fastmap);
/* Either a translate table to apply to all characters before
comparing them, or zero for no translation. The translation is
applied to a pattern when it is compiled and to a string when it
is matched. */
__RE_TRANSLATE_TYPE __REPB_PREFIX(translate);
/* Number of subexpressions found by the compiler. */
size_t re_nsub;
/* Zero if this pattern cannot match the empty string, one else.
Well, in truth it's used only in `re_search_2', to see whether or
not we should use the fastmap, so we don't set this absolutely
perfectly; see `re_compile_fastmap' (the `duplicate' case). */
unsigned __REPB_PREFIX(can_be_null) : 1;
/* If REGS_UNALLOCATED, allocate space in the `regs' structure
for `max (RE_NREGS, re_nsub + 1)' groups.
If REGS_REALLOCATE, reallocate space if necessary.
If REGS_FIXED, use what's there. */
#ifdef __USE_GNU
# define REGS_UNALLOCATED 0
# define REGS_REALLOCATE 1
# define REGS_FIXED 2
#endif
unsigned __REPB_PREFIX(regs_allocated) : 2;
/* Set to zero when `regex_compile' compiles a pattern; set to one
by `re_compile_fastmap' if it updates the fastmap. */
unsigned __REPB_PREFIX(fastmap_accurate) : 1;
/* If set, `re_match_2' does not return information about
subexpressions. */
unsigned __REPB_PREFIX(no_sub) : 1;
/* If set, a beginning-of-line anchor doesn't match at the beginning
of the string. */
unsigned __REPB_PREFIX(not_bol) : 1;
/* Similarly for an end-of-line anchor. */
unsigned __REPB_PREFIX(not_eol) : 1;
/* If true, an anchor at a newline matches. */
unsigned __REPB_PREFIX(newline_anchor) : 1;
};
typedef struct re_pattern_buffer regex_t;
/* Type for byte offsets within the string. POSIX mandates this. */
typedef int regoff_t;
#ifdef __USE_GNU
/* This is the structure we store register match data in. See
regex.texinfo for a full description of what registers match. */
struct re_registers
{
unsigned num_regs;
regoff_t *start;
regoff_t *end;
};
/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
`re_match_2' returns information about at least this many registers
the first time a `regs' structure is passed. */
# ifndef RE_NREGS
# define RE_NREGS 30
# endif
#endif
/* POSIX specification for registers. Aside from the different names than
`re_registers', POSIX uses an array of structures, instead of a
structure of arrays. */
typedef struct
{
regoff_t rm_so; /* Byte offset from string's start to substring's start. */
regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
} regmatch_t;
/* Declarations for routines. */
#ifdef __USE_GNU
/* Sets the current default syntax to SYNTAX, and return the old syntax.
You can also simply assign to the `re_syntax_options' variable. */
extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
/* Compile the regular expression PATTERN, with length LENGTH
and syntax given by the global `re_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not. */
extern const char *re_compile_pattern (const char *__pattern, size_t __length,
struct re_pattern_buffer *__buffer);
/* Compile a fastmap for the compiled pattern in BUFFER; used to
accelerate searches. Return 0 if successful and -2 if was an
internal error. */
extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
/* Search in the string STRING (with length LENGTH) for the pattern
compiled into BUFFER. Start searching at position START, for RANGE
characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
extern int re_search (struct re_pattern_buffer *__buffer, const char *__string,
int __length, int __start, int __range,
struct re_registers *__regs);
/* Like `re_search', but search in the concatenation of STRING1 and
STRING2. Also, stop searching at index START + STOP. */
extern int re_search_2 (struct re_pattern_buffer *__buffer,
const char *__string1, int __length1,
const char *__string2, int __length2, int __start,
int __range, struct re_registers *__regs, int __stop);
/* Like `re_search', but return how many characters in STRING the regexp
in BUFFER matched, starting at position START. */
extern int re_match (struct re_pattern_buffer *__buffer, const char *__string,
int __length, int __start, struct re_registers *__regs);
/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
extern int re_match_2 (struct re_pattern_buffer *__buffer,
const char *__string1, int __length1,
const char *__string2, int __length2, int __start,
struct re_registers *__regs, int __stop);
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
ENDS. Subsequent matches using BUFFER and REGS will use this memory
for recording register information. STARTS and ENDS must be
allocated with malloc, and must each be at least `NUM_REGS * sizeof
(regoff_t)' bytes long.
If NUM_REGS == 0, then subsequent matches should allocate their own
register data.
Unless this function is called, the first search or match using
PATTERN_BUFFER will allocate its own register data, without
freeing the old data. */
extern void re_set_registers (struct re_pattern_buffer *__buffer,
struct re_registers *__regs,
unsigned int __num_regs,
regoff_t *__starts, regoff_t *__ends);
#endif /* Use GNU */
#if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_BSD)
# ifndef _CRAY
/* 4.2 bsd compatibility. */
extern char *re_comp (const char *);
extern int re_exec (const char *);
# endif
#endif
/* GCC 2.95 and later have "__restrict"; C99 compilers have
"restrict", and "configure" may have defined "restrict". */
#ifndef __restrict
# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
# if defined restrict || 199901L <= __STDC_VERSION__
# define __restrict restrict
# else
# define __restrict
# endif
# endif
#endif
/* gcc 3.1 and up support the [restrict] syntax. */
#ifndef __restrict_arr
# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \
&& !defined __GNUG__
# define __restrict_arr __restrict
# else
# define __restrict_arr
# endif
#endif
/* POSIX compatibility. */
extern int regcomp (regex_t *__restrict __preg,
const char *__restrict __pattern,
int __cflags);
extern int regexec (const regex_t *__restrict __preg,
const char *__restrict __string, size_t __nmatch,
regmatch_t __pmatch[__restrict_arr],
int __eflags);
extern size_t regerror (int __errcode, const regex_t *__restrict __preg,
char *__restrict __errbuf, size_t __errbuf_size);
extern void regfree (regex_t *__preg);
#ifdef __cplusplus
}
#endif /* C++ */
#endif /* regex.h */

File diff suppressed because it is too large Load Diff

View File

@ -1,773 +0,0 @@
/* Extended regular expression matching and search library.
Copyright (C) 2002-2005, 2007, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _REGEX_INTERNAL_H
#define _REGEX_INTERNAL_H 1
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
# include <langinfo.h>
#endif
#if defined HAVE_LOCALE_H || defined _LIBC
# include <locale.h>
#endif
#if defined HAVE_WCHAR_H || defined _LIBC
# include <wchar.h>
#endif /* HAVE_WCHAR_H || _LIBC */
#if defined HAVE_WCTYPE_H || defined _LIBC
# include <wctype.h>
#endif /* HAVE_WCTYPE_H || _LIBC */
#if defined HAVE_STDBOOL_H || defined _LIBC
# include <stdbool.h>
#endif /* HAVE_STDBOOL_H || _LIBC */
#if defined HAVE_STDINT_H || defined _LIBC
# include <stdint.h>
#endif /* HAVE_STDINT_H || _LIBC */
#if defined _LIBC
# include <bits/libc-lock.h>
#else
# define __libc_lock_define(CLASS,NAME)
# define __libc_lock_init(NAME) do { } while (0)
# define __libc_lock_lock(NAME) do { } while (0)
# define __libc_lock_unlock(NAME) do { } while (0)
#endif
/* In case that the system doesn't have isblank(). */
#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank
# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
#endif
#ifdef _LIBC
# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
# define _RE_DEFINE_LOCALE_FUNCTIONS 1
# include <locale/localeinfo.h>
# include <locale/elem-hash.h>
# include <locale/coll-lookup.h>
# endif
#endif
/* This is for other GNU distributions with internationalized messages. */
#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
# include <libintl.h>
# ifdef _LIBC
# undef gettext
# define gettext(msgid) \
INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES)
# endif
#else
# define gettext(msgid) (msgid)
#endif
#ifndef gettext_noop
/* This define is so xgettext can find the internationalizable
strings. */
# define gettext_noop(String) String
#endif
/* For loser systems without the definition. */
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC
# define RE_ENABLE_I18N
#endif
#if __GNUC__ >= 3
# define BE(expr, val) __builtin_expect (expr, val)
#else
# define BE(expr, val) (expr)
# define inline
#endif
/* Number of single byte character. */
#define SBC_MAX 256
#define COLL_ELEM_LEN_MAX 8
/* The character which represents newline. */
#define NEWLINE_CHAR '\n'
#define WIDE_NEWLINE_CHAR L'\n'
/* Rename to standard API for using out of glibc. */
#ifndef _LIBC
# define __wctype wctype
# define __iswctype iswctype
# define __btowc btowc
# define __mbrtowc mbrtowc
# define __mempcpy mempcpy
# define __wcrtomb wcrtomb
# define __regfree regfree
# define attribute_hidden
#endif /* not _LIBC */
#ifdef __GNUC__
# define __attribute(arg) __attribute__ (arg)
#else
# define __attribute(arg)
#endif
extern const char __re_error_msgid[] attribute_hidden;
extern const size_t __re_error_msgid_idx[] attribute_hidden;
/* An integer used to represent a set of bits. It must be unsigned,
and must be at least as wide as unsigned int. */
typedef unsigned long int bitset_word_t;
/* All bits set in a bitset_word_t. */
#define BITSET_WORD_MAX ULONG_MAX
/* Number of bits in a bitset_word_t. */
#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT)
/* Number of bitset_word_t in a bit_set. */
#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS)
typedef bitset_word_t bitset_t[BITSET_WORDS];
typedef bitset_word_t *re_bitset_ptr_t;
typedef const bitset_word_t *re_const_bitset_ptr_t;
#define bitset_set(set,i) \
(set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS)
#define bitset_clear(set,i) \
(set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS))
#define bitset_contain(set,i) \
(set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS))
#define bitset_empty(set) memset (set, '\0', sizeof (bitset_t))
#define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t))
#define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t))
#define PREV_WORD_CONSTRAINT 0x0001
#define PREV_NOTWORD_CONSTRAINT 0x0002
#define NEXT_WORD_CONSTRAINT 0x0004
#define NEXT_NOTWORD_CONSTRAINT 0x0008
#define PREV_NEWLINE_CONSTRAINT 0x0010
#define NEXT_NEWLINE_CONSTRAINT 0x0020
#define PREV_BEGBUF_CONSTRAINT 0x0040
#define NEXT_ENDBUF_CONSTRAINT 0x0080
#define WORD_DELIM_CONSTRAINT 0x0100
#define NOT_WORD_DELIM_CONSTRAINT 0x0200
typedef enum
{
INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
WORD_DELIM = WORD_DELIM_CONSTRAINT,
NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT
} re_context_type;
typedef struct
{
int alloc;
int nelem;
int *elems;
} re_node_set;
typedef enum
{
NON_TYPE = 0,
/* Node type, These are used by token, node, tree. */
CHARACTER = 1,
END_OF_RE = 2,
SIMPLE_BRACKET = 3,
OP_BACK_REF = 4,
OP_PERIOD = 5,
#ifdef RE_ENABLE_I18N
COMPLEX_BRACKET = 6,
OP_UTF8_PERIOD = 7,
#endif /* RE_ENABLE_I18N */
/* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used
when the debugger shows values of this enum type. */
#define EPSILON_BIT 8
OP_OPEN_SUBEXP = EPSILON_BIT | 0,
OP_CLOSE_SUBEXP = EPSILON_BIT | 1,
OP_ALT = EPSILON_BIT | 2,
OP_DUP_ASTERISK = EPSILON_BIT | 3,
ANCHOR = EPSILON_BIT | 4,
/* Tree type, these are used only by tree. */
CONCAT = 16,
SUBEXP = 17,
/* Token type, these are used only by token. */
OP_DUP_PLUS = 18,
OP_DUP_QUESTION,
OP_OPEN_BRACKET,
OP_CLOSE_BRACKET,
OP_CHARSET_RANGE,
OP_OPEN_DUP_NUM,
OP_CLOSE_DUP_NUM,
OP_NON_MATCH_LIST,
OP_OPEN_COLL_ELEM,
OP_CLOSE_COLL_ELEM,
OP_OPEN_EQUIV_CLASS,
OP_CLOSE_EQUIV_CLASS,
OP_OPEN_CHAR_CLASS,
OP_CLOSE_CHAR_CLASS,
OP_WORD,
OP_NOTWORD,
OP_SPACE,
OP_NOTSPACE,
BACK_SLASH
} re_token_type_t;
#ifdef RE_ENABLE_I18N
typedef struct
{
/* Multibyte characters. */
wchar_t *mbchars;
/* Collating symbols. */
# ifdef _LIBC
int32_t *coll_syms;
# endif
/* Equivalence classes. */
# ifdef _LIBC
int32_t *equiv_classes;
# endif
/* Range expressions. */
# ifdef _LIBC
uint32_t *range_starts;
uint32_t *range_ends;
# else /* not _LIBC */
wchar_t *range_starts;
wchar_t *range_ends;
# endif /* not _LIBC */
/* Character classes. */
wctype_t *char_classes;
/* If this character set is the non-matching list. */
unsigned int non_match : 1;
/* # of multibyte characters. */
int nmbchars;
/* # of collating symbols. */
int ncoll_syms;
/* # of equivalence classes. */
int nequiv_classes;
/* # of range expressions. */
int nranges;
/* # of character classes. */
int nchar_classes;
} re_charset_t;
#endif /* RE_ENABLE_I18N */
typedef struct
{
union
{
unsigned char c; /* for CHARACTER */
re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */
#ifdef RE_ENABLE_I18N
re_charset_t *mbcset; /* for COMPLEX_BRACKET */
#endif /* RE_ENABLE_I18N */
int idx; /* for BACK_REF */
re_context_type ctx_type; /* for ANCHOR */
} opr;
#if __GNUC__ >= 2
re_token_type_t type : 8;
#else
re_token_type_t type;
#endif
unsigned int constraint : 10; /* context constraint */
unsigned int duplicated : 1;
unsigned int opt_subexp : 1;
#ifdef RE_ENABLE_I18N
unsigned int accept_mb : 1;
/* These 2 bits can be moved into the union if needed (e.g. if running out
of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */
unsigned int mb_partial : 1;
#endif
unsigned int word_char : 1;
} re_token_t;
#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)
struct re_string_t
{
/* Indicate the raw buffer which is the original string passed as an
argument of regexec(), re_search(), etc.. */
const unsigned char *raw_mbs;
/* Store the multibyte string. In case of "case insensitive mode" like
REG_ICASE, upper cases of the string are stored, otherwise MBS points
the same address that RAW_MBS points. */
unsigned char *mbs;
#ifdef RE_ENABLE_I18N
/* Store the wide character string which is corresponding to MBS. */
wint_t *wcs;
int *offsets;
mbstate_t cur_state;
#endif
/* Index in RAW_MBS. Each character mbs[i] corresponds to
raw_mbs[raw_mbs_idx + i]. */
int raw_mbs_idx;
/* The length of the valid characters in the buffers. */
int valid_len;
/* The corresponding number of bytes in raw_mbs array. */
int valid_raw_len;
/* The length of the buffers MBS and WCS. */
int bufs_len;
/* The index in MBS, which is updated by re_string_fetch_byte. */
int cur_idx;
/* length of RAW_MBS array. */
int raw_len;
/* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */
int len;
/* End of the buffer may be shorter than its length in the cases such
as re_match_2, re_search_2. Then, we use STOP for end of the buffer
instead of LEN. */
int raw_stop;
/* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */
int stop;
/* The context of mbs[0]. We store the context independently, since
the context of mbs[0] may be different from raw_mbs[0], which is
the beginning of the input string. */
unsigned int tip_context;
/* The translation passed as a part of an argument of re_compile_pattern. */
RE_TRANSLATE_TYPE trans;
/* Copy of re_dfa_t's word_char. */
re_const_bitset_ptr_t word_char;
/* 1 if REG_ICASE. */
unsigned char icase;
unsigned char is_utf8;
unsigned char map_notascii;
unsigned char mbs_allocated;
unsigned char offsets_needed;
unsigned char newline_anchor;
unsigned char word_ops_used;
int mb_cur_max;
};
typedef struct re_string_t re_string_t;
struct re_dfa_t;
typedef struct re_dfa_t re_dfa_t;
#ifndef _LIBC
# ifdef __i386__
# define internal_function __attribute ((regparm (3), stdcall))
# else
# define internal_function
# endif
#endif
#ifndef NOT_IN_libc
static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
int new_buf_len)
internal_function;
# ifdef RE_ENABLE_I18N
static void build_wcs_buffer (re_string_t *pstr) internal_function;
static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr)
internal_function;
# endif /* RE_ENABLE_I18N */
static void build_upper_buffer (re_string_t *pstr) internal_function;
static void re_string_translate_buffer (re_string_t *pstr) internal_function;
static unsigned int re_string_context_at (const re_string_t *input, int idx,
int eflags)
internal_function __attribute ((pure));
#endif
#define re_string_peek_byte(pstr, offset) \
((pstr)->mbs[(pstr)->cur_idx + offset])
#define re_string_fetch_byte(pstr) \
((pstr)->mbs[(pstr)->cur_idx++])
#define re_string_first_byte(pstr, idx) \
((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF)
#define re_string_is_single_byte_char(pstr, idx) \
((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \
|| (pstr)->wcs[(idx) + 1] != WEOF))
#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
#define re_string_get_buffer(pstr) ((pstr)->mbs)
#define re_string_length(pstr) ((pstr)->len)
#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
#ifdef WIN32
# include <malloc.h>
#else
# include <alloca.h>
#endif
#ifndef _LIBC
# if HAVE_ALLOCA
/* The OS usually guarantees only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
allocate anything larger than 4096 bytes. Also care for the possibility
of a few compiler-allocated temporary stack slots. */
# define __libc_use_alloca(n) ((n) < 4032)
# else
/* alloca is implemented with malloc, so just use malloc. */
# define __libc_use_alloca(n) 0
# endif
#endif
#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
#define re_free(p) free (p)
struct bin_tree_t
{
struct bin_tree_t *parent;
struct bin_tree_t *left;
struct bin_tree_t *right;
struct bin_tree_t *first;
struct bin_tree_t *next;
re_token_t token;
/* `node_idx' is the index in dfa->nodes, if `type' == 0.
Otherwise `type' indicate the type of this node. */
int node_idx;
};
typedef struct bin_tree_t bin_tree_t;
#define BIN_TREE_STORAGE_SIZE \
((1024 - sizeof (void *)) / sizeof (bin_tree_t))
struct bin_tree_storage_t
{
struct bin_tree_storage_t *next;
bin_tree_t data[BIN_TREE_STORAGE_SIZE];
};
typedef struct bin_tree_storage_t bin_tree_storage_t;
#define CONTEXT_WORD 1
#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_')
#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)
#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
|| ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
|| ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
|| ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
|| (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
|| (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
|| (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
struct re_dfastate_t
{
unsigned int hash;
re_node_set nodes;
re_node_set non_eps_nodes;
re_node_set inveclosure;
re_node_set *entrance_nodes;
struct re_dfastate_t **trtable, **word_trtable;
unsigned int context : 4;
unsigned int halt : 1;
/* If this state can accept `multi byte'.
Note that we refer to multibyte characters, and multi character
collating elements as `multi byte'. */
unsigned int accept_mb : 1;
/* If this state has backreference node(s). */
unsigned int has_backref : 1;
unsigned int has_constraint : 1;
};
typedef struct re_dfastate_t re_dfastate_t;
struct re_state_table_entry
{
int num;
int alloc;
re_dfastate_t **array;
};
/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */
typedef struct
{
int next_idx;
int alloc;
re_dfastate_t **array;
} state_array_t;
/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */
typedef struct
{
int node;
int str_idx; /* The position NODE match at. */
state_array_t path;
} re_sub_match_last_t;
/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.
And information about the node, whose type is OP_CLOSE_SUBEXP,
corresponding to NODE is stored in LASTS. */
typedef struct
{
int str_idx;
int node;
state_array_t *path;
int alasts; /* Allocation size of LASTS. */
int nlasts; /* The number of LASTS. */
re_sub_match_last_t **lasts;
} re_sub_match_top_t;
struct re_backref_cache_entry
{
int node;
int str_idx;
int subexp_from;
int subexp_to;
char more;
char unused;
unsigned short int eps_reachable_subexps_map;
};
typedef struct
{
/* The string object corresponding to the input string. */
re_string_t input;
#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
const re_dfa_t *const dfa;
#else
const re_dfa_t *dfa;
#endif
/* EFLAGS of the argument of regexec. */
int eflags;
/* Where the matching ends. */
int match_last;
int last_node;
/* The state log used by the matcher. */
re_dfastate_t **state_log;
int state_log_top;
/* Back reference cache. */
int nbkref_ents;
int abkref_ents;
struct re_backref_cache_entry *bkref_ents;
int max_mb_elem_len;
int nsub_tops;
int asub_tops;
re_sub_match_top_t **sub_tops;
} re_match_context_t;
typedef struct
{
re_dfastate_t **sifted_states;
re_dfastate_t **limited_states;
int last_node;
int last_str_idx;
re_node_set limits;
} re_sift_context_t;
struct re_fail_stack_ent_t
{
int idx;
int node;
regmatch_t *regs;
re_node_set eps_via_nodes;
};
struct re_fail_stack_t
{
int num;
int alloc;
struct re_fail_stack_ent_t *stack;
};
struct re_dfa_t
{
re_token_t *nodes;
size_t nodes_alloc;
size_t nodes_len;
int *nexts;
int *org_indices;
re_node_set *edests;
re_node_set *eclosures;
re_node_set *inveclosures;
struct re_state_table_entry *state_table;
re_dfastate_t *init_state;
re_dfastate_t *init_state_word;
re_dfastate_t *init_state_nl;
re_dfastate_t *init_state_begbuf;
bin_tree_t *str_tree;
bin_tree_storage_t *str_tree_storage;
re_bitset_ptr_t sb_char;
int str_tree_storage_idx;
/* number of subexpressions `re_nsub' is in regex_t. */
unsigned int state_hash_mask;
int init_node;
int nbackref; /* The number of backreference in this dfa. */
/* Bitmap expressing which backreference is used. */
bitset_word_t used_bkref_map;
bitset_word_t completed_bkref_map;
unsigned int has_plural_match : 1;
/* If this dfa has "multibyte node", which is a backreference or
a node which can accept multibyte character or multi character
collating element. */
unsigned int has_mb_node : 1;
unsigned int is_utf8 : 1;
unsigned int map_notascii : 1;
unsigned int word_ops_used : 1;
int mb_cur_max;
bitset_t word_char;
reg_syntax_t syntax;
int *subexp_map;
#ifdef DEBUG
char* re_str;
#endif
__libc_lock_define (, lock)
};
#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
#define re_node_set_remove(set,id) \
(re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
#define re_node_set_empty(p) ((p)->nelem = 0)
#define re_node_set_free(set) re_free ((set)->elems)
typedef enum
{
SB_CHAR,
MB_CHAR,
EQUIV_CLASS,
COLL_SYM,
CHAR_CLASS
} bracket_elem_type;
typedef struct
{
bracket_elem_type type;
union
{
unsigned char ch;
unsigned char *name;
wchar_t wch;
} opr;
} bracket_elem_t;
/* Inline functions for bitset operation. */
static inline void
bitset_not (bitset_t set)
{
int bitset_i;
for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
set[bitset_i] = ~set[bitset_i];
}
static inline void
bitset_merge (bitset_t dest, const bitset_t src)
{
int bitset_i;
for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
dest[bitset_i] |= src[bitset_i];
}
static inline void
bitset_mask (bitset_t dest, const bitset_t src)
{
int bitset_i;
for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
dest[bitset_i] &= src[bitset_i];
}
#ifdef RE_ENABLE_I18N
/* Inline functions for re_string. */
static inline int
internal_function __attribute ((pure))
re_string_char_size_at (const re_string_t *pstr, int idx)
{
int byte_idx;
if (pstr->mb_cur_max == 1)
return 1;
for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
if (pstr->wcs[idx + byte_idx] != WEOF)
break;
return byte_idx;
}
static inline wint_t
internal_function __attribute ((pure))
re_string_wchar_at (const re_string_t *pstr, int idx)
{
if (pstr->mb_cur_max == 1)
return (wint_t) pstr->mbs[idx];
return (wint_t) pstr->wcs[idx];
}
# ifndef NOT_IN_libc
static int
internal_function __attribute ((pure))
re_string_elem_size_at (const re_string_t *pstr, int idx)
{
# ifdef _LIBC
const unsigned char *p, *extra;
const int32_t *table, *indirect;
int32_t tmp;
# include <locale/weight.h>
uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
if (nrules != 0)
{
table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
extra = (const unsigned char *)
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
_NL_COLLATE_INDIRECTMB);
p = pstr->mbs + idx;
tmp = findidx (&p);
return p - pstr->mbs - idx;
}
else
# endif /* _LIBC */
return 1;
}
# endif
#endif /* RE_ENABLE_I18N */
#endif /* _REGEX_INTERNAL_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,162 +0,0 @@
const char ctagsCommonPrelude []=
"%\n"
"% Copyright (c) 2021, Masatake YAMATO\n"
"% Copyright (c) 2021, Red Hat, Inc.\n"
"%\n"
"% This source code is released for free distribution under the terms of the\n"
"% GNU General Public License version 2 or (at your option) any later version.\n"
"%\n"
"\n"
"%\n"
"% The documentation table\n"
"%\n"
"\n"
"% __PROCDOCS:dict<proc:name, doc:string>\n"
"/__procdocs 30 dict def\n"
"\n"
"% name value __BDEF -\n"
"/__bdef { bind def } bind def\n"
"\n"
"% doc:string key:name any:val __DOCDEF -\n"
"/__bddef {\n"
" 1 index exch __bdef\n"
" exch __procdocs 3 1 roll put\n"
"} __bdef\n"
"\n"
"\n"
"%\n"
"% procedures\n"
"%\n"
"(any n:int _NDUP any1 ... anyn)\n"
"/_ndup { { dup } repeat } __bddef\n"
"\n"
"(x:any x:any _DEDUP x:any\n"
" x:any y:any _DEDUP x:any y:any)\n"
"/_dedup {\n"
" count 1 gt {\n"
" 2 copy eq {\n"
" pop\n"
" } if\n"
" } if\n"
"} __bddef\n"
"\n"
"(space:int space:int _DEDUP_SPACES space:int\n"
" otherthanspace:int space:int _DEDUP_SPACES otherthanspace:int space:int)\n"
"/_dedup_spaces {\n"
" count 0 gt {\n"
" dup ?\\_ eq {\n"
" _dedup\n"
" } if\n"
" } if\n"
"} __bddef\n"
"\n"
"% 32 32 _dedup_spaces pstack clear (---) ==\n"
"% 32 41 _dedup_spaces pstack clear (---) ==\n"
"% 41 32 _dedup_spaces pstack clear (---) ==\n"
"% 32 _dedup_spaces pstack clear (---) ==\n"
"% 41 _dedup_spaces pstack clear (---) ==\n"
"% quit\n"
"\n"
"/__buildstring {\n"
" {\n"
" counttomark dup 1 eq {\n"
" pop exch pop\n"
" exit\n"
" } {\n"
" -1 roll 1 index exch _putlast!\n"
" } ifelse\n"
" } loop\n"
"} __bdef\n"
"\n"
"(mark char:int|substring:string... _BUILDSTRING string)\n"
"/_buildstring {\n"
" 0 string __buildstring\n"
"} __bddef\n"
"\n"
"(string char:int|string _PUTLAST! -)\n"
"/_putlast! {\n"
" 1 index length exch\n"
" dup type /integertype eq {\n"
" put\n"
" } {\n"
" putinterval\n"
" } ifelse\n"
"} __bddef\n"
"\n"
"(target:string fromto:str _TR! -)\n"
"/_tr! {\n"
" %\n"
" % () is not allowed.\n"
" % The reason must be be documented.\n"
" %\n"
" 0 string\n"
" % str [int<from> int<to>] str'\n"
" 2 index {\n"
" % str [int<from> int<to>] str' int<chr>\n"
" dup 3 index 0 get\n"
" % str [int<from> int<to>] str' int<chr> int<chr> int<from>\n"
" eq {% str [int<from> int<to>] str' int<chr>\n"
" pop\n"
" dup 2 index 1 get _putlast!\n"
" } {% str [int<from> int<to>] str' int<chr>\n"
" 1 index exch _putlast!\n"
" } ifelse\n"
" } forall\n"
" % str [int<from> int<to>] str'\n"
" exch pop\n"
" 0 exch putinterval\n"
"} __bddef\n"
"\n"
"(string _NORMALIZE_SPACES! -)\n"
"/_normalize_spaces! {\n"
" dup\n"
" dup (\\n ) _tr!\n"
" dup (\\t ) _tr!\n"
" dup (\\r ) _tr!\n"
" dup (\\f ) _tr!\n"
" dup (\\v ) _tr!\n"
" mark exch { _dedup_spaces } forall _buildstring\n"
" exch copy pop\n"
"} __bddef\n"
"\n"
"% /x mark 40 (a) 32 32 10 (b) 10 10 9 9 (xyz) 9 9 41 _buildstring def\n"
"% x _normalize_spaces! x pstack\n"
"\n"
"(tag:int _SCOPEREF -)\n"
"/_scoperef {\n"
" _scopetop not { 0 } if scope:\n"
"} __bddef\n"
"\n"
"(tag:int _SCOPEPUSH -)\n"
"/_scopepush {\n"
" dup _scoperef _scopeset\n"
"} __bddef\n"
"\n"
"(string _ISSTRING string true\n"
" any:!string _ISSTRING false)\n"
"/_isstring {\n"
" dup type /stringtype eq {\n"
" true\n"
" } {\n"
" pop false\n"
" } ifelse\n"
"} __bddef\n"
"\n"
"(array key _AMEMBER true|fales)\n"
"/_amember {\n"
" false 3 1 roll\n"
" % false array key\n"
" exch {\n"
" % false key elt\n"
" 1 index\n"
" % false key elt key\n"
" eq {\n"
" % false key\n"
" exch pop true exch\n"
" exit\n"
" } if\n"
" % false key\n"
" } forall\n"
" pop\n"
"} __bddef\n"
;

View File

@ -16,10 +16,9 @@
#include <string.h>
#include <ctype.h>
#include "args_p.h"
#include "args.h"
#include "debug.h"
#include "routines.h"
#include "vstring.h"
/*
* FUNCTION DEFINITIONS
@ -145,8 +144,8 @@ static char* nextFileLine (FILE* const fp)
c = ungetc (c, fp);
}
vStringStripTrailing (vs);
vStringStripLeading (vs);
result = xMalloc (vStringLength (vs) + 1, char);
vStringStripLeading (vs);
strcpy (result, vStringValue (vs));
}
vStringDelete (vs);
@ -161,120 +160,18 @@ static bool isCommentLine (char* line)
return (*line == '#');
}
static bool isOptscriptLine (char *line)
{
size_t len = strlen (line);
if (len < 2)
return false;
if (line [len - 1] == '{' && line [len - 2] == '{')
return true;
return false;
}
static char* nextOptscriptLines (FILE* const fp, char *line)
{
vString *vstr = vStringNewInit (line);
vStringPut (vstr, '\n');
eFree (line);
/* \n}}, \n=>1, }=>2, }=>3 */
int endMarkers = 0;
int c;
while (true)
{
c = fgetc (fp);
if (c == EOF)
break;
if (c == '\r' || c == '\n')
{
if (c == '\r')
{
c = fgetc (fp);
if (c != '\n')
{
ungetc(c, fp);
c = '\n';
}
}
if (c == '\n')
{
vStringPut (vstr, c);
if (endMarkers != 1)
endMarkers = 1;
}
}
else if (c == '}')
{
vStringPut (vstr, c);
if (endMarkers == 1 || endMarkers == 2)
endMarkers++;
if (endMarkers == 3)
break;
}
else
{
endMarkers = 0;
vStringPut (vstr, c);
}
}
if (c == EOF)
{
switch (endMarkers)
{
case 0:
vStringPut (vstr, '\n');
/* Fall through */
case 1:
vStringPut (vstr, '}');
/* Fall through */
case 2:
vStringPut (vstr, '}');
default:
break;
}
}
c = fgetc (fp);
while (c != EOF)
{
if (c == '\n')
break;
if (c == '\r')
{
c = fgetc (fp);
if (c == '\n')
break;
ungetc (c, fp);
}
c = fgetc (fp);
}
return vStringDeleteUnwrap (vstr);
}
static char* nextFileLineSkippingComments (FILE* const fp)
{
char* result;
bool comment;
bool optscript;
do
{
result = nextFileLine (fp);
comment = false;
optscript = false;
if (result)
{
comment = isCommentLine (result);
optscript = isOptscriptLine (result);
}
comment = (result && isCommentLine (result));
if (comment)
eFree (result);
else if (optscript)
result = nextOptscriptLines (fp, result);
} while (comment);
return result;
}
@ -384,8 +281,7 @@ extern void argForth (Arguments* const current)
extern void argDelete (Arguments* const current)
{
Assert (current != NULL);
if ((current->type == ARG_STRING
|| current->type == ARG_FILE) && current->item != NULL)
if (current->type == ARG_STRING && current->item != NULL)
eFree (current->item);
memset (current, 0, sizeof (Arguments));
eFree (current);

View File

@ -6,8 +6,8 @@
*
* Defines external interface to command line argument reading.
*/
#ifndef CTAGS_MAIN_ARGS_PRIVATE_H
#define CTAGS_MAIN_ARGS_PRIVATE_H
#ifndef CTAGS_MAIN_ARGS_H
#define CTAGS_MAIN_ARGS_H
/*
* INCLUDE FILES
@ -54,4 +54,4 @@ extern void argSetLineMode (Arguments* const current);
extern void argForth (Arguments* const current);
extern void argDelete (Arguments* const current);
#endif /* CTAGS_MAIN_ARGS_PRIVATE_H */
#endif /* CTAGS_MAIN_ARGS_H */

View File

@ -1,22 +0,0 @@
/*
* Copyright (c) 1998-2002, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*/
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "main_p.h"
/*
* FUNCTION DEFINITIONS
*/
int main(int argc, char **argv)
{
return ctags_cli_main (argc, argv);
}

View File

@ -1,295 +0,0 @@
/*
* Copyright (c) 2017 Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#include "general.h" /* must always come first */
#include "colprint_p.h"
#include "ptrarray.h"
#include "routines.h"
#include "strlist.h"
#include "vstring.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
enum colprintJustification {
COLPRINT_LEFT, /* L:... */
COLPRINT_RIGHT, /* R:... */
COLPRINT_LAST,
};
struct colprintHeaderColumn {
vString *value;
enum colprintJustification justification;
unsigned int maxWidth;
bool needPrefix;
};
struct colprintTable {
ptrArray *header;
ptrArray *lines;
};
static void fillWithWhitespaces (int i, FILE *fp)
{
while (i-- > 0)
{
fputc(' ', fp);
}
}
static struct colprintHeaderColumn * colprintHeaderColumnNew (const char* spec)
{
int offset = 2;
struct colprintHeaderColumn *headerCol = xCalloc (1, struct colprintHeaderColumn);
if (strstr(spec, "L:") == spec)
headerCol->justification = COLPRINT_LEFT;
else if (strstr(spec, "R:") == spec)
headerCol->justification = COLPRINT_RIGHT;
else
{
headerCol->justification = COLPRINT_LEFT;
offset = 0;
}
headerCol->value = vStringNewInit(spec + offset);
headerCol->maxWidth = vStringLength(headerCol->value);
return headerCol;
}
static void colprintHeaderColumnDelete (struct colprintHeaderColumn * headerCol)
{
vStringDelete (headerCol->value);
eFree (headerCol);
}
struct colprintTable *colprintTableNew (const char* columnHeader, ... /* NULL TERMINATED */)
{
char *tmp;
va_list ap;
struct colprintTable *table;
struct colprintHeaderColumn *headerCol;
table = xCalloc (1, struct colprintTable);
table->header = ptrArrayNew ((ptrArrayDeleteFunc)colprintHeaderColumnDelete);
table->lines = ptrArrayNew ((ptrArrayDeleteFunc)stringListDelete);
headerCol = colprintHeaderColumnNew(columnHeader);
ptrArrayAdd (table->header, headerCol);
va_start(ap, columnHeader);
while (1)
{
tmp = va_arg(ap, char*);
if (tmp)
{
headerCol = colprintHeaderColumnNew(tmp);
ptrArrayAdd (table->header, headerCol);
}
else
break;
}
va_end(ap);
struct colprintHeaderColumn *last_col = ptrArrayLast (table->header);
if (last_col)
last_col->justification = COLPRINT_LAST;
return table;
}
void colprintTableDelete (struct colprintTable *table)
{
ptrArrayDelete(table->header);
table->header = NULL;
ptrArrayDelete(table->lines);
table->header = NULL;
eFree (table);
}
static void colprintColumnPrintGeneric (vString *column, struct colprintHeaderColumn *spec, bool machinable, FILE *fp)
{
int maxWidth = spec->maxWidth + (spec->needPrefix? 1: 0);
if ((column == spec->value) && (spec->needPrefix))
{
fputc('#', fp);
maxWidth--;
}
if (machinable)
{
fputs (vStringValue (column), fp);
if (spec->justification != COLPRINT_LAST)
fputc ('\t', fp);
}
else
{
int padLen = maxWidth - vStringLength (column);
if (spec->justification == COLPRINT_LEFT
|| spec->justification == COLPRINT_LAST)
{
fputs (vStringValue (column), fp);
if (spec->justification != COLPRINT_LAST)
{
fillWithWhitespaces (padLen, fp);
fputc (' ', fp);
}
}
else
{
fillWithWhitespaces (padLen, fp);
fputs (vStringValue (column), fp);
fputc (' ', fp);
}
}
}
static void colprintHeaderColumnPrint (struct colprintHeaderColumn *headerCol, bool machinable, FILE* fp)
{
colprintColumnPrintGeneric (headerCol->value, headerCol, machinable, fp);
}
static void colprintHeaderPrint (ptrArray *header, unsigned int startFrom, bool withHeader, bool machinable, FILE *fp)
{
unsigned int i;
if (!withHeader)
return;
for (i = startFrom; i < ptrArrayCount(header); i++)
{
struct colprintHeaderColumn *headerCol = ptrArrayItem (header, i);
colprintHeaderColumnPrint (headerCol, machinable, fp);
}
fputc('\n', fp);
}
static void colprintLinePrint (stringList *line, unsigned int startFrom, ptrArray *header, bool machinable, FILE *fp)
{
unsigned int i;
for (i = startFrom; i < stringListCount (line); i++)
{
vString *value = stringListItem(line, i);
struct colprintHeaderColumn *spec = ptrArrayItem (header, i);
colprintColumnPrintGeneric(value, spec, machinable, fp);
}
}
static void colprintLinesPrint (ptrArray *lines, unsigned int startFrom, ptrArray *header, bool machinable, FILE *fp)
{
unsigned int i;
for (i = 0; i < ptrArrayCount (lines); i++)
{
stringList *line = ptrArrayItem (lines, i);
colprintLinePrint (line, startFrom, header, machinable, fp);
fputc('\n', fp);
}
}
static void colprintUpdateMaxWidths (ptrArray *header, ptrArray *lines, unsigned int startFrom)
{
for (unsigned int c = 0; c < ptrArrayCount(header); c++)
{
struct colprintHeaderColumn *spec = ptrArrayItem (header, c);
if (c == startFrom)
spec->needPrefix = true;
else
spec->needPrefix = false;
}
for (unsigned int c = 0; c < ptrArrayCount(header); c++)
{
struct colprintHeaderColumn *spec = ptrArrayItem (header, c);
for (unsigned int l = 0; l < ptrArrayCount(lines); l++)
{
struct colprintLine *line = ptrArrayItem(lines, l);
vString *column = ptrArrayItem((ptrArray *)line, c);
if (spec->maxWidth < vStringLength(column))
spec->maxWidth = vStringLength(column);
}
}
}
void colprintTablePrint (struct colprintTable *table, unsigned int startFrom, bool withHeader, bool machinable, FILE *fp)
{
colprintUpdateMaxWidths (table->header, table->lines, startFrom);
colprintHeaderPrint (table->header, startFrom, withHeader, machinable, fp);
colprintLinesPrint (table->lines, startFrom, table->header, machinable, fp);
}
void colprintTableSort (struct colprintTable *table, int (* compareFn) (struct colprintLine *, struct colprintLine *))
{
ptrArraySort (table->lines, (int (*) (const void *, const void *))compareFn);
}
struct colprintLine *colprintTableGetNewLine (struct colprintTable *table)
{
stringList *line = stringListNew ();
ptrArrayAdd (table->lines, line);
return (struct colprintLine *)line;
}
static void colprintLineAppendColumn (struct colprintLine *line, vString *column)
{
stringList *slist = (stringList *)line;
stringListAdd (slist, column);
}
void colprintLineAppendColumnCString (struct colprintLine *line, const char *column)
{
vString* vcol = vStringNewInit (column? column: "");
colprintLineAppendColumn (line, vcol);
}
void colprintLineAppendColumnVString (struct colprintLine *line, vString* column)
{
colprintLineAppendColumnCString(line, vStringValue (column));
}
void colprintLineAppendColumnChar (struct colprintLine *line, char column)
{
vString* vcol = vStringNew ();
vStringPut (vcol, column);
colprintLineAppendColumn (line, vcol);
}
void colprintLineAppendColumnInt (struct colprintLine *line, unsigned int column)
{
char buf[12];
snprintf(buf, 12, "%u", column);
colprintLineAppendColumnCString (line, buf);
}
void colprintLineAppendColumnBool (struct colprintLine *line, bool column)
{
colprintLineAppendColumnCString (line, column? "yes": "no");
}
const char *colprintLineGetColumn (struct colprintLine *line, unsigned int column)
{
stringList *slist = (stringList *)line;
if (column <= stringListCount(slist))
{
vString *vstr = stringListItem (slist, column);
return vStringValue (vstr);
}
else
return NULL;
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2017 Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#ifndef CTAGS_MAIN_COLPRINT_PRIVATE_H
#define CTAGS_MAIN_COLPRINT_PRIVATE_H
#include "general.h"
#include "vstring.h"
#include <stdio.h>
struct colprintTable;
struct colprintLine;
/* Each column must have a prefix for specifying justification: "L:" or "R:". */
struct colprintTable *colprintTableNew (const char* columnHeader, ... /* NULL TERMINATED */);
void colprintTableDelete (struct colprintTable *table);
void colprintTablePrint (struct colprintTable *table, unsigned int startFrom, bool withHeader, bool machinable, FILE *fp);
void colprintTableSort (struct colprintTable *table, int (* compareFn) (struct colprintLine *, struct colprintLine *));
struct colprintLine *colprintTableGetNewLine (struct colprintTable *table);
void colprintLineAppendColumnCString (struct colprintLine *line, const char* column);
void colprintLineAppendColumnVString (struct colprintLine *line, vString* column);
void colprintLineAppendColumnChar (struct colprintLine *line, char column);
void colprintLineAppendColumnInt (struct colprintLine *line, unsigned int column);
/* Appends "yes" or "no". */
void colprintLineAppendColumnBool (struct colprintLine *line, bool column);
const char *colprintLineGetColumn (struct colprintLine *line, unsigned int column);
#endif /* CTAGS_MAIN_COLPRINT_PRIVATE_H */

144
ctags/main/ctags-api.c Normal file
View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2016, Jiri Techet
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Defines ctags API when compiled as a library.
*/
#include "general.h" /* must always come first */
#ifdef CTAGS_LIB
#include "ctags-api.h"
#include "types.h"
#include "routines.h"
#include "error.h"
#include "output.h"
#include "parse.h"
#include "options.h"
#include "trashbox.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
static bool nofatalErrorPrinter (const errorSelection selection,
const char *const format,
va_list ap, void *data CTAGS_ATTR_UNUSED)
{
fprintf (stderr, "%s: ", (selection & WARNING) ? "Warning: " : "Error");
vfprintf (stderr, format, ap);
if (selection & PERROR)
#ifdef HAVE_STRERROR
fprintf (stderr, " : %s", strerror (errno));
#else
perror (" ");
#endif
fputs ("\n", stderr);
return false;
}
extern void ctagsInit(void)
{
setErrorPrinter (nofatalErrorPrinter, NULL);
setTagWriter (&ctagsWriter);
checkRegex ();
initFieldDescs ();
initializeParsing ();
initOptions ();
initDefaultTrashBox ();
/* make sure all parsers are initialized */
initializeParser (LANG_AUTO);
}
extern void ctagsParse(unsigned char *buffer, size_t bufferSize,
const char *fileName, const langType language,
tagEntryFunction tagCallback, passStartCallback passCallback,
void *userData)
{
if (buffer == NULL && fileName == NULL)
{
error(FATAL, "Neither buffer nor file provided to ctagsParse()");
return;
}
createTagsWithFallback(buffer, bufferSize, fileName, language,
tagCallback, passCallback, userData);
}
extern const char *ctagsGetLangName(int lang)
{
return getLanguageName(lang);
}
extern int ctagsGetNamedLang(const char *name)
{
return getNamedLanguage(name, 0);
}
extern const char *ctagsGetLangKinds(int lang)
{
const parserDefinition *def = getParserDefinition(lang);
unsigned int i;
static char kinds[257];
for (i = 0; i < def->kindCount; i++)
kinds[i] = def->kindTable[i].letter;
kinds[i] = '\0';
return kinds;
}
extern const char *ctagsGetKindName(char kind, int lang)
{
const parserDefinition *def = getParserDefinition(lang);
unsigned int i;
for (i = 0; i < def->kindCount; i++)
{
if (def->kindTable[i].letter == kind)
return def->kindTable[i].name;
}
return "unknown";
}
extern char ctagsGetKindFromName(const char *name, int lang)
{
const parserDefinition *def = getParserDefinition(lang);
unsigned int i;
for (i = 0; i < def->kindCount; i++)
{
if (strcmp(def->kindTable[i].name, name) == 0)
return def->kindTable[i].letter;
}
return '-';
}
extern bool ctagsIsUsingRegexParser(int lang)
{
return getParserDefinition(lang)->method & METHOD_REGEX;
}
extern unsigned int ctagsGetLangCount(void)
{
return countParsers();
}
#endif /* CTAGS_LIB */

57
ctags/main/ctags-api.h Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2016, Jiri Techet
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Defines ctags API when compiled as a library.
*/
#ifndef CTAGS_API_H
#define CTAGS_API_H
#include "general.h" /* must always come first */
#ifdef CTAGS_LIB
#include <stdlib.h>
#include <stdbool.h>
typedef struct {
const char *name;
const char *signature;
const char *scopeName;
const char *inheritance;
const char *varType;
const char *access;
const char *implementation;
char kindLetter;
bool isFileScope;
unsigned long lineNumber;
int lang;
} ctagsTag;
/* Callback invoked for every tag found by the parser. The return value is
* currently unused. */
typedef bool (*tagEntryFunction) (const ctagsTag *const tag, void *userData);
/* Callback invoked at the beginning of every parsing pass. The return value is
* currently unused */
typedef bool (*passStartCallback) (void *userData);
extern void ctagsInit(void);
extern void ctagsParse(unsigned char *buffer, size_t bufferSize,
const char *fileName, const int language,
tagEntryFunction tagCallback, passStartCallback passCallback,
void *userData);
extern const char *ctagsGetLangName(int lang);
extern int ctagsGetNamedLang(const char *name);
extern const char *ctagsGetLangKinds(int lang);
extern const char *ctagsGetKindName(char kind, int lang);
extern char ctagsGetKindFromName(const char *name, int lang);
extern bool ctagsIsUsingRegexParser(int lang);
extern unsigned int ctagsGetLangCount(void);
#endif /* CTAGS_LIB */
#endif /* CTAGS_API_H */

View File

@ -17,7 +17,7 @@
#if defined (HAVE_CONFIG_H)
# define PROGRAM_VERSION PACKAGE_VERSION
#else
# define PROGRAM_VERSION "5.9.0"
# define PROGRAM_VERSION "0.0.0"
#endif
#define PROGRAM_NAME "Universal Ctags"
#define PROGRAM_URL "https://ctags.io/"
@ -30,11 +30,5 @@
extern const char* ctags_repoinfo;
#define CTAGS_FIELD_PREFIX "UCTAGS"
/*
* Reserved words
*/
#define RSV_LANGMAP_DEFAULT "default"
#define RSV_LANG_ALL "all"
#define RSV_LANG_AUTO "auto"
#define RSV_NONE "NONE"
#endif /* CTAGS_MAIN_CTAGS_H */

View File

@ -16,22 +16,16 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "debug.h"
#include "entry_p.h"
#include "options.h"
#include "parse_p.h"
#include "read.h"
#include "read_p.h"
/*
* FUNCTION DEFINITIONS
*/
#ifdef DEBUG
#include "htable.h"
extern void lineBreak (void) {} /* provides a line-specified break point */
@ -80,16 +74,11 @@ extern void debugEntry (const tagEntryInfo *const tag)
if (debug (DEBUG_PARSE))
{
langType lang = (tag->extensionFields.scopeLangType == LANG_AUTO)
? tag->langType
: tag->extensionFields.scopeLangType;
kindDefinition *scopeKindDef = getLanguageKind(lang,
tag->extensionFields.scopeKindIndex);
printf ("<#%s%s:%s", scope, getTagKindName(tag), tag->name);
printf ("<#%s%s:%s", scope, tag->kind->name, tag->name);
if (tag->extensionFields.scopeKindIndex != KIND_GHOST_INDEX &&
if (tag->extensionFields.scopeKind != NULL &&
tag->extensionFields.scopeName != NULL)
printf (" [%s:%s]", scopeKindDef->name,
printf (" [%s:%s]", tag->extensionFields.scopeKind->name,
tag->extensionFields.scopeName);
if (isFieldEnabled (FIELD_INHERITANCE) &&
@ -136,88 +125,4 @@ extern void debugAssert (const char *assertion, const char *file, unsigned int l
abort();
}
static int debugScopeDepth;
#define DEBUG_INDENT_UNIT 4
static char debugPrefix[DEBUG_INDENT_UNIT + 1];
extern void debugInit (void)
{
memset(debugPrefix, ' ', DEBUG_INDENT_UNIT);
debugPrefix[DEBUG_INDENT_UNIT] = '\0';
}
extern void debugIndent(void)
{
for(int i=0;i< debugScopeDepth;i++)
fputs(debugPrefix, stderr);
}
extern void debugInc(void)
{
debugScopeDepth++;
}
extern void debugDec(void)
{
debugScopeDepth--;
if(debugScopeDepth < 0)
debugScopeDepth = 0;
}
struct circularRefChecker {
hashTable *visitTable;
int counter;
};
extern void circularRefCheckerDestroy (struct circularRefChecker * checker)
{
hashTableDelete (checker->visitTable);
checker->visitTable = NULL;
eFree (checker);
}
extern struct circularRefChecker * circularRefCheckerNew (void)
{
Assert (sizeof(void *) >= sizeof(int));
struct circularRefChecker *c = xMalloc (1, struct circularRefChecker);
c->visitTable = hashTableNew (17, hashPtrhash, hashPtreq, NULL, NULL);
c->counter = 0;
return c;
}
extern int circularRefCheckerCheck (struct circularRefChecker *c, void *ptr)
{
union conv {
int i;
void *ptr;
} v;
v.ptr = hashTableGetItem(c->visitTable, ptr);
if (v.ptr)
return v.i;
else
{
v.i = ++c->counter;
hashTablePutItem (c->visitTable, ptr, v.ptr);
return 0;
}
}
extern int circularRefCheckerGetCurrent (struct circularRefChecker *c)
{
return c->counter;
}
extern void circularRefCheckClear (struct circularRefChecker *c)
{
hashTableClear (c->visitTable);
c->counter = 0;
}
#endif

View File

@ -14,26 +14,27 @@
*/
#include "general.h" /* must always come first */
#include "gvars.h"
#include "types.h"
#ifdef DEBUG
# include <assert.h>
#endif
#include "entry.h"
/*
* Macros
*/
#ifdef DEBUG
# define debug(level) ((ctags_debugLevel & (long)(level)) != 0)
# define debug(level) ((Option.debugLevel & (long)(level)) != 0)
# define DebugStatement(x) x
# define PrintStatus(x) if (debug(DEBUG_STATUS)) printf x;
# ifdef NDEBUG
# define Assert(c) do {} while(0)
# define AssertNotReached() do {} while(0)
# else
/* We expect cc supports c99 standard. */
# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
/* based on glibc's assert.h __ASSERT_FUNCTION */
# if defined (__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 4))
# define ASSERT_FUNCTION __PRETTY_FUNCTION__
# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
# define ASSERT_FUNCTION __func__
# else
# define ASSERT_FUNCTION ((const char*)0)
@ -51,10 +52,6 @@
# endif
#endif
#ifdef DEBUG
/* This makes valgrind report an error earlier. */
#define DISABLE_OBJPOOL
#endif
/*
* Data declarations
*/
@ -82,21 +79,4 @@ extern void debugCppIgnore (const bool ignore);
extern void debugEntry (const tagEntryInfo *const tag);
extern void debugAssert (const char *assertion, const char *file, unsigned int line, const char *function) attr__noreturn;
#ifdef DEBUG
#define DEBUG_INIT() debugInit()
extern void debugInit (void);
extern void debugIndent(void);
extern void debugInc(void);
extern void debugDec(void);
struct circularRefChecker;
extern struct circularRefChecker * circularRefCheckerNew (void);
extern void circularRefCheckerDestroy (struct circularRefChecker * checker);
extern int circularRefCheckerCheck (struct circularRefChecker *c, void *ptr);
extern int circularRefCheckerGetCurrent (struct circularRefChecker *c);
extern void circularRefCheckClear (struct circularRefChecker *c);
#else
#define DEBUG_INIT() do { } while(0)
#endif /* DEBUG */
#endif /* CTAGS_MAIN_DEBUG_H */

View File

@ -12,359 +12,91 @@
#include "general.h" /* must always come first */
#include "debug.h"
#include "dependency.h"
#include "options.h"
#include "parse_p.h"
#include "read.h"
#include "read_p.h"
#include "routines.h"
#include "subparser.h"
#include "subparser_p.h"
#include "xtag.h"
#include "parse.h"
#include <string.h>
struct slaveControlBlock {
slaveParser *slaveParsers; /* The parsers on this list must be initialized when
this parser is initialized. */
subparser *subparsersDefault;
subparser *subparsersInUse;
langType owner;
};
extern void linkDependencyAtInitializeParsing (depType dtype,
parserDefinition *const master,
struct slaveControlBlock *masterSCB,
struct kindControlBlock *masterKCB,
parserDefinition *const slave,
struct kindControlBlock *slaveKCB,
void *data)
static void linkKinds (kindDefinition *masterKind, kindDefinition *slaveKind)
{
if (dtype == DEPTYPE_KIND_OWNER)
linkKindDependency (masterKCB, slaveKCB);
else if (dtype == DEPTYPE_SUBPARSER)
kindDefinition *tail;
slaveKind->master = masterKind;
tail = slaveKind;
while (tail->slave)
{
slaveParser *s = xMalloc (1, slaveParser);
s->type = dtype;
s->id = slave->id;
s->data = data;
s->next = masterSCB->slaveParsers;
masterSCB->slaveParsers = s;
tail->enabled = masterKind->enabled;
tail = tail->slave;
}
tail->slave = masterKind->slave;
masterKind->slave = slaveKind;
}
static void attachSubparser (struct slaveControlBlock *base_sb, subparser *subparser)
static void linkKindDependency (parserDefinition *const masterParser,
parserDefinition *const slaveParser)
{
subparser->next = base_sb->subparsersDefault;
base_sb->subparsersDefault = subparser;
}
unsigned int k_slave, k_master;
kindDefinition *kind_slave, *kind_master;
extern struct slaveControlBlock *allocSlaveControlBlock (parserDefinition *parser)
{
struct slaveControlBlock *cb;
cb = xMalloc (1, struct slaveControlBlock);
cb->slaveParsers = NULL;
cb->subparsersDefault = NULL;
cb->subparsersInUse = NULL;
cb->owner = parser->id;
return cb;
}
extern void freeSlaveControlBlock (struct slaveControlBlock *cb)
{
eFree (cb);
}
extern void initializeDependencies (parserDefinition *parser,
struct slaveControlBlock *cb)
{
unsigned int i;
slaveParser *sp;
/* Initialize slaves */
sp = cb->slaveParsers;
while (sp != NULL)
for (k_slave = 0; k_slave < slaveParser->kindCount; k_slave++)
{
if (sp->type == DEPTYPE_SUBPARSER)
if (slaveParser->kindTable [k_slave].syncWith == LANG_AUTO)
{
subparser *sub;
sub = (subparser *)sp->data;
sub->slaveParser = sp;
}
if (sp->type == DEPTYPE_KIND_OWNER
|| (sp->type == DEPTYPE_SUBPARSER &&
(((subparser *)sp->data)->direction & SUBPARSER_BASE_RUNS_SUB)))
{
initializeParser (sp->id);
if (sp->type == DEPTYPE_SUBPARSER
&& isXtagEnabled (XTAG_SUBPARSER))
kind_slave = slaveParser->kindTable + k_slave;
for (k_master = 0; k_master < masterParser->kindCount; k_master++)
{
subparser *subparser = sp->data;
attachSubparser (cb, subparser);
kind_master = masterParser->kindTable + k_master;
if ((kind_slave->letter == kind_master->letter)
&& (strcmp (kind_slave->name, kind_master->name) == 0))
{
linkKinds (kind_master, kind_slave);
kind_slave->syncWith = masterParser->id;
kind_master->syncWith = masterParser->id;
break;
}
}
}
sp = sp->next;
}
}
/* Initialize masters that act as base parsers. */
for (i = 0; i < parser->dependencyCount; i++)
extern void linkDependencyAtInitializeParsing (depType dtype,
parserDefinition *const masterParser,
parserDefinition *const slaveParser)
{
if (dtype == DEPTYPE_KIND_OWNER)
linkKindDependency (masterParser, slaveParser);
else if (dtype == DEPTYPE_SUBPARSER)
{
parserDependency *d = parser->dependencies + i;
if (d->type == DEPTYPE_SUBPARSER &&
((subparser *)(d->data))->direction & SUBPARSER_SUB_RUNS_BASE)
{
langType baseParser;
baseParser = getNamedLanguage (d->upperParser, 0);
Assert (baseParser != LANG_IGNORE);
initializeParser (baseParser);
}
subparser *s = xMalloc (1, subparser);
s->id = slaveParser->id;
s->next = masterParser->subparsers;
masterParser->subparsers = s;
}
}
extern void finalizeDependencies (parserDefinition *parser,
struct slaveControlBlock *cb)
extern void initializeSubparsers (const parserDefinition *parser)
{
while (cb->slaveParsers)
{
slaveParser *sp = cb->slaveParsers;
cb->slaveParsers = sp->next;
sp->next = NULL;
eFree (sp);
}
subparser *sp;
for (sp = parser->subparsers; sp; sp = sp->next)
initializeParser (sp->id);
}
extern void notifyInputStart (void)
{
subparser *s;
/* for running prelude of optlib */
langType lang = getInputLanguage ();
notifyLanguageRegexInputStart (lang);
foreachSubparser(s, true)
{
enterSubparser(s);
if (s->inputStart)
s->inputStart (s);
/* propagate the event recursively */
notifyInputStart ();
leaveSubparser();
}
}
extern void notifyInputEnd (void)
{
subparser *s;
foreachSubparser(s, true)
{
enterSubparser(s);
/* propagate the event recursively */
notifyInputEnd ();
if (s->inputEnd)
s->inputEnd (s);
leaveSubparser();
}
/* for running sequel of optlib */
langType lang = getInputLanguage ();
notifyLanguageRegexInputEnd (lang);
}
extern void notifyMakeTagEntry (const tagEntryInfo *tag, int corkIndex)
{
subparser *s;
foreachSubparser(s, false)
{
if (s->makeTagEntryNotify)
{
enterSubparser(s);
s->makeTagEntryNotify (s, tag, corkIndex);
leaveSubparser();
}
}
}
extern langType getSubparserLanguage (subparser *s)
{
return s->slaveParser->id;
}
extern void chooseExclusiveSubparser (subparser *s, void *data)
{
if (s->exclusiveSubparserChosenNotify)
{
s->chosenAsExclusiveSubparser = true;
enterSubparser(s);
s->exclusiveSubparserChosenNotify (s, data);
verbose ("%s is chosen as exclusive subparser\n",
getLanguageName (getSubparserLanguage (s)));
leaveSubparser();
}
}
extern subparser *getFirstSubparser(struct slaveControlBlock *controlBlock)
{
if (controlBlock)
return controlBlock->subparsersInUse;
return NULL;
}
extern void useDefaultSubparsers (struct slaveControlBlock *controlBlock)
{
controlBlock->subparsersInUse = controlBlock->subparsersDefault;
}
extern void useSpecifiedSubparser (struct slaveControlBlock *controlBlock, subparser *s)
{
s->schedulingBaseparserExplicitly = true;
controlBlock->subparsersInUse = s;
}
extern void setupSubparsersInUse (struct slaveControlBlock *controlBlock)
{
if (!controlBlock->subparsersInUse)
useDefaultSubparsers(controlBlock);
}
extern subparser* teardownSubparsersInUse (struct slaveControlBlock *controlBlock)
extern void finalizeSubparsers (parserDefinition *parser)
{
subparser *sp;
subparser *tmp;
subparser *s = NULL;
tmp = controlBlock->subparsersInUse;
controlBlock->subparsersInUse = NULL;
if (tmp && tmp->schedulingBaseparserExplicitly)
for (sp = parser->subparsers; sp;)
{
tmp->schedulingBaseparserExplicitly = false;
s = tmp;
tmp = sp;
sp = sp->next;
tmp->next = NULL;
eFree (tmp);
}
if (s)
return s;
while (tmp)
{
if (tmp->chosenAsExclusiveSubparser)
{
s = tmp;
}
tmp = tmp->next;
}
return s;
}
static int subparserDepth;
extern void enterSubparser(subparser *subparser)
{
subparserDepth++;
pushLanguage (getSubparserLanguage (subparser));
}
extern void leaveSubparser(void)
{
popLanguage ();
subparserDepth--;
}
extern bool doesSubparserRun (void)
{
if (getLanguageForBaseParser () == getInputLanguage())
return false;
return subparserDepth;
}
extern slaveParser *getFirstSlaveParser (struct slaveControlBlock *scb)
{
if (scb)
return scb->slaveParsers;
return NULL;
}
extern subparser *getLanguageSubparser (langType sublang,
bool including_none_crafted_parser)
{
subparser *s;
foreachSubparser (s, including_none_crafted_parser)
{
if (getSubparserLanguage (s) == sublang)
return s;
}
return NULL;
}
extern struct colprintTable * subparserColprintTableNew (void)
{
return colprintTableNew ("L:NAME", "L:BASEPARSER", "L:DIRECTIONS", NULL);
}
extern void subparserColprintAddSubparsers (struct colprintTable *table,
struct slaveControlBlock *scb)
{
slaveParser *tmp;
pushLanguage (scb->owner);
foreachSlaveParser(tmp)
{
struct colprintLine *line = colprintTableGetNewLine(table);
colprintLineAppendColumnCString (line, getLanguageName (tmp->id));
colprintLineAppendColumnCString (line, getLanguageName (scb->owner));
const char *direction;
switch (((subparser *)tmp->data)->direction)
{
case SUBPARSER_BASE_RUNS_SUB:
direction = "base => sub {shared}";
break;
case SUBPARSER_SUB_RUNS_BASE:
direction = "base <= sub {dedicated}";
break;
case SUBPARSER_BI_DIRECTION:
direction = "base <> sub {bidirectional}";
break;
default:
direction = "UNKNOWN(INTERNAL BUG)";
break;
}
colprintLineAppendColumnCString (line, direction);
}
popLanguage ();
}
static int subparserColprintCompareLines (struct colprintLine *a , struct colprintLine *b)
{
const char *a_name = colprintLineGetColumn (a, 0);
const char *b_name = colprintLineGetColumn (b, 0);
int r;
r = strcmp (a_name, b_name);
if (r != 0)
return r;
const char *a_baseparser = colprintLineGetColumn (a, 1);
const char *b_baseparser = colprintLineGetColumn (b, 1);
return strcmp(a_baseparser, b_baseparser);
}
extern void subparserColprintTablePrint (struct colprintTable *table,
bool withListHeader, bool machinable, FILE *fp)
{
colprintTableSort (table, subparserColprintCompareLines);
colprintTablePrint (table, 0, withListHeader, machinable, fp);
parser->subparsers = NULL;
}

View File

@ -12,34 +12,34 @@
#ifndef CTAGS_MAIN_DEPENDENCY_H
#define CTAGS_MAIN_DEPENDENCY_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "general.h"
#include "types.h"
/*
* DATA DECLARATIONS
*/
typedef enum eDepType {
DEPTYPE_KIND_OWNER,
DEPTYPE_SUBPARSER,
COUNT_DEPTYPES,
} depType;
struct sParserDependency {
typedef struct sParserDependency {
depType type;
const char *upperParser;
void *data;
} parserDependency;
extern void linkDependencyAtInitializeParsing (depType dtype,
parserDefinition *const masterParser,
parserDefinition *const slaveParser);
typedef struct sSubparser subparser;
struct sSubparser {
langType id;
subparser *next;
};
struct sSlaveParser {
depType type;
langType id;
void *data;
slaveParser *next;
};
extern void initializeSubparsers (const parserDefinition *parser);
extern void finalizeSubparsers (parserDefinition *parser);
#endif /* CTAGS_MAIN_DEPENDENCY_H */

View File

@ -1,58 +0,0 @@
/*
*
* Copyright (c) 2016, Red Hat, Inc.
* Copyright (c) 2016, Masatake YAMATO
*
* Author: Masatake YAMATO <yamato@redhat.com>
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#ifndef CTAGS_MAIN_DEPENDENCY_PRIVATE_H
#define CTAGS_MAIN_DEPENDENCY_PRIVATE_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "dependency.h"
#include "kind.h"
#include "types.h"
/*
* MACROS
*/
#define foreachSlaveParser(VAR) \
VAR = NULL; \
while ((VAR = getNextSlaveParser (VAR)) != NULL)
/*
* DATA DECLARATIONS
*/
struct slaveControlBlock; /* Opaque data type for parse.c */
/*
* FUNCTION PROTOTYPES
*/
extern void linkDependencyAtInitializeParsing (depType dtype,
parserDefinition *const master,
struct slaveControlBlock *masterSCB,
struct kindControlBlock *masterKCB,
parserDefinition *const slave,
struct kindControlBlock *slaveKCB,
void *data);
extern struct slaveControlBlock *allocSlaveControlBlock (parserDefinition *parser);
extern void freeSlaveControlBlock (struct slaveControlBlock *cb);
extern void initializeDependencies (parserDefinition *parser,
struct slaveControlBlock *cb);
extern void finalizeDependencies (parserDefinition *parser,
struct slaveControlBlock *cb);
extern slaveParser *getFirstSlaveParser(struct slaveControlBlock *controlBlock);
extern slaveParser *getNextSlaveParser(slaveParser *last);
#endif /* CTAGS_MAIN_DEPENDENCY_PRIVATE_H */

View File

@ -14,30 +14,34 @@
#define MSDOS_STYLE_PATH 1
#define HAVE_FCNTL_H 1
#define HAVE_IO_H 1
#define HAVE_LIMITS_H 1
#define HAVE_STDLIB_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_TIME_H 1
#define HAVE_CLOCK 1
#define HAVE_CHSIZE 1
#define HAVE_DIRECT_H 1
#define HAVE_FGETPOS 1
#define HAVE_STRICMP 1
#define HAVE_STRNICMP 1
#define HAVE_STRSTR 1
#define HAVE_STRERROR 1
#define HAVE__FINDFIRST 1
#define HAVE_FINDNEXT 1
#define findfirst_t intptr_t
#define HAVE_MKSTEMP 1
#define HAVE_TEMPNAM 1
#define HAVE_FNMATCH 1
#define HAVE_FNMATCH_H 1
#define HAVE_PUTENV 1
#define tempnam(dir,pfx) _tempnam(dir,pfx)
#define TMPDIR "\\"
int mkstemp (char *template_name);
#ifdef _MSC_VER
# define HAVE__FINDFIRST 1
# define HAVE_DIRECT_H 1
# if _MSC_VER < 1900
# define snprintf _snprintf
# endif
# define findfirst_t intptr_t
#if (_MSC_VER >= 1800) // Visual Studio 2013 or newer
#define HAVE_STDBOOL_H 1
@ -54,15 +58,14 @@ typedef enum { false, true } bool;
# include <_mingw.h>
# define HAVE_STDBOOL_H 1
# define HAVE_DIR_H 1
# define HAVE_DIRENT_H 1
# define HAVE__FINDFIRST 1
# define findfirst_t long
# define ffblk _finddata_t
# define FA_DIREC _A_SUBDIR
# define ff_name name
# if defined(__USE_MINGW_ANSI_STDIO) && defined(__MINGW64_VERSION_MAJOR)
# define HAVE_ASPRINTF 1
# endif
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -16,19 +16,21 @@
#include "types.h"
#include <stdint.h>
#include <time.h>
#include <stdio.h>
#include "field.h"
#include "kind.h"
#include "vstring.h"
#include "xtag.h"
#include "mio.h"
#include "ptrarray.h"
#include "nestlevel.h"
#include "script_p.h"
#include "ctags-api.h"
/*
* MACROS
*/
#define WHOLE_FILE -1L
#define includeExtensionFlags() (Option.tagFileFormat > 1)
/*
* DATA DECLARATIONS
@ -36,11 +38,8 @@
typedef struct sTagField {
fieldType ftype;
const char* value;
bool valueOwner; /* used only in parserFieldsDynamic */
} tagField;
typedef uint64_t roleBitsType;
/* Information about the current tag candidate.
*/
struct sTagEntryInfo {
@ -48,14 +47,9 @@ struct sTagEntryInfo {
unsigned int isFileScope :1; /* is tag visible only within input file? */
unsigned int isFileEntry :1; /* is this just an entry for a file name? */
unsigned int truncateLineAfterTag :1; /* truncate tag line at end of tag name? */
unsigned int placeholder :1; /* is used only for keeping corkIndex based scope chain.
unsigned int placeholder :1; /* This is just a part of scope context.
Put this entry to cork queue but
don't print it to tags file. */
unsigned int skipAutoFQEmission:1; /* If a parser makes a fq tag for the
current tag by itself, set this. */
unsigned int isPseudoTag:1; /* Used only in xref output.
If a tag is a pseudo, set this. */
unsigned int inCorkQueue:1;
unsigned long lineNumber; /* line number of tag */
const char* pattern; /* pattern for locating input line
@ -66,11 +60,11 @@ struct sTagEntryInfo {
const char *inputFileName; /* name of input file */
const char *name; /* name of the tag */
int kindIndex; /* kind descriptor */
uint8_t extra[ ((XTAG_COUNT) / 8) + 1 ];
uint8_t *extraDynamic; /* Dynamically allocated but freed by per parser TrashBox */
unsigned char extra[ ((XTAG_COUNT) / 8) + 1 ];
struct {
const char* access;
const char* fileScope;
const char* implementation;
const char* inheritance;
@ -90,30 +84,23 @@ struct sTagEntryInfo {
/* type (union/struct/etc.) and name for a variable or typedef. */
const char* typeRef [2]; /* e.g., "struct" and struct name */
#define ROLE_DEFINITION_INDEX -1
#define ROLE_DEFINITION_NAME "def"
#define ROLE_MAX_COUNT (sizeof(roleBitsType) * 8)
roleBitsType roleBits; /* for role of reference tag */
/* GEANY DIFF */
const char *varType;
/* GEANY DIFF END */
#define ROLE_INDEX_DEFINITION -1
int roleIndex; /* for role of reference tag */
#ifdef HAVE_LIBXML
const char* xpath;
#endif
unsigned long endLine;
time_t epoch;
#define NO_NTH_FIELD -1
short nth;
} extensionFields; /* list of extension fields*/
/* `usedParserFields' tracks how many parser own fields are
used. If it is a few (less than PRE_ALLOCATED_PARSER_FIELDS),
statically allocated parserFields is used. If more fields than
PRE_ALLOCATED_PARSER_FIELDS is defined and attached, parserFieldsDynamic
is used. */
unsigned int usedParserFields;
#define PRE_ALLOCATED_PARSER_FIELDS 5
#define NO_PARSER_FIELD -1
unsigned int usedParserFields;
tagField parserFields [PRE_ALLOCATED_PARSER_FIELDS];
ptrArray * parserFieldsDynamic;
/* Following source* fields are used only when #line is found
in input and --line-directive is given in ctags command line. */
@ -122,9 +109,6 @@ struct sTagEntryInfo {
unsigned long sourceLineNumberDifference;
};
typedef bool (* entryForeachFunc) (int corkIndex,
tagEntryInfo * entry,
void * data);
/*
* GLOBAL VARIABLES
@ -134,150 +118,71 @@ typedef bool (* entryForeachFunc) (int corkIndex,
/*
* FUNCTION PROTOTYPES
*/
extern void freeTagFileResources (void);
extern const char *tagFileName (void);
extern void openTagFile (void);
extern void closeTagFile (const bool resize);
extern void setupWriter (void);
extern void teardownWriter (const char *inputFilename);
extern int makeTagEntry (const tagEntryInfo *const tag);
extern void initTagEntry (tagEntryInfo *const e, const char *const name,
int kindIndex);
extern void initRefTagEntry (tagEntryInfo *const e, const char *const name,
int kindIndex, int roleIndex);
extern void initForeignRefTagEntry (tagEntryInfo *const e, const char *const name,
langType type,
int kindIndex, int roleIndex);
extern void assignRole(tagEntryInfo *const e, int roleIndex);
extern bool isRoleAssigned(const tagEntryInfo *const e, int roleIndex);
extern void initTagEntryFull (tagEntryInfo *const e, const char *const name,
unsigned long lineNumber,
langType langType_,
MIOPos filePosition,
const char *inputFileName,
int kindIndex,
int roleIndex,
const char *sourceFileName,
langType sourceLangType,
long sourceLineNumberDifference);
extern int makeQualifiedTagEntry (const tagEntryInfo *const e);
extern void setTagPositionFromTag (tagEntryInfo *const dst, const tagEntryInfo *const src);
extern unsigned long numTagsAdded(void);
extern void setNumTagsAdded (unsigned long nadded);
extern unsigned long numTagsTotal(void);
extern unsigned long maxTagsLine(void);
extern void invalidatePatternCache(void);
extern void tagFilePosition (MIOPos *p);
extern void setTagFilePosition (MIOPos *p);
extern const char* getTagFileDirectory (void);
extern void getTagScopeInformation (tagEntryInfo *const tag,
const char **kind, const char **name);
/* Getting line associated with tag */
extern char *readLineFromBypassAnyway (vString *const vLine, const tagEntryInfo *const tag,
long *const pSeekValue);
/* Generating pattern associated tag, caller must do eFree for the returned value. */
extern char* makePatternString (const tagEntryInfo *const tag);
/* language is optional: can be NULL. */
extern bool writePseudoTag (const ptagDesc *pdesc,
const char *const fileName,
const char *const pattern,
const char *const parserName);
#define CORK_NIL 0
tagEntryInfo *getEntryInCorkQueue (int n);
void corkTagFile(void);
void uncorkTagFile(void);
tagEntryInfo *getEntryInCorkQueue (unsigned int n);
tagEntryInfo *getEntryOfNestingLevel (const NestingLevel *nl);
size_t countEntryInCorkQueue (void);
/* If a parser sets (CORK_QUEUE and )CORK_SYMTAB to useCork,
* the parsesr can use symbol lookup tables for the current input.
* Each scope has a symbol lookup table.
* To register an tag to the table, use registerEntry().
* registerEntry registers CORKINDEX to a symbol table of a parent tag
* specified in the scopeIndex field of the tag specified with CORKINDEX.
*/
void registerEntry (int corkIndex);
/* foreachEntriesInScope is for traversing the symbol table for a table
* specified with CORKINDEX. If CORK_NIL is given, this function traverses
* top-level entries. If name is NULL, this function traverses all entries
* under the scope.
*
* If FUNC returns false, this function returns false.
* If FUNC never returns false, this function returns true.
* If FUNC is not called because no node for NAME in the symbol table,
* this function returns true.
*/
bool foreachEntriesInScope (int corkIndex,
const char *name, /* or NULL */
entryForeachFunc func,
void *data);
/* Return the cork index for NAME in the scope specified with CORKINDEX.
* Even if more than one entries for NAME are in the scope, this function
* just returns one of them. Returning CORK_NIL means there is no entry
* for NAME.
*/
int anyEntryInScope (int corkIndex,
const char *name);
int anyKindEntryInScope (int corkIndex,
const char *name, int kind);
int anyKindsEntryInScope (int corkIndex,
const char *name,
const int * kinds, int count);
int anyKindsEntryInScopeRecursive (int corkIndex,
const char *name,
const int * kinds, int count);
extern void makeFileTag (const char *const fileName);
extern void markTagExtraBit (tagEntryInfo *const tag, xtagType extra);
extern void unmarkTagExtraBit (tagEntryInfo *const tag, xtagType extra);
extern bool isTagExtraBitMarked (const tagEntryInfo *const tag, xtagType extra);
/* If any extra bit is on, return true. */
extern bool isTagExtra (const tagEntryInfo *const tag);
/* Functions for attaching parser specific fields
*
* Which function you should use?
* ------------------------------
* Case A:
*
* If your parser uses the Cork API, and your parser called
* makeTagEntry () already, you can use both
* attachParserFieldToCorkEntry () and attachParserField (). Your
* parser has the cork index returned from makeTagEntry (). With the
* cork index, your parser can call attachParserFieldToCorkEntry ().
* If your parser already call getEntryInCorkQueue () to get the tag
* entry for the cork index, your parser can call attachParserField ()
* with passing true for `inCorkQueue' parameter. attachParserField ()
* is a bit faster than attachParserFieldToCorkEntry ().
*
* attachParserField () and attachParserFieldToCorkEntry () duplicates
* the memory object specified with `value' and stores the duplicated
* object to the entry on the cork queue. So the parser must/can free
* the original one passed to the functions after calling. The cork
* queue manages the life of the duplicated object. It is not the
* parser's concern.
*
*
* Case B:
*
* If your parser called one of initTagEntry () family but didn't call
* makeTagEntry () for a tagEntry yet, use attachParserField () with
* false for `inCorkQueue' whether your parser uses the Cork API or
* not.
*
* The parser (== caller) keeps the memory object specified with `value'
* till calling makeTagEntry (). The parser must free the memory object
* after calling makeTagEntry () if it is allocated dynamically in the
* parser side.
*
* Interpretation of VALUE
* -----------------------
* For FIELDTYPE_STRING:
* Both json writer and xref writer prints it as-is.
*
* For FIELDTYPE_STRING|FIELDTYPE_BOOL:
* If VALUE points "" (empty C string), the json writer prints it as
* false, and the xref writer prints it as -.
* If VALUE points a non-empty C string, Both json writer and xref
* writer print it as-is.
*
* For FIELDTYPE_BOOL
* The json writer always prints true.
* The xref writer always prints the name of field.
* Set "" explicitly though the value pointed by VALUE is not referred,
*
*
* The other data type and the combination of types are not implemented yet.
*
*/
extern void attachParserField (tagEntryInfo *const tag, bool inCorkQueue, fieldType ftype, const char* value);
extern void attachParserField (tagEntryInfo *const tag, fieldType ftype, const char* value);
extern void attachParserFieldToCorkEntry (int index, fieldType ftype, const char* value);
extern const char* getParserFieldValueForType (tagEntryInfo *const tag, fieldType ftype);
extern int makePlaceholder (const char *const name);
extern void markTagPlaceholder (tagEntryInfo *e, bool placeholder);
/* Marking all tag entries entries under the scope specified
* with index recursively.
*
* The parser calling this function enables CORK_SYMTAB.
* Entries to be marked must be registered to the scope
* specified with index or its descendant scopes with
* registerEntry ().
*
* Call makePlaceholder () at the start of your parser for
* making the root scope where the entries are registered.
*/
extern void markAllEntriesInScopeAsPlaceholder (int index);
#ifdef CTAGS_LIB
extern void setTagEntryFunction(tagEntryFunction entry_function, void *user_data);
#endif
#endif /* CTAGS_MAIN_ENTRY_H */

View File

@ -1,77 +0,0 @@
/*
* Copyright (c) 2017, Red Hat, Inc.
* Copyright (c) 2017, Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* main part private interface to entry.c
*/
#ifndef CTAGS_PRIVATE_ENTRY_H
#define CTAGS_PRIVATE_ENTRY_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "entry.h"
#include "types.h"
/*
* FUNCTION PROTOTYPES
*/
extern const kindDefinition* getTagKind(const tagEntryInfo *const tag);
extern char getTagKindLetter(const tagEntryInfo *const tag);
extern const char* getTagKindName(const tagEntryInfo *const tag);
extern const roleDefinition* getTagRole(const tagEntryInfo *const tag, int roleIndex);
extern void freeTagFileResources (void);
extern const char *tagFileName (void);
extern void openTagFile (void);
extern void closeTagFile (const bool resize);
extern void setupWriter (void *writerClientData);
extern bool teardownWriter (const char *inputFilename);
extern unsigned long numTagsAdded(void);
extern void setNumTagsAdded (unsigned long nadded);
extern unsigned long numTagsTotal(void);
extern unsigned long maxTagsLine(void);
extern void invalidatePatternCache(void);
extern void tagFilePosition (MIOPos *p);
extern void setTagFilePosition (MIOPos *p, bool truncation);
extern const char* getTagFileDirectory (void);
extern void getTagScopeInformation (tagEntryInfo *const tag,
const char **kind, const char **name);
/* Getting line associated with tag */
extern char *readLineFromBypassForTag (vString *const vLine, const tagEntryInfo *const tag,
long *const pSeekValue);
/* Generating pattern associated tag, caller must do eFree for the returned value. */
extern char* makePatternString (const tagEntryInfo *const tag);
/* language is optional: can be NULL. */
extern bool writePseudoTag (const ptagDesc *pdesc,
const char *const fileName,
const char *const pattern,
const char *const parserName);
void corkTagFile(unsigned int corkFlags);
void uncorkTagFile(void);
extern void makeFileTag (const char *const fileName);
extern const tagField* getParserFieldForIndex (const tagEntryInfo * tag, int index);
CTAGS_INLINE roleBitsType makeRoleBit(int roleIndex)
{
if (roleIndex == ROLE_DEFINITION_INDEX)
return 0;
else
return ((roleBitsType)1) << roleIndex;
}
#endif /* CTAGS_PRIVATE_ENTRY_H */

View File

@ -1,38 +0,0 @@
/*
* Copyright (c) 2017, Red Hat, Inc.
* Copyright (c) 2017, Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* main part private interface to entry.c
*/
#include "general.h"
#include "entry_p.h"
#include "parse_p.h"
extern const kindDefinition* getTagKind(const tagEntryInfo *const tag)
{
return getLanguageKind(tag->langType, tag->kindIndex);
}
extern char getTagKindLetter(const tagEntryInfo *const tag)
{
kindDefinition *kdef = getLanguageKind(tag->langType, tag->kindIndex);
return kdef->letter;
}
extern const char* getTagKindName(const tagEntryInfo *const tag)
{
kindDefinition *kdef = getLanguageKind(tag->langType, tag->kindIndex);
return kdef->name;
}
extern const roleDefinition* getTagRole(const tagEntryInfo *const tag,
int roleIndex)
{
if (roleIndex == ROLE_DEFINITION_INDEX)
return NULL;
return getLanguageRole(tag->langType, tag->kindIndex, roleIndex);
}

View File

@ -11,13 +11,8 @@
#include <string.h>
#include <errno.h>
#include "error_p.h"
#include "options_p.h"
#include "routines_p.h"
#ifdef HAVE_JANSSON
#include <jansson.h>
#endif
#include "error.h"
#include "options.h"
#define selected(var,feature) (((int)(var) & (int)(feature)) == (int)feature)
@ -35,17 +30,14 @@ extern bool stderrDefaultErrorPrinter (const errorSelection selection,
va_list ap, void *data CTAGS_ATTR_UNUSED)
{
fprintf (stderr, "%s: %s", getExecutableName (),
selected (selection, WARNING) ? "Warning: " :
selected (selection, NOTICE) ? "Notice: " : "");
selected (selection, WARNING) ? "Warning: " : "");
vfprintf (stderr, format, ap);
if (selected (selection, PERROR))
{
#ifdef HAVE_STRERROR
fprintf (stderr, " : %s", strerror (errno));
#else
perror (" ");
perror (" ");
#endif
}
fputs ("\n", stderr);
return (selected (selection, FATAL) || Option.fatalWarnings)? true: false;
@ -57,9 +49,6 @@ extern void error (const errorSelection selection,
va_list ap;
bool shouldExit;
if (Option.quiet && selected (selection, NOTICE))
return;
va_start (ap, format);
shouldExit = (* errorPrinter) (selection, format, ap, errorPrinterData);
va_end (ap);
@ -68,35 +57,3 @@ extern void error (const errorSelection selection,
exit (1);
}
#ifdef HAVE_JANSSON
bool jsonErrorPrinter (const errorSelection selection, const char *const format, va_list ap,
void *data CTAGS_ATTR_UNUSED)
{
#define ERR_BUFFER_SIZE 4096
static char reason[ERR_BUFFER_SIZE];
vsnprintf (reason, ERR_BUFFER_SIZE, format, ap);
reason [ERR_BUFFER_SIZE - 1] = '\0'; /* Do we need this? */
json_t *response = json_object ();
json_object_set_new (response, "_type", json_string ("error"));
json_object_set_new (response, "message", json_string (reason));
if (selected (selection, NOTICE))
json_object_set_new (response, "notice", json_true ());
if (selected (selection, WARNING))
json_object_set_new (response, "warning", json_true ());
if (selected (selection, FATAL))
json_object_set_new (response, "fatal", json_true ());
if (selected (selection, PERROR))
{
json_object_set_new (response, "errno", json_integer (errno));
json_object_set_new (response, "perror", json_string (strerror (errno)));
}
json_dumpf (response, stdout, JSON_PRESERVE_ORDER);
fprintf (stdout, "\n");
json_decref (response);
return false;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -12,19 +12,10 @@
#ifndef CTAGS_MAIN_FIELD_H
#define CTAGS_MAIN_FIELD_H
/*
* INCLUDE FILES
*/
#include "general.h"
#include "types.h"
#include "vstring.h"
#include "optscript.h"
/*
* DATA DECLARATIONS
*/
typedef enum eFieldType { /* extension field content control */
FIELD_UNKNOWN = -1,
@ -33,92 +24,88 @@ typedef enum eFieldType { /* extension field content control */
FIELD_NAME,
FIELD_INPUT_FILE,
FIELD_PATTERN,
FIELD_ECTAGS_START,
FIELD_COMPACT_INPUT_LINE = FIELD_ECTAGS_START,
FIELD_COMPACT_INPUT_LINE,
/* EXTENSION FIELDS */
FIELD_JSON_LOOP_START,
FIELD_FILE_SCOPE = FIELD_JSON_LOOP_START,
FIELD_EXTENSION_START,
FIELD_ACCESS = FIELD_EXTENSION_START,
FIELD_FILE_SCOPE,
FIELD_INHERITANCE,
FIELD_KIND_LONG,
FIELD_KIND,
FIELD_LANGUAGE,
FIELD_IMPLEMENTATION,
FIELD_LINE_NUMBER,
FIELD_SIGNATURE,
FIELD_SCOPE,
FIELD_TYPE_REF,
FIELD_KIND_KEY,
FIELD_ECTAGS_LOOP_START,
FIELD_INHERITANCE = FIELD_ECTAGS_LOOP_START,
FIELD_ACCESS,
FIELD_IMPLEMENTATION,
FIELD_SIGNATURE,
FIELD_ECTAGS_LOOP_LAST = FIELD_SIGNATURE,
/* Extension fields newly introduced in Universal Ctags. */
FIELDS_UCTAGS_START,
FIELD_REF_MARK = FIELDS_UCTAGS_START,
/* EXTENSION FIELDS NEWLY INTRODUCED IN UCTAGS */
FIELD_ROLE,
FIELD_REF_MARK,
FIELD_SCOPE_KEY,
FIELD_SCOPE_KIND_LONG,
FIELD_UCTAGS_LOOP_START,
FIELD_ROLES = FIELD_UCTAGS_LOOP_START,
FIELD_EXTRAS,
FIELD_EXTRA,
FIELD_XPATH,
FIELD_END_LINE,
FIELD_EPOCH,
FIELD_NTH,
FIELD_BUILTIN_LAST = FIELD_NTH,
FIELD_SCOPE_KIND_LONG,
FIELD_END,
FIELD_BUILTIN_LAST = FIELD_END,
} fieldType ;
#define fieldDataTypeFalgs "sib" /* used in --list-fields */
typedef enum eFieldDataType {
FIELDTYPE_STRING = 1 << 0,
FIELDTYPE_INTEGER = 1 << 1,
FIELDTYPE_BOOL = 1 << 2,
/* used in --list-fields */
FIELDTYPE_END_MARKER = 1 << 3,
} fieldDataType;
typedef const char* (*fieldRenderer)(const tagEntryInfo *const,
const char *,
vString *);
typedef const char* (* renderEscaped) (const tagEntryInfo *const tag,
const char *value,
vString * buffer);
typedef bool (* isValueAvailable) (const struct sTagEntryInfo *const tag);
#define FIELD_LETTER_NO_USE '\0'
struct sFieldDefinition {
/* letter, and ftype are initialized in the main part,
typedef struct sFieldDefinition {
/* lettern, and ftype are initialized in the main part,
not in a parser. */
#define NUL_FIELD_LETTER '\0'
unsigned char letter;
const char* name;
const char* description;
bool enabled;
fieldRenderer render;
fieldRenderer renderNoEscaping;
bool (* doesContainAnyChar) (const tagEntryInfo *const, const char*, const char *);
bool (* isValueAvailable) (const tagEntryInfo *const);
const char * getterValueType;
EsObject * (* getValueObject) (const tagEntryInfo *, const fieldDefinition *);
const char * setterValueType;
/* Return es_false if passed value is acceptable.
Return an error object is unacceptable. */
EsObject * (* checkValueForSetter) (const fieldDefinition *, const EsObject *);
EsObject * (* setValueObject) (tagEntryInfo *, const fieldDefinition *, const EsObject *);
fieldDataType dataType; /* used in json output */
renderEscaped renderEscaped;
isValueAvailable isValueAvailable;
unsigned int ftype; /* Given from the main part */
};
} fieldDefinition;
extern fieldType getFieldTypeForOption (char letter);
/*
* FUNCTION PROTOTYPES
*/
`getFieldTypeForName' is for looking for a field not owned by any parser,
`getFieldTypeForNameAndLanguage' can be used for getting all fields having
the same name; specify `LANG_AUTO' as `language' parameter to get the first
field having the name. With the returned fieldType, `nextSiblingField' gets
the next field having the same name. `nextSiblingField' returns `FIELD_UNKNOWN'
at the end of iteration.
Specifying `LANG_IGNORE' has the same effects as `LANG_AUTO'. However,
internally, each parser is not initialized. `LANG_IGNORE' is a bit faster. */
extern fieldType getFieldTypeForName (const char *name);
extern fieldType getFieldTypeForNameAndLanguage (const char *fieldName, langType language);
extern bool isFieldEnabled (fieldType type);
extern bool enableField (fieldType type, bool state, bool warnIfFixedField);
extern bool isCommonField (fieldType type);
extern int getFieldOwner (fieldType type);
extern const char* getFieldName (fieldType type);
extern void printFields (int language);
extern bool isFieldRenderable (fieldType type);
extern bool doesFieldHaveValue (fieldType type, const tagEntryInfo *tag);
extern const char* renderFieldEscaped (fieldType type, const tagEntryInfo *tag, int index);
extern void initFieldDescs (void);
extern int countFields (void);
/* language should be typed to langType.
Use int here to avoid circular dependency */
extern int defineField (fieldDefinition *spec, langType language);
extern fieldType nextSiblingField (fieldType type);
#endif /* CTAGS_MAIN_FIELD_H */

View File

@ -1,91 +0,0 @@
/*
*
* Copyright (c) 2015, Red Hat, Inc.
* Copyright (c) 2015, Masatake YAMATO
*
* Author: Masatake YAMATO <yamato@redhat.com>
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#ifndef CTAGS_MAIN_FIELD_PRIVATE_H
#define CTAGS_MAIN_FIELD_PRIVATE_H
/*
* INCLUDE FILES
*/
#include "general.h"
#include "colprint_p.h"
#include "field.h"
#include "optscript.h"
/*
* DATA DECLARATIONS
*/
/*
* FUNCTION PROTOTYPES
*/
extern fieldType getFieldTypeForOption (char letter);
/*
`getFieldTypeForName' is for looking for a field not owned by any parser,
`getFieldTypeForNameAndLanguage' can be used for getting all fields having
the same name; specify `LANG_AUTO' as `language' parameter to get the first
field having the name. With the returned fieldType, `nextSiblingField' gets
the next field having the same name. `nextSiblingField' returns `FIELD_UNKNOWN'
at the end of iteration.
Specifying `LANG_IGNORE' has the same effects as `LANG_AUTO'. However,
internally, each parser is not initialized. `LANG_IGNORE' is a bit faster. */
extern fieldType getFieldTypeForName (const char *name);
extern fieldType getFieldTypeForNameAndLanguage (const char *fieldName, langType language);
extern bool enableField (fieldType type, bool state);
extern bool isCommonField (fieldType type);
extern int getFieldOwner (fieldType type);
extern const char* getFieldDescription (fieldType type);
extern const char* getFieldName (fieldType type);
extern unsigned char getFieldLetter (fieldType type);
extern unsigned int getFieldDataType (fieldType type);
extern bool isFieldValueAvailableAlways (fieldType type);
/* Whether the field specified with TYPE has a
method for rendering in the current format. */
extern bool doesFieldHaveRenderer (fieldType type, bool noEscaping);
extern bool doesFieldHaveValue (fieldType type, const tagEntryInfo *tag);
extern const char* renderField (fieldType type, const tagEntryInfo *tag, int index);
extern const char* renderFieldNoEscaping (fieldType type, const tagEntryInfo *tag, int index);
extern bool doesFieldHaveTabOrNewlineChar (fieldType type, const tagEntryInfo *tag, int index);
extern void initFieldObjects (void);
extern int countFields (void);
/* language should be typed to langType.
Use int here to avoid circular dependency */
extern int defineField (fieldDefinition *spec, langType language);
extern fieldType nextSiblingField (fieldType type);
/* --list-fields implementation. LANGUAGE must be initialized. */
extern struct colprintTable * fieldColprintTableNew (void);
extern void fieldColprintAddCommonLines (struct colprintTable *table);
extern void fieldColprintAddLanguageLines (struct colprintTable *table, langType language);
extern void fieldColprintTablePrint (struct colprintTable *table,
bool withListHeader, bool machinable, FILE *fp);
/* tag is assumed that it is in the cork queue. */
extern EsObject * getFieldValue (fieldType type, const tagEntryInfo *tag);
extern bool hasFieldGetter (fieldType type);
extern const char * getFieldGetterValueType (fieldType type);
extern EsObject * setFieldValue (fieldType type, tagEntryInfo *tag, const EsObject *val);
extern bool hasFieldSetter (fieldType type);
extern const char * getFieldSetterValueType (fieldType type);
extern bool hasFieldValueCheckerForSetter (fieldType type);
extern EsObject *checkFieldValueForSetter (fieldType type, const EsObject *val);
#endif /* CTAGS_MAIN_FIELD_PRIVATE_H */

View File

@ -16,61 +16,56 @@
#include <string.h>
#include <stdio.h>
#include "ctags.h"
#include "flags_p.h"
#include "flags.h"
#include "vstring.h"
#include "routines.h"
extern const char *flagsEval (const char* flags_original, flagDefinition* defs, unsigned int ndefs, void* data)
void flagsEval (const char* flags_original, flagDefinition* defs, unsigned int ndefs, void* data)
{
unsigned int i, j;
char *flags;
const char *optscript = NULL;
if (!flags_original)
return NULL;
return;
if (!defs)
return;
flags = eStrdup (flags_original);
for (i = 0 ; flags [i] != '\0' ; ++i)
{
if (flags [i] == LONG_FLAGS_OPEN && flags [i + 1] == LONG_FLAGS_OPEN)
{
optscript = flags_original + i;
break;
}
else if (flags [i] == LONG_FLAGS_OPEN)
if (flags [i] == LONG_FLAGS_OPEN)
{
const char* aflag = flags + i + 1;
char* needle_close_paren = strchr(aflag, LONG_FLAGS_CLOSE);
const char* param;
char* needle_equal;
char* needle_eqaul;
if (needle_close_paren == NULL)
{
error (WARNING, "long flags specifier opened with `%c' is not closed `%c': \"%s\"",
LONG_FLAGS_OPEN, LONG_FLAGS_CLOSE, flags_original);
error (WARNING, "long flags specifier opened with `%c' is not closed `%c'",
LONG_FLAGS_OPEN, LONG_FLAGS_CLOSE);
break;
}
*needle_close_paren = '\0';
needle_equal = strchr(aflag, '=');
if ((needle_equal == NULL || (needle_equal >= needle_close_paren)))
needle_eqaul = strchr(aflag, '=');
if ((needle_eqaul == NULL || (needle_eqaul >= needle_close_paren)))
{
needle_equal = NULL;
needle_eqaul = NULL;
param = NULL;
}
else
{
param = needle_equal + 1;
*needle_equal = '\0';
param = needle_eqaul + 1;
*needle_eqaul = '\0';
}
for ( j = 0 ; j < ndefs ; ++j )
if (defs[j].longStr && (strcmp(aflag, defs[j].longStr) == 0))
defs[j].longProc(aflag, param, data);
if (needle_equal)
*needle_equal = '=';
if (needle_eqaul)
*needle_eqaul = '=';
*needle_close_paren = LONG_FLAGS_CLOSE;
i = needle_close_paren - flags;
@ -80,78 +75,33 @@ extern const char *flagsEval (const char* flags_original, flagDefinition* defs,
defs[j].shortProc(flags[i], data);
}
eFree (flags);
return optscript;
}
extern struct colprintTable * flagsColprintTableNew (void)
void flagPrintHelp (flagDefinition* def, unsigned int ndefs)
{
return colprintTableNew ("L:LETTER", "L:NAME", "L:DESCRIPTION", NULL);
}
extern void flagsColprintAddDefinitions (struct colprintTable *table, flagDefinition* def,
unsigned int ndefs)
{
vString *longName = vStringNew ();
for (unsigned int i = 0; i < ndefs; i++)
unsigned int i;
const char *longStr;
const char *description;
const char *paramName;
char shortChar[3];
for ( i = 0; i < ndefs; ++i )
{
struct colprintLine * line;
char shortChar;
const char *paramName;
const char *description;
line = colprintTableGetNewLine(table);
shortChar = def[i].shortChar;
if (shortChar == '\0')
shortChar = '-';
colprintLineAppendColumnChar (line, shortChar);
vStringCopyS (longName, def[i].longStr? def[i].longStr: RSV_NONE);
paramName = def[i].paramName;
if (paramName)
{
vStringPut (longName, '=');
vStringCatS (longName, paramName);
}
colprintLineAppendColumnVString (line, longName);
vStringClear(longName);
longStr = def[i].longStr? def[i].longStr: "";
description = def[i].description? def[i].description: "";
colprintLineAppendColumnCString (line, description);
paramName = def[i].paramName;
if (def[i].shortChar == '\0')
strcpy (shortChar, "\\0");
else
{
shortChar[0] = def[i].shortChar;
shortChar[1] = '\0';
}
if (paramName)
printf ("%s\t%s=%s\t%s\n", shortChar, longStr, paramName, description);
else
printf ("%s\t%s\t%s\n", shortChar, longStr, description);
}
vStringDelete(longName);
}
static int flagsColprintCompareLines(struct colprintLine *a , struct colprintLine *b)
{
const char *a_letter = colprintLineGetColumn (a, 0);
const char *b_letter = colprintLineGetColumn (b, 0);
if (a_letter[0] != '-' && b_letter[0] == '-')
return -1;
else if (a_letter[0] == '-' && b_letter[0] != '-')
return 1;
else if (a_letter[0] != '-' && b_letter[0] != '-')
return strcmp(a_letter, b_letter);
const char *a_name = colprintLineGetColumn (a, 1);
const char *b_name = colprintLineGetColumn (b, 1);
if (a_name[0] != '_' && b_name[0] == '_')
return -1;
else if (a_name[0] == '_' && b_name[0] != '_')
return 1;
return strcmp(a_name, b_name);
}
extern void flagsColprintTablePrint (struct colprintTable *table,
bool withListHeader, bool machinable, FILE *fp)
{
colprintTableSort (table, flagsColprintCompareLines);
colprintTablePrint (table, 0, withListHeader, machinable, fp);
}

View File

@ -8,12 +8,8 @@
*
* Defines external interface to option processing.
*/
#ifndef CTAGS_MAIN_FLAGS_PRIVATE_H
#define CTAGS_MAIN_FLAGS_PRIVATE_H
#include "general.h"
#include "colprint_p.h"
#ifndef CTAGS_MAIN_FLAGS_H
#define CTAGS_MAIN_FLAGS_H
#define LONG_FLAGS_OPEN '{'
#define LONG_FLAGS_CLOSE '}'
@ -27,10 +23,7 @@ typedef struct sFlagDefinition {
const char *description;
} flagDefinition;
/* Return {{optscript}} part. */
extern const char* flagsEval (const char* flags, flagDefinition* defs, unsigned int ndefs, void* data);
extern struct colprintTable * flagsColprintTableNew (void);
extern void flagsColprintAddDefinitions (struct colprintTable *table, flagDefinition* def, unsigned int ndefs);
extern void flagsColprintTablePrint (struct colprintTable *table,
bool withListHeader, bool machinable, FILE *fp);
#endif /* CTAGS_MAIN_FLAGS_PRIVATE_H */
extern void flagsEval (const char* flags, flagDefinition* defs, unsigned int ndefs, void* data);
extern void flagPrintHelp (flagDefinition* def, unsigned int ndefs);
#endif /* CTAGS_MAIN_FLAGS_H */

View File

@ -12,10 +12,9 @@
#include "general.h"
#include "debug.h"
#include "entry_p.h"
#include "fmt_p.h"
#include "fmt.h"
#include "field.h"
#include "field_p.h"
#include "options.h"
#include "parse.h"
#include "routines.h"
#include <string.h>
@ -26,7 +25,6 @@ typedef union uFmtSpec {
struct {
fieldType ftype;
int width;
char *raw_fmtstr;
} field;
} fmtSpec;
@ -61,49 +59,31 @@ static int printTagField (fmtSpec* fspec, MIO* fp, const tagEntryInfo * tag)
ftype = fspec->field.ftype;
if (isCommonField (ftype))
str = renderField (ftype, tag, NO_PARSER_FIELD);
str = renderFieldEscaped (ftype, tag, NO_PARSER_FIELD);
else
{
unsigned int findex;
const tagField *f;
for (findex = 0; findex < tag->usedParserFields; findex++)
{
f = getParserFieldForIndex(tag, findex);
if (isParserFieldCompatibleWithFtype (f, ftype))
if (isParserFieldCompatibleWithFtype (tag->parserFields + findex, ftype))
break;
}
if (findex == tag->usedParserFields)
str = "";
else if (isFieldEnabled (f->ftype))
{
unsigned int dt = getFieldDataType (f->ftype);
if (dt & FIELDTYPE_STRING)
{
str = renderField (f->ftype, tag, findex);
if ((dt & FIELDTYPE_BOOL) && str[0] == '\0')
{
/* TODO: FIELD_NULL_LETTER_STRING */
str = "-";
}
}
else if (dt & FIELDTYPE_BOOL)
str = getFieldName (f->ftype);
else
{
/* Not implemented */
AssertNotReached ();
str = "CTAGS INTERNAL BUG!";
}
}
else if (isFieldEnabled (tag->parserFields [findex].ftype))
str = renderFieldEscaped (tag->parserFields [findex].ftype,
tag, findex);
}
if (str == NULL)
str = "";
if (width)
i = mio_printf (fp, fspec->field.raw_fmtstr, width, str);
if (width < 0)
i = mio_printf (fp, "%-*s", -1 * width, str);
else if (width > 0)
i = mio_printf (fp, "%*s", width, str);
else
{
mio_puts (fp, str);
@ -179,8 +159,8 @@ static langType getLanguageComponentInFieldName (const char *fullName,
return language;
}
static fmtElement** queueTagField (fmtElement **last, long width, bool truncation,
char field_letter, const char *field_name)
static fmtElement** queueTagField (fmtElement **last, long width, char field_letter,
const char *field_name)
{
fieldType ftype;
fmtElement *cur;
@ -209,7 +189,7 @@ static fmtElement** queueTagField (fmtElement **last, long width, bool truncatio
error (FATAL, "No such field letter: %c", field_letter);
}
if (!doesFieldHaveRenderer (ftype, false))
if (!isFieldRenderable (ftype))
{
Assert (field_letter != NUL_FIELD_LETTER);
error (FATAL, "The field cannot be printed in format output: %c", field_letter);
@ -220,23 +200,13 @@ static fmtElement** queueTagField (fmtElement **last, long width, bool truncatio
cur->spec.field.width = width;
cur->spec.field.ftype = ftype;
if (width < 0)
{
cur->spec.field.width *= -1;
cur->spec.field.raw_fmtstr = (truncation? "%-.*s": "%-*s");
}
else if (width > 0)
cur->spec.field.raw_fmtstr = (truncation? "%.*s": "%*s");
else
cur->spec.field.raw_fmtstr = NULL;
enableField (ftype, true);
enableField (ftype, true, false);
if (language == LANG_AUTO)
{
fieldType ftype_next = ftype;
while ((ftype_next = nextSiblingField (ftype_next)) != FIELD_UNKNOWN)
enableField (ftype_next, true);
enableField (ftype_next, true, false);
}
cur->printer = printTagField;
@ -271,7 +241,6 @@ extern fmtElement *fmtNew (const char* fmtString)
else
{
int justification_right = 1;
bool truncation = false;
vString *width = NULL;
if (literal)
{
@ -288,14 +257,6 @@ extern fmtElement *fmtNew (const char* fmtString)
error (FATAL, "unexpectedly terminated just after '-': \"%s\"", fmtString);
}
if (cursor [i] == '.')
{
truncation = true;
i++;
if (cursor [i] == '\0')
error (FATAL, "unexpectedly terminated just after '.': \"%s\"", fmtString);
}
while ( '0' <= cursor[i] && cursor[i] <= '9' )
{
@ -315,7 +276,7 @@ extern fmtElement *fmtNew (const char* fmtString)
if (width)
{
if(!strToLong (vStringValue (width), 0, &column_width))
error (FATAL | PERROR, "converting failed: %s", vStringValue (width));
error (FATAL | PERROR, "coverting failed: %s", vStringValue (width));
vStringDelete (width);
width = NULL;
column_width *= justification_right;
@ -329,14 +290,13 @@ extern fmtElement *fmtNew (const char* fmtString)
for (; cursor[i] != '}'; i++)
vStringPut (field_name, cursor[i]);
last = queueTagField (last, column_width, truncation,
NUL_FIELD_LETTER, vStringValue (field_name));
last = queueTagField (last, column_width, NUL_FIELD_LETTER,
vStringValue (field_name));
vStringDelete (field_name);
}
else
last = queueTagField (last, column_width, truncation,
cursor[i], NULL);
last = queueTagField (last, column_width, cursor[i], NULL);
}
}

View File

@ -14,14 +14,16 @@
/* Prevent warnings about unused variables in GCC. */
#if defined (__GNUC__) && !defined (__GNUG__)
# define CTAGS_ATTR_UNUSED __attribute__((unused))
# ifdef __MINGW32__
# define CTAGS_ATTR_UNUSED
# else
# define CTAGS_ATTR_UNUSED __attribute__((unused))
# endif
# define CTAGS_ATTR_PRINTF(s,f) __attribute__((format (printf, s, f)))
# define CTAGA_ATTR_ALIGNED(X) __attribute__((aligned(X)))
# define attr__noreturn __attribute__((__noreturn__))
#else
# define CTAGS_ATTR_UNUSED
# define CTAGS_ATTR_PRINTF(s,f)
# define CTAGA_ATTR_ALIGNED(X)
# define attr__noreturn
#endif

View File

@ -14,13 +14,13 @@
*/
#if defined (HAVE_CONFIG_H)
# include <config.h>
#if (defined (HAVE_FORK) && defined (HAVE_WAITPID) && defined (HAVE_EXECV) && defined (HAVE_PIPE))
#define HAVE_COPROC
#endif
#elif defined (WIN32)
# include "e_msoft.h"
#endif
/* To provide timings features.
*/
#include <time.h>
/*
* MACROS
@ -50,18 +50,24 @@
* DATA DECLARATIONS
*/
#ifdef HAVE_STDBOOL_H
#ifdef USE_STDBOOL_H
# include <stdbool.h>
#endif
/*
* HACK for #1610.
* FUNCTION PROTOTYPES
*/
#ifdef ICONV_USE_LIB_PREFIX
#define iconv libiconv
#define iconv_open libiconv_open
#define iconv_close libiconv_close
#if defined (NEED_PROTO_REMOVE) && defined (HAVE_REMOVE)
extern int remove (const char *);
#endif
#if defined (NEED_PROTO_UNLINK) && ! defined (HAVE_REMOVE)
extern void *unlink (const char *);
#endif
#ifdef NEED_PROTO_GETENV
extern char *getenv (const char *);
#endif
#endif /* CTAGS_MAIN_GENERAL_H */

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 1998-2003, Darren Hiebert
* Copyright (c) 2018, Red Hat, Inc.
* Copyright (c) 2018, Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Declare variables visible to parsers
*/
#ifndef CTAGS_GVARS_H
#define CTAGS_GVARS_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#ifdef DEBUG
/* -d debugging output */
extern long ctags_debugLevel;
#endif /* DEBUG */
/* -V verbose */
extern bool ctags_verbose;
#endif /* CTAGS_GVARS_H */

View File

@ -43,18 +43,10 @@ struct sHashTable {
unsigned int size;
hashTableHashFunc hashfn;
hashTableEqualFunc equalfn;
hashTableDeleteFunc keyfreefn;
hashTableDeleteFunc valfreefn;
void *valForNotUnknownKey;
hashTableDeleteFunc valForNotUnknownKeyfreefn;
hashTableFreeFunc keyfreefn;
hashTableFreeFunc valfreefn;
};
struct chainTracker {
const void *const target_key;
hashTableForeachFunc user_proc;
void *user_data;
hashTableEqualFunc equalfn;
};
static hentry* entry_new (void *key, void *value, hentry* next)
{
@ -67,27 +59,18 @@ static hentry* entry_new (void *key, void *value, hentry* next)
return entry;
}
static void entry_reset (hentry* entry,
void *newkey,
void *newval,
hashTableDeleteFunc keyfreefn,
hashTableDeleteFunc valfreefn)
static hentry* entry_destroy (hentry* entry,
hashTableFreeFunc keyfreefn,
hashTableFreeFunc valfreefn)
{
hentry* tmp;
if (keyfreefn)
keyfreefn (entry->key);
if (valfreefn)
valfreefn (entry->value);
entry->key = newkey;
entry->value = newval;
}
static hentry* entry_destroy (hentry* entry,
hashTableDeleteFunc keyfreefn,
hashTableDeleteFunc valfreefn)
{
hentry* tmp;
entry_reset (entry, NULL, NULL, keyfreefn, valfreefn);
entry->key = NULL;
entry->value = NULL;
tmp = entry->next;
eFree (entry);
@ -95,15 +78,14 @@ static hentry* entry_destroy (hentry* entry,
}
static void entry_reclaim (hentry* entry,
hashTableDeleteFunc keyfreefn,
hashTableDeleteFunc valfreefn)
hashTableFreeFunc keyfreefn,
hashTableFreeFunc valfreefn)
{
while (entry)
entry = entry_destroy (entry, keyfreefn, valfreefn);
}
static void *entry_find (hentry* entry, const void* const key, hashTableEqualFunc equalfn,
void *valForNotUnknownKey)
static void *entry_find (hentry* entry, const void* const key, hashTableEqualFunc equalfn)
{
while (entry)
{
@ -111,11 +93,11 @@ static void *entry_find (hentry* entry, const void* const key, hashTableEqualFun
return entry->value;
entry = entry->next;
}
return valForNotUnknownKey;
return NULL;
}
static bool entry_delete (hentry **entry, const void *key, hashTableEqualFunc equalfn,
hashTableDeleteFunc keyfreefn, hashTableDeleteFunc valfreefn)
static bool entry_delete (hentry **entry, void *key, hashTableEqualFunc equalfn,
hashTableFreeFunc keyfreefn, hashTableFreeFunc valfreefn)
{
while (*entry)
{
@ -124,42 +106,25 @@ static bool entry_delete (hentry **entry, const void *key, hashTableEqualFunc e
*entry = entry_destroy (*entry, keyfreefn, valfreefn);
return true;
}
entry = &((*entry)->next);
}
return false;
}
static bool entry_update (hentry *entry, void *key, void *value, hashTableEqualFunc equalfn,
hashTableDeleteFunc keyfreefn, hashTableDeleteFunc valfreefn)
static void entry_foreach (hentry *entry, hashTableForeachFunc proc, void *user_data)
{
while (entry)
{
if (equalfn (key, entry->key))
{
entry_reset (entry, key, value, keyfreefn, valfreefn);
return true;
}
proc (entry->key, entry->value, user_data);
entry = entry->next;
}
return false;
}
static bool entry_foreach (hentry *entry, hashTableForeachFunc proc, void *user_data)
{
while (entry)
{
if (!proc (entry->key, entry->value, user_data))
return false;
entry = entry->next;
}
return true;
}
extern hashTable *hashTableNew (unsigned int size,
hashTableHashFunc hashfn,
hashTableEqualFunc equalfn,
hashTableDeleteFunc keyfreefn,
hashTableDeleteFunc valfreefn)
hashTableFreeFunc keyfreefn,
hashTableFreeFunc valfreefn)
{
hashTable *htable;
@ -171,23 +136,10 @@ extern hashTable *hashTableNew (unsigned int size,
htable->equalfn = equalfn;
htable->keyfreefn = keyfreefn;
htable->valfreefn = valfreefn;
htable->valForNotUnknownKey = NULL;
htable->valForNotUnknownKeyfreefn = NULL;
return htable;
}
extern void hashTableSetValueForUnknownKey (hashTable *htable,
void *val,
hashTableDeleteFunc valfreefn)
{
if (htable->valfreefn)
htable->valfreefn (htable->valForNotUnknownKey);
htable->valForNotUnknownKey = val;
htable->valForNotUnknownKeyfreefn = valfreefn;
}
extern void hashTableDelete (hashTable *htable)
{
if (!htable)
@ -195,8 +147,6 @@ extern void hashTableDelete (hashTable *htable)
hashTableClear (htable);
if (htable->valForNotUnknownKeyfreefn)
htable->valForNotUnknownKeyfreefn (htable->valForNotUnknownKey);
eFree (htable->table);
eFree (htable);
}
@ -230,10 +180,10 @@ extern void* hashTableGetItem (hashTable *htable, const void * key)
unsigned int i;
i = htable->hashfn (key) % htable->size;
return entry_find(htable->table[i], key, htable->equalfn, htable->valForNotUnknownKey);
return entry_find(htable->table[i], key, htable->equalfn);
}
extern bool hashTableDeleteItem (hashTable *htable, const void *key)
extern bool hashTableDeleteItem (hashTable *htable, void *key)
{
unsigned int i;
@ -242,69 +192,26 @@ extern bool hashTableDeleteItem (hashTable *htable, const void *key)
htable->equalfn, htable->keyfreefn, htable->valfreefn);
}
extern bool hashTableUpdateItem (hashTable *htable, void *key, void *value)
{
unsigned int i;
i = htable->hashfn (key) % htable->size;
bool r = entry_update(htable->table[i], key, value,
htable->equalfn, htable->keyfreefn, htable->valfreefn);
if (!r)
htable->table[i] = entry_new(key, value, htable->table[i]);
return r;
}
extern bool hashTableHasItem (hashTable *htable, const void *key)
{
return hashTableGetItem (htable, key) == htable->valForNotUnknownKey? false: true;
return hashTableGetItem (htable, key)? true: false;
}
extern bool hashTableForeachItem (hashTable *htable, hashTableForeachFunc proc, void *user_data)
extern void hashTableForeachItem (hashTable *htable, hashTableForeachFunc proc, void *user_data)
{
unsigned int i;
for (i = 0; i < htable->size; i++)
if (!entry_foreach(htable->table[i], proc, user_data))
return false;
return true;
entry_foreach(htable->table[i], proc, user_data);
}
static bool track_chain (const void *const key, void *value, void *chain_data)
{
struct chainTracker *chain_tracker = chain_data;
if (chain_tracker->equalfn (chain_tracker->target_key, key))
{
if (! chain_tracker->user_proc (key, value, chain_tracker->user_data))
return false;
}
return true;
}
extern bool hashTableForeachItemOnChain (hashTable *htable, const void *key, hashTableForeachFunc proc, void *user_data)
{
unsigned int i;
struct chainTracker chain_tracker = {
.target_key = key,
.user_proc = proc,
.user_data = user_data,
.equalfn = htable->equalfn,
};
i = htable->hashfn (key) % htable->size;
if (!entry_foreach(htable->table[i], track_chain, &chain_tracker))
return false;
return true;
}
static bool count (const void *const key CTAGS_ATTR_UNUSED, void *value CTAGS_ATTR_UNUSED, void *data)
static void count (void *key CTAGS_ATTR_UNUSED, void *value CTAGS_ATTR_UNUSED, void *data)
{
int *c = data;
++*c;
return true;
}
extern unsigned int hashTableCountItem (hashTable *htable)
extern int hashTableCountItem (hashTable *htable)
{
int c = 0;
hashTableForeachItem (htable, count, &c);

View File

@ -12,29 +12,12 @@
#define CTAGS_MAIN_HTABLE_H
#include "general.h"
#include <stdint.h>
/* This hashtable allows adding multiple items for the same key.
*
* hashTablePutItem() adds a key/item pair to the htable even if the
* htable has an item for the key already.
*
* hashTableGetItem() returns the first occurrence item for the given
* key.
*
* hashTableDeleteItem() deletes the first occurrence item for the given
* key.
*
* Use hashTableForeachItemOnChain () to process all items for the same key.
*/
typedef struct sHashTable hashTable;
typedef unsigned int (* hashTableHashFunc) (const void * const key);
typedef bool (* hashTableEqualFunc) (const void* a, const void* b);
typedef void (* hashTableDeleteFunc) (void * ptr);
/* To continue interation, return true.
* To break interation, return false. */
typedef bool (* hashTableForeachFunc) (const void *key, void *value, void *user_data);
typedef void (* hashTableFreeFunc) (void * ptr);
typedef void (* hashTableForeachFunc) (void *key, void *value, void* user_data);
unsigned int hashPtrhash (const void * x);
bool hashPtreq (const void * a, const void * constb);
@ -51,45 +34,15 @@ bool hashInteq (const void * a, const void * b);
extern hashTable* hashTableNew (unsigned int size,
hashTableHashFunc hashfn,
hashTableEqualFunc equalfn,
hashTableDeleteFunc keyfreefn,
hashTableDeleteFunc valfreefn);
/* By default, hashTableGetItem() returns NULL for a unknown key.
* It means you cannot store NULL as a value for a key.
* With hashTableSetValueForUnknownKey(), you can specific
* an alternative address representing the value for for unknown
* keys.
*/
extern void hashTableSetValueForUnknownKey (hashTable *htable,
void *val,
hashTableDeleteFunc valfreefn);
hashTableFreeFunc keyfreefn,
hashTableFreeFunc valfreefn);
extern void hashTableDelete (hashTable *htable);
extern void hashTableClear (hashTable *htable);
extern void hashTablePutItem (hashTable *htable, void *key, void *value);
extern void* hashTableGetItem (hashTable *htable, const void * key);
extern bool hashTableHasItem (hashTable * htable, const void * key);
extern bool hashTableDeleteItem (hashTable *htable, const void *key);
extern bool hashTableUpdateItem (hashTable *htable, void *key, void *value);
/* Return true if proc never returns false; proc returns true for all
* the items, or htable holds no item.
*
* Return false if htable holds at least one item and proc returns false
* for one of the items. */
extern bool hashTableForeachItem (hashTable *htable, hashTableForeachFunc proc, void *user_data);
/* This function is useful for htable having multiple items for a key.
* By giving a key, you can traverse all the items associated with the
* key via proc. * "Chain" means group of items associated with a
* key. */
extern bool hashTableForeachItemOnChain (hashTable *htable, const void *key, hashTableForeachFunc proc, void *user_data);
extern unsigned int hashTableCountItem (hashTable *htable);
#define HT_PTR_TO_INT(P) ((int)(intptr_t)(P))
#define HT_INT_TO_PTR(P) ((void*)(intptr_t)(P))
#define HT_PTR_TO_UINT(P) ((unsigned int)(uintptr_t)(P))
#define HT_UINT_TO_PTR(P) ((void*)(uintptr_t)(P))
extern bool hashTableDeleteItem (hashTable *htable, void *key);
extern void hashTableForeachItem (hashTable *htable, hashTableForeachFunc proc, void *user_data);
extern int hashTableCountItem (hashTable *htable);
#endif /* CTAGS_MAIN_HTABLE_H */

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 2016, Aman Gupta
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Defines interface to interactive loop.
*/
#ifndef CTAGS_MAIN_INTERACTIVE_H
#define CTAGS_MAIN_INTERACTIVE_H
#include "general.h"
#include "options_p.h"
#include "routines.h"
struct interactiveModeArgs
{
bool sandbox;
};
void interactiveLoop (cookedArgs *args, void *user);
bool jsonErrorPrinter (const errorSelection selection, const char *const format, va_list ap,
void *data);
int installSyscallFilter (void);
#endif /* CTAGS_MAIN_INTERACTIVE_H */
/* vi:set tabstop=4 shiftwidth=4: */

View File

@ -17,8 +17,7 @@
#include "debug.h"
#include "keyword.h"
#include "keyword_p.h"
#include "parse.h"
#include "options.h"
#include "routines.h"
/*
@ -241,36 +240,3 @@ extern void printKeywordTable (void)
}
#endif
extern void dumpKeywordTable (FILE *fp)
{
unsigned int i;
for (i = 0 ; i < TableSize ; ++i)
{
hashEntry **const table = getHashTable ();
hashEntry *entry = table [i];
while (entry != NULL)
{
fprintf(fp, "%s %s\n", entry->string, getLanguageName (entry->language));
entry = entry->next;
}
}
}
extern void addKeywordGroup (const struct keywordGroup *const groupdef,
langType language)
{
for (int i = 0; groupdef->keywords[i]; i++)
{
if (groupdef->addingUnlessExisting)
{
if (lookupKeyword (groupdef->keywords[i],
language) != KEYWORD_NONE)
continue; /* already added */
}
else
Assert (lookupKeyword (groupdef->keywords[i],
language) == KEYWORD_NONE);
addKeyword (groupdef->keywords[i], language, groupdef->value);
}
}

View File

@ -13,11 +13,10 @@
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "types.h"
/*
* MACROS
*/
#include "types.h"
#include "vstring.h"
#define KEYWORD_NONE -1
/*
@ -26,16 +25,9 @@
extern void addKeyword (const char *const string, langType language, int value);
extern int lookupKeyword (const char *const string, langType language);
extern int lookupCaseKeyword (const char *const string, langType language);
extern void freeKeywordTable (void);
#ifdef DEBUG
extern void printKeywordTable (void);
#endif
/*
* KEYWORD GROUP API: Adding keywords for value in batch
*/
struct keywordGroup {
int value;
bool addingUnlessExisting;
const char *keywords []; /* NULL terminated */
};
extern void addKeywordGroup (const struct keywordGroup *const groupdef,
langType language);
#endif /* CTAGS_MAIN_KEYWORD_H */

View File

@ -1,26 +0,0 @@
/*
* Copyright (c) 1998-2002, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* main part private interface to keyword.c
*/
#ifndef CTAGS_MAIN_KEYWORD_PRIVATE_H
#define CTAGS_MAIN_KEYWORD_PRIVATE_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include <stdio.h>
extern void freeKeywordTable (void);
extern void dumpKeywordTable (FILE *fp);
#ifdef DEBUG
extern void printKeywordTable (void);
#endif
#endif /* CTAGS_MAIN_KEYWORD_PRIVATE_H */

View File

@ -12,46 +12,16 @@
#include "general.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "colprint_p.h"
#include "ctags.h"
#include "debug.h"
#include "entry.h"
#include "kind.h"
#include "parse_p.h"
#include "options.h"
#include "ptrarray.h"
#include "routines.h"
#include "vstring.h"
#include "parse.h"
typedef struct sRoleObject {
roleDefinition *def;
freeRoleDefFunc free;
} roleObject;
struct roleControlBlock {
roleObject *role;
unsigned int count;
int owner;
};
typedef struct sKindObject {
kindDefinition *def;
freeKindDefFunc free;
struct roleControlBlock *rcb;
ptrArray * dynamicSeparators;
} kindObject;
struct kindControlBlock {
kindObject *kind;
unsigned int count;
langType owner;
scopeSeparator defaultScopeSeparator;
scopeSeparator defaultRootScopeSeparator;
};
extern void printRole (const roleDefinition* const role)
{
if (role)
printf ("%s\t%s\t%s\n", role->name, role->description, role->enabled? "on": "off");
}
extern const char *renderRole (const roleDefinition* const role, vString* b)
{
@ -59,12 +29,117 @@ extern const char *renderRole (const roleDefinition* const role, vString* b)
return vStringValue (b);
}
extern void printKind (const kindDefinition* const kind, bool indent)
#define PR_KIND_WIDTH_LETTER 7
#define PR_KIND_WIDTH_NAME 15
#define PR_KIND_WIDTH_DESCRIPTION 30
#define PR_KIND_WIDTH_ENABLED 8
#define PR_KIND_WIDTH_REFONLY 7
#define PR_KIND_WIDTH_NROLE 6
#define PR_KIND_WIDTH_MASTER 10
#define MAKE_KIND_FMT(PREFIX,LETTER_SPEC,NROLL_SPEC) \
PREFIX \
PR_KIND_FMT (LETTER,LETTER_SPEC) \
" " \
PR_KIND_FMT (NAME,s) \
" " \
PR_KIND_FMT (ENABLED,s) \
" " \
PR_KIND_FMT (REFONLY,s) \
" " \
PR_KIND_FMT (NROLE,NROLL_SPEC) \
" " \
PR_KIND_FMT (MASTER,s) \
" " \
PR_KIND_FMT (DESCRIPTION,s) \
"\n"
extern void printKindListHeader (bool indent, bool tabSeparated)
{
printf ("%s%c %s%s\n", indent ? " " : "", kind->letter,
#define KIND_HEADER_COMMON_FMT MAKE_KIND_FMT("%s", s, s)
const char *fmt = tabSeparated
? "%s%s%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
: (indent
? PR_KIND_FMT (LANG,s) KIND_HEADER_COMMON_FMT
: "%s" KIND_HEADER_COMMON_FMT)
;
printf (fmt,
(indent? "#PARSER": ""),
(indent? (tabSeparated? "\t": " "): ""),
(indent? "LETTER": "#LETTER"),
"NAME",
"ENABLED",
"REFONLY",
"NROLES",
"MASTER",
"DESCRIPTION");
#undef KIND_HEADER_COMMON_FMT
}
extern void printKind (const kindDefinition* const kind, bool allKindFields, bool indent,
bool tabSeparated)
{
#define KIND_FMT MAKE_KIND_FMT("", c, d)
if (allKindFields)
{
printf ((tabSeparated
?"%s%c\t%s\t%s\t%s\t%d\t%s\t%s\n"
:"%s" KIND_FMT),
(indent? (tabSeparated? "\t": " "): ""),
kind->letter,
kind->name != NULL ? kind->name : "",
kind->enabled ? "on" : "off",
kind->referenceOnly ? "TRUE" : "FALSE",
kind->nRoles,
(kind->master
|| kind->slave ) ? getLanguageName (kind->syncWith): "",
kind->description != NULL ? kind->description : "");
}
else if (!kind->referenceOnly)
{
printf ("%s%c %s%s\n", indent ? " " : "", kind->letter,
kind->description != NULL ? kind->description :
(kind->name != NULL ? kind->name : ""),
kind->enabled ? "" : " [off]");
}
#undef KIND_FMT
}
const char *scopeSeparatorFor (langType lang, int kindIndex, int parentKindIndex)
{
kindDefinition *kind = getLanguageKind (lang, kindIndex);
scopeSeparator *table = kind->separators;
/* If no table is given, use the default generic separator ".".
The exception is if a root separator is looked up. In this case,
return NULL to notify there is no root separator to the caller. */
if (table == NULL)
{
if (parentKindIndex == KIND_GHOST_INDEX)
return NULL;
else
return ".";
}
while (table - kind->separators < kind->separatorCount)
{
/* KIND_WILDCARD cannot be used as a key for finding
a root separator.*/
if ( (table->parentKindIndex == KIND_WILDCARD_INDEX
&& parentKindIndex != KIND_GHOST_INDEX)
|| table->parentKindIndex == parentKindIndex)
return table->separator;
table++;
}
if (parentKindIndex == KIND_GHOST_INDEX)
return NULL;
else
return ".";
}
extern void enableKind (kindDefinition *kind, bool enable)
@ -80,618 +155,3 @@ extern void enableKind (kindDefinition *kind, bool enable)
slave->enabled = enable;
}
}
extern void enableRole (roleDefinition *role, bool enable)
{
role->enabled = enable;
}
static void initRoleObject (roleObject *robj, roleDefinition *rdef, freeRoleDefFunc freefunc, int roleId)
{
#ifdef DEBUG
size_t len = strlen (rdef->name);
for (int i = 0; i < len; i++)
Assert (isalnum (rdef->name [i]));
#endif
robj->def = rdef;
robj->free = freefunc;
robj->def->id = roleId;
}
static struct roleControlBlock* allocRoleControlBlock (kindObject *kind)
{
unsigned int j;
struct roleControlBlock* rcb;
rcb = xMalloc(1, struct roleControlBlock);
rcb->count = kind->def->nRoles;
rcb->owner = kind->def->id;
rcb->role = xMalloc(rcb->count, roleObject);
for (j = 0; j < rcb->count; j++)
initRoleObject (rcb->role + j, kind->def->roles + j, NULL, j);
return rcb;
}
extern struct kindControlBlock* allocKindControlBlock (parserDefinition *parser)
{
unsigned int i;
struct kindControlBlock *kcb;
kcb = xMalloc (1, struct kindControlBlock);
kcb->kind = xMalloc (parser->kindCount, kindObject);
kcb->count = parser->kindCount;
kcb->owner = parser->id;
kcb->defaultScopeSeparator.parentKindIndex = KIND_WILDCARD_INDEX;
kcb->defaultScopeSeparator.separator = NULL;
if (parser->defaultScopeSeparator)
kcb->defaultScopeSeparator.separator = eStrdup (parser->defaultScopeSeparator);
kcb->defaultRootScopeSeparator.parentKindIndex = KIND_GHOST_INDEX;
kcb->defaultRootScopeSeparator.separator = NULL;
if (parser->defaultRootScopeSeparator)
kcb->defaultRootScopeSeparator.separator = eStrdup (parser->defaultRootScopeSeparator);
for (i = 0; i < parser->kindCount; ++i)
{
kindObject *kind = kcb->kind + i;
kind->def = parser->kindTable + i;
kind->free = NULL;
kind->def->id = i;
kind->rcb = allocRoleControlBlock (kind);
kind->dynamicSeparators = NULL;
}
return kcb;
}
static void freeRoleControlBlock (struct roleControlBlock *rcb)
{
unsigned int i;
for (i = 0; i < rcb->count; ++i)
{
if (rcb->role[i].free)
rcb->role [i].free (rcb->role [i].def);
}
eFreeNoNullCheck (rcb->role);
eFree (rcb);
}
extern void freeKindControlBlock (struct kindControlBlock* kcb)
{
unsigned int i;
for (i = 0; i < kcb->count; ++i)
{
if (kcb->kind [i].free)
kcb->kind [i].free (kcb->kind [i].def);
freeRoleControlBlock (kcb->kind [i].rcb);
if (kcb->kind [i].dynamicSeparators)
ptrArrayDelete(kcb->kind [i].dynamicSeparators);
}
if (kcb->defaultRootScopeSeparator.separator)
eFree((char *)kcb->defaultRootScopeSeparator.separator);
if (kcb->defaultScopeSeparator.separator)
eFree((char *)kcb->defaultScopeSeparator.separator);
if (kcb->kind)
eFree (kcb->kind);
eFree (kcb);
}
extern int defineKind (struct kindControlBlock* kcb, kindDefinition *def,
freeKindDefFunc freeKindDef)
{
def->id = kcb->count++;
kcb->kind = xRealloc (kcb->kind, kcb->count, kindObject);
kcb->kind [def->id].def = def;
kcb->kind [def->id].free = freeKindDef;
kcb->kind [def->id].rcb = allocRoleControlBlock(kcb->kind + def->id);
kcb->kind [def->id].dynamicSeparators = NULL;
verbose ("Add kind[%d] \"%c,%s,%s\" to %s\n", def->id,
def->letter, def->name, def->description,
getLanguageName (kcb->owner));
return def->id;
}
extern int defineRole (struct kindControlBlock* kcb, int kindIndex,
roleDefinition *def, freeRoleDefFunc freeRoleDef)
{
struct roleControlBlock *rcb = kcb->kind[kindIndex].rcb;
int roleIndex = rcb->count++;
if (roleIndex == ROLE_MAX_COUNT)
{
rcb->count--;
error (FATAL, "Too many role definition for kind \"%s\" of language \"%s\" (> %d)",
kcb->kind[kindIndex].def->name,
getLanguageName (kcb->owner),
(int)(ROLE_MAX_COUNT - 1));
}
rcb->role = xRealloc (rcb->role, rcb->count, roleObject);
initRoleObject (rcb->role + roleIndex, def, freeRoleDef, roleIndex);
return roleIndex;
}
extern bool isRoleEnabled (struct kindControlBlock* kcb, int kindIndex, int roleIndex)
{
roleDefinition *rdef = getRole (kcb, kindIndex, roleIndex);
return rdef->enabled;
}
extern unsigned int countKinds (struct kindControlBlock* kcb)
{
return kcb->count;
}
extern unsigned int countRoles (struct kindControlBlock* kcb, int kindIndex)
{
return kcb->kind [kindIndex].rcb->count;
}
extern kindDefinition *getKind (struct kindControlBlock* kcb, int kindIndex)
{
return kcb->kind [kindIndex].def;
}
extern kindDefinition *getKindForLetter (struct kindControlBlock* kcb, char letter)
{
unsigned int i;
kindDefinition * kdef;
for (i = 0; i < countKinds (kcb); ++i)
{
kdef = getKind (kcb, i);
if (kdef->letter == letter)
return kdef;
}
return NULL;
}
extern kindDefinition *getKindForName (struct kindControlBlock* kcb, const char* name)
{
unsigned int i;
kindDefinition * kdef;
for (i = 0; i < countKinds (kcb); ++i)
{
kdef = getKind (kcb, i);
Assert(kdef);
if (kdef->name && (strcmp(kdef->name, name) == 0))
return kdef;
}
return NULL;
}
extern int getKindIndexForLetter (struct kindControlBlock* kcb, char letter)
{
unsigned int i;
kindDefinition * kdef;
for (i = 0; i < countKinds (kcb); ++i)
{
kdef = getKind (kcb, i);
if (kdef->letter == letter)
return (unsigned int)i;
}
return KIND_GHOST_INDEX;
}
extern int getKindIndexForName (struct kindControlBlock* kcb, const char* name)
{
unsigned int i;
kindDefinition * kdef;
for (i = 0; i < countKinds (kcb); ++i)
{
kdef = getKind (kcb, i);
Assert(kdef);
if (kdef->name && (strcmp(kdef->name, name) == 0))
return (int)i;
}
return KIND_GHOST_INDEX;
}
extern roleDefinition* getRole(struct kindControlBlock* kcb, int kindIndex, int roleIndex)
{
struct roleControlBlock *rcb = kcb->kind[kindIndex].rcb;
return rcb->role [roleIndex].def;
}
extern roleDefinition* getRoleForName(struct kindControlBlock* kcb,
int kindIndex, const char* name)
{
unsigned int i;
roleDefinition *rdef;
for (i = 0; i < countRoles (kcb, kindIndex); ++i)
{
rdef = getRole(kcb, kindIndex, i);
Assert(rdef);
if (rdef->name && (strcmp(rdef->name, name) == 0))
return rdef;
}
return NULL;
}
static void linkKinds (langType master, kindDefinition *masterKind, kindDefinition *slaveKind)
{
kindDefinition *tail;
slaveKind->master = masterKind;
tail = slaveKind;
while (tail->slave)
{
tail->enabled = masterKind->enabled;
tail = tail->slave;
}
tail->slave = masterKind->slave;
masterKind->slave = slaveKind;
masterKind->syncWith = master;
slaveKind->syncWith = master;
}
extern void linkKindDependency (struct kindControlBlock *masterKCB,
struct kindControlBlock *slaveKCB)
{
unsigned int k_slave, k_master;
kindDefinition *kind_slave, *kind_master;
for (k_slave = 0; k_slave < countKinds (slaveKCB); k_slave++)
{
kind_slave = getKind(slaveKCB, k_slave);
if (kind_slave->syncWith == LANG_AUTO)
{
for (k_master = 0; k_master < countKinds (masterKCB); k_master++)
{
kind_master = getKind(masterKCB, k_master);
if ((kind_slave->letter == kind_master->letter)
&& (strcmp (kind_slave->name, kind_master->name) == 0))
{
linkKinds (masterKCB->owner, kind_master, kind_slave);
break;
}
}
}
}
}
static void scopeSeparatorDelete (void *data)
{
scopeSeparator *sep = data;
eFree ((void *)sep->separator);
sep->separator = NULL;
eFree (sep);
}
extern int defineScopeSeparator(struct kindControlBlock* kcb,
int kindIndex,
int parentKindIndex, const char *separator)
{
if (kindIndex == KIND_WILDCARD_INDEX)
{
if (parentKindIndex == KIND_WILDCARD_INDEX)
{
if (kcb->defaultScopeSeparator.separator)
eFree ((char *)kcb->defaultScopeSeparator.separator);
verbose ("Installing default separator for %s: %s\n",
getLanguageName (kcb->owner), separator);
kcb->defaultScopeSeparator.separator = eStrdup (separator);
}
else if (parentKindIndex == KIND_GHOST_INDEX)
{
if (kcb->defaultRootScopeSeparator.separator)
eFree ((char *)kcb->defaultRootScopeSeparator.separator);
verbose ("Installing default root separator for %s: %s\n",
getLanguageName (kcb->owner),
separator);
kcb->defaultRootScopeSeparator.separator = eStrdup (separator);
}
else
error (FATAL,
"Don't specify a real kind as parent when defining a default scope separator: %d",
parentKindIndex);
return 0;
}
Assert (kcb->count > kindIndex);
kindObject *kind = kcb->kind + kindIndex;
if (!kind->dynamicSeparators)
kind->dynamicSeparators = ptrArrayNew (scopeSeparatorDelete);
scopeSeparator *sep = xMalloc (1, scopeSeparator);
sep->parentKindIndex = parentKindIndex;
sep->separator = eStrdup(separator);
ptrArrayAdd (kind->dynamicSeparators, sep);
return 0;
}
static scopeSeparator *getScopeSeparatorDynamic(kindObject *kobj, int parentKindIndex)
{
scopeSeparator *sep;
if (kobj->dynamicSeparators)
{
for (unsigned int i = ptrArrayCount (kobj->dynamicSeparators); 0 < i ; i--)
{
sep = ptrArrayItem (kobj->dynamicSeparators, i - 1);
if (sep->parentKindIndex == parentKindIndex)
return sep;
}
}
return NULL;
}
static const scopeSeparator *getScopeSeparatorStatic(kindDefinition *kdef, int parentKindIndex)
{
scopeSeparator *table = kdef->separators;
if (table == NULL)
return NULL;
while (table - kdef->separators < (int)kdef->separatorCount)
{
if (table->parentKindIndex == parentKindIndex)
return table;
/* If a caller wants a root separator for kdef,
we should not return a wildcard table. */
if (parentKindIndex != KIND_GHOST_INDEX
&& table->parentKindIndex == KIND_WILDCARD_INDEX)
return table;
table++;
}
return NULL;
}
extern const scopeSeparator *getScopeSeparator(struct kindControlBlock* kcb,
int kindIndex, int parentKindIndex)
{
Assert (kindIndex != KIND_GHOST_INDEX);
Assert (kindIndex != KIND_FILE_INDEX);
Assert (kindIndex != KIND_WILDCARD_INDEX);
Assert (parentKindIndex != KIND_WILDCARD_INDEX);
Assert (parentKindIndex != KIND_FILE_INDEX);
/* A caller specifies KIND_GHOST_INDEX for parentKindIndex when it
* wants root separator. */
Assert (kcb->count > kindIndex);
kindObject *kobj = kcb->kind + kindIndex;
const scopeSeparator *sep;
sep = getScopeSeparatorDynamic (kobj, parentKindIndex);
if (sep)
return sep;
sep = getScopeSeparatorStatic (kobj->def, parentKindIndex);
if (sep)
return sep;
/* Cannot find a suitable sep definition.
* Use default one. */
if (parentKindIndex == KIND_GHOST_INDEX)
{
if (kcb->defaultRootScopeSeparator.separator)
return &kcb->defaultRootScopeSeparator;
return NULL;
}
else
{
if (kcb->defaultScopeSeparator.separator)
return &kcb->defaultScopeSeparator;
static scopeSeparator defaultSeparator = {
.separator = ".",
.parentKindIndex = KIND_WILDCARD_INDEX,
};
return &defaultSeparator;
}
}
#ifdef DEBUG
extern bool doesParserUseKind (struct kindControlBlock* kcb, char letter)
{
unsigned int k;
kindDefinition *kdef;
for (k = 0; k < countKinds (kcb); k++)
{
kdef = getKind(kcb, k);
if (kdef->letter == letter)
return true;
}
return false;
}
#endif
extern struct colprintTable * kindColprintTableNew (void)
{
return colprintTableNew ("L:LANGUAGE", "L:LETTER", "L:NAME", "L:ENABLED",
"L:REFONLY", "L:NROLES", "L:MASTER",
"L:DESCRIPTION",
NULL);
}
static void kindColprintFillLine (struct colprintLine *line,
const char *langName,
kindDefinition *kdef)
{
langType lang = getNamedLanguage (langName, 0);
unsigned int count = countLanguageRoles(lang, kdef->id);
colprintLineAppendColumnCString (line, langName);
colprintLineAppendColumnChar (line, kdef->letter);
colprintLineAppendColumnCString (line, kdef->name
? kdef->name
: "ThisShouldNotBePrintedKindNameMustBeGiven");
colprintLineAppendColumnBool (line, kdef->enabled);
colprintLineAppendColumnBool (line, kdef->referenceOnly);
colprintLineAppendColumnInt (line, count);
colprintLineAppendColumnCString (line, (kdef->master
|| kdef->slave ) ?
getLanguageName (kdef->syncWith): RSV_NONE);
colprintLineAppendColumnCString (line, kdef->description? kdef->description: "NO DESCRIPTION GIVEN");
}
extern void kindColprintAddLanguageLines (struct colprintTable *table,
struct kindControlBlock* kcb)
{
const char *lang = getLanguageName (kcb->owner);
for (unsigned int i = 0; i < countKinds (kcb); i++)
{
kindDefinition *kdef = getKind (kcb, i);
struct colprintLine *line = colprintTableGetNewLine(table);
kindColprintFillLine (line, lang, kdef);
}
}
static int kindColprintCompareLines (struct colprintLine *a , struct colprintLine *b)
{
const char *a_parser = colprintLineGetColumn (a, 0);
const char *b_parser = colprintLineGetColumn (b, 0);
const char *a_letter;
const char *b_letter;
int r;
r = strcmp (a_parser, b_parser);
if (r != 0)
return r;
a_letter = colprintLineGetColumn (a, 1);
b_letter = colprintLineGetColumn (b, 1);
r = strcmp (a_letter, b_letter);
if (r != 0)
return r;
return 0;
}
extern void kindColprintTablePrint (struct colprintTable *table, bool noparser,
bool withListHeader, bool machinable, FILE *fp)
{
colprintTableSort (table, kindColprintCompareLines);
colprintTablePrint (table, noparser? 1: 0, withListHeader, machinable, fp);
}
extern struct colprintTable * roleColprintTableNew (void)
{
return colprintTableNew ("L:LANGUAGE", "L:KIND(L/N)", "L:NAME",
"L:ENABLED", "L:DESCRIPTION", NULL);
}
extern void roleColprintAddRoles (struct colprintTable *table, struct kindControlBlock *kcb,
const char *kindspecs)
{
const char* lang;
vString *kind_l_and_n;
lang = getLanguageName (kcb->owner);
kind_l_and_n = vStringNew ();
for (const char *c = kindspecs; *c != '\0'; c++)
{
const char *kname = NULL;
size_t kname_len;
if (*c == '{')
{
const char *start = c + 1;
const char *end = strchr(c, '}');
if (!end)
error (FATAL, "'{' is not closed with '}' in \"%s\"", c);
if (start == end)
error (FATAL, "empty kind name is given in \"%s\"", c);
kname = start;
kname_len = end - start;
c = end;
}
for (unsigned int i = 0; i < countKinds (kcb); i++)
{
const kindDefinition *k = getKind (kcb, i);
if ((kname
&& strlen (k->name) == kname_len
&& strncmp (k->name, kname, kname_len) == 0)
|| (!kname && *c == k->letter)
|| (!kname && *c == KIND_WILDCARD_LETTER))
{
unsigned int nRoles = countRoles(kcb, i);
for (unsigned int j = 0; j < nRoles; j++)
{
const roleDefinition *r = getRole (kcb, i, j);
struct colprintLine *line = colprintTableGetNewLine(table);
colprintLineAppendColumnCString (line, lang);
vStringPut (kind_l_and_n, k->letter);
vStringPut (kind_l_and_n, '/');
vStringCatS (kind_l_and_n, k->name);
colprintLineAppendColumnVString (line, kind_l_and_n);
vStringClear (kind_l_and_n);
colprintLineAppendColumnCString (line, r->name);
colprintLineAppendColumnCString (line,
r->enabled ? "on" : "off");
colprintLineAppendColumnCString (line, r->description);
}
if (! (!kname && *c == KIND_WILDCARD_LETTER))
break;
}
}
}
vStringDelete (kind_l_and_n);
#if 0
if ((i == countKinds (kcb)) && (*c != KIND_WILDCARD) && (!allowMissingKind))
error (FATAL, "No such letter kind in %s: %c\n", lang->name, *c);
#endif
}
static int roleColprintCompareLines(struct colprintLine *a, struct colprintLine *b)
{
int r;
const char *a_parser, *b_parser;
a_parser = colprintLineGetColumn (a, 0);
b_parser = colprintLineGetColumn (b, 0);
r = strcmp(a_parser, b_parser);
if (r != 0)
return r;
const char *a_kindln, *b_kindln;
a_kindln = colprintLineGetColumn (a, 1);
b_kindln = colprintLineGetColumn (b, 1);
r = strcmp(a_kindln, b_kindln);
if (r != 0)
return r;
const char *a_role, *b_role;
a_role = colprintLineGetColumn (a, 2);
b_role = colprintLineGetColumn (b, 2);
return strcmp(a_role, b_role);
}
extern void roleColprintTablePrint (struct colprintTable *table, bool noparser,
bool withListHeader, bool machinable, FILE *fp)
{
colprintTableSort (table, roleColprintCompareLines);
colprintTablePrint (table, noparser? 1: 0, withListHeader, machinable, fp);
}

View File

@ -8,60 +8,45 @@
#ifndef CTAGS_MAIN_KIND_H
#define CTAGS_MAIN_KIND_H
/*
* INCLUDE FILES
*/
#include "general.h"
#include "types.h"
#include "routines.h"
#include "routines.h" /* for STRINGIFY */
#include "vstring.h"
/*
* DATA DECLARATIONS
*/
struct sRoleDefinition {
typedef struct sRoleDefinition {
bool enabled;
char* name; /* role name */
char* description; /* displayed in --help output */
const char* name; /* role name */
const char* description; /* displayed in --help output */
} roleDefinition;
int id;
};
extern void printRole (const roleDefinition* const role); /* for --help */
extern const char *renderRole (const roleDefinition* const role, vString* b);
/*
* Predefined kinds
*/
#define KIND_REGEX_DEFAULT_LETTER 'r'
#define KIND_REGEX_DEFAULT_NAME "regex"
#define KIND_REGEX_DEFAULT 'r'
#define KIND_REGEX_DEFAULT_LONG "regex"
/* We treat ' ' as a ghost kind.
It will never be listed up in --list-kinds. */
#define KIND_NULL_LETTER '\0'
#define KIND_NULL '\0'
/* GHOST kind can be used for a value for
* initializing a variable holding a kind index,
* or filling a struct member holding a kind index.
*
* Typical case is filling a scope related struct
* member with GHOST to represent root name scope.
*
* input.c:
*
* int main (void) { return 0; }
*
* Consider that tagging "main" in above input.
* You may wonder what kind of value
* should be used to fill tag.extensionFields.scopeKindIndex.
* KIND_GHOST_INDEX can be used for the purpose.
*/
#define KIND_GHOST_INDEX -1
#define KIND_GHOST_LETTER ' '
#define KIND_GHOST_NAME "ghost"
#define KIND_GHOST ' '
#define KIND_GHOST_LONG "ghost"
#define KIND_FILE_INDEX -2
#define KIND_FILE_DEFAULT_LETTER 'F'
#define KIND_FILE_DEFAULT_NAME "file"
#define KIND_FILE_DEFAULT 'F'
#define KIND_FILE_DEFAULT_LONG "file"
#define KIND_FILE_ALT '!'
#define KIND_GENERIC_REFERENCE '@'
#define KIND_GENERIC_REFERENCE_DEFAULT_LONG "reference"
#define KIND_WILDCARD_INDEX -3
#define KIND_WILDCARD_LETTER '*'
#define KIND_WILDCARD '*'
typedef struct sScopeSeparator {
int parentKindIndex;
@ -71,21 +56,18 @@ typedef struct sScopeSeparator {
struct sKindDefinition {
bool enabled; /* are tags for kind enabled? */
char letter; /* kind letter */
char* name; /* kind name */
char* description; /* displayed in --help output */
const char* name; /* kind name */
const char* description; /* displayed in --help output */
bool referenceOnly;
int nRoles; /* The number of role elements. */
roleDefinition *roles;
scopeSeparator *separators;
unsigned int separatorCount;
int id;
/* TODO:Following fields should be moved to kindObject. */
/* Usage of `syncWith' field is a bit tricky.
If `LANG_AUTO' is specified to `syncWith' field of a kind
(target kind), the main part of ctags updates the field with
(target kind), the main part of ctags updtes the field with
the id of a parser (master parser) when initializing
parsers. It also updates `slave' and `master' fields.
@ -99,10 +81,17 @@ struct sKindDefinition {
#define ATTACH_ROLES(RS) .nRoles = ARRAY_SIZE(RS), .roles = RS
#define ATTACH_SEPARATORS(S) .separators = S, .separatorCount = ARRAY_SIZE(S)
/*
* FUNCTION PROTOTYPES
*/
/* The value of `tabSeparated' is meaningfull only when `allKindFields' is true. */
extern void printKind (const kindDefinition* const kind, bool allKindFields, bool indent,
bool tabSeparated);
extern void printKindListHeader (bool indent, bool tabSeparated);
extern const char *scopeSeparatorFor (langType lang, int kindIndex, int parentKindIndex);
extern void enableKind (kindDefinition *kind, bool enable);
#define PR_KIND_STR(X) PR_KIND_WIDTH_##X
#define PR_KIND_FMT(X,T) "%-" STRINGIFY(PR_KIND_STR(X)) STRINGIFY(T)
#define PR_KIND_WIDTH_LANG 15
#endif /* CTAGS_MAIN_KIND_H */

View File

@ -1,83 +0,0 @@
/*
* Copyright (c) 1998-2003, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#ifndef CTAGS_MAIN_KIND_PRIVATE_H
#define CTAGS_MAIN_KIND_PRIVATE_H
/*
* INCLUDE FILES
*/
#include "general.h"
#include "kind.h"
#include "vstring.h"
/*
* DATA DECLARATIONS
*/
struct kindControlBlock;
typedef void (* freeKindDefFunc) (kindDefinition *);
typedef void (* freeRoleDefFunc) (roleDefinition *);
/*
* FUNCTION PROTOTYPES
*/
extern void enableKind (kindDefinition *kind, bool enable);
extern void enableRole (roleDefinition *role, bool enable);
extern const char *renderRole (const roleDefinition* const def, vString* b);
extern struct kindControlBlock* allocKindControlBlock (parserDefinition *parser);
extern void freeKindControlBlock (struct kindControlBlock* kcb);
extern int defineKind (struct kindControlBlock* kcb, kindDefinition *def,
freeKindDefFunc freeKindDef);
extern int defineRole (struct kindControlBlock* kcb, int kindIndex,
roleDefinition *def, freeRoleDefFunc freeRoleDef);
extern bool isRoleEnabled (struct kindControlBlock* kcb, int kindIndex, int roleIndex);
extern unsigned int countKinds (struct kindControlBlock* kcb);
extern unsigned int countRoles (struct kindControlBlock* kcb, int kindIndex);
extern kindDefinition *getKind (struct kindControlBlock* kcb, int kindIndex);
extern kindDefinition *getKindForLetter (struct kindControlBlock* kcb, char letter);
extern kindDefinition *getKindForName (struct kindControlBlock* kcb, const char* name);
extern int getKindIndexForLetter (struct kindControlBlock* kcb, char letter);
extern int getKindIndexForName (struct kindControlBlock* kcb, const char* name);
extern roleDefinition* getRole(struct kindControlBlock* kcb, int kindIndex, int roleIndex);
extern roleDefinition* getRoleForName(struct kindControlBlock* kcb, int kindIndex, const char* name);
extern void linkKindDependency (struct kindControlBlock *masterKCB,
struct kindControlBlock *slaveKCB);
extern int defineScopeSeparator(struct kindControlBlock* kcb,
int kindIndex,
int parentKindIndex, const char *separator);
extern const scopeSeparator *getScopeSeparator(struct kindControlBlock* kcb, int kindIndex, int parentKindIndex);
/* for the obsolete --list-kinds option */
extern void printKind (const kindDefinition* const kind, bool indent);
/* for --list-kinds-full option. LANGUAGE must be initialized. */
extern struct colprintTable * kindColprintTableNew (void);
extern void kindColprintAddLanguageLines (struct colprintTable *table,
struct kindControlBlock* kcb);
extern void kindColprintTablePrint (struct colprintTable *table, bool noparser,
bool withListHeader, bool machinable, FILE *fp);
extern struct colprintTable * roleColprintTableNew (void);
extern void roleColprintAddRoles (struct colprintTable *table,
struct kindControlBlock* kcb,
const char *kindspecs);
extern void roleColprintTablePrint (struct colprintTable *table, bool noparser,
bool withListHeader, bool machinable, FILE *fp);
#ifdef DEBUG
extern bool doesParserUseKind (struct kindControlBlock* kcb, char letter);
#endif
#endif /* CTAGS_MAIN_KIND_PRIVATE_H */

View File

@ -17,9 +17,9 @@
#include "debug.h"
#include "entry.h"
#include "geany_lcpp.h"
#include "lcpp.h"
#include "kind.h"
#include "options_p.h"
#include "options.h"
#include "read.h"
#include "vstring.h"
#include "parse.h"
@ -106,17 +106,17 @@ static cppState Cpp = {
* FUNCTION DEFINITIONS
*/
extern bool lcppIsBraceFormat (void)
extern bool cppIsBraceFormat (void)
{
return BraceFormat;
}
extern unsigned int lcppGetDirectiveNestLevel (void)
extern unsigned int cppGetDirectiveNestLevel (void)
{
return Cpp.directive.nestLevel;
}
extern void lcppInit (const bool state, const bool hasAtLiteralStrings,
extern void cppInit (const bool state, const bool hasAtLiteralStrings,
const bool hasCxxRawLiteralStrings,
int defineMacroKindIndex)
{
@ -141,7 +141,7 @@ extern void lcppInit (const bool state, const bool hasAtLiteralStrings,
Cpp.directive.name = vStringNewOrClear (Cpp.directive.name);
}
extern void lcppTerminate (void)
extern void cppTerminate (void)
{
if (Cpp.directive.name != NULL)
{
@ -150,12 +150,12 @@ extern void lcppTerminate (void)
}
}
extern void lcppBeginStatement (void)
extern void cppBeginStatement (void)
{
Cpp.resolveRequired = true;
}
extern void lcppEndStatement (void)
extern void cppEndStatement (void)
{
Cpp.resolveRequired = false;
}
@ -170,7 +170,7 @@ extern void lcppEndStatement (void)
/* This puts a character back into the input queue for the input File.
* Up to two characters may be ungotten.
*/
extern void lcppUngetc (const int c)
extern void cppUngetc (const int c)
{
Assert (Cpp.ungetch2 == '\0');
Cpp.ungetch2 = Cpp.ungetch;
@ -228,7 +228,7 @@ static void readIdentifier (int c, vString *const name)
{
vStringPut (name, c);
c = getcAndCollect ();
} while (c != EOF && lcppIsident (c));
} while (c != EOF && cppIsident (c));
ungetcAndCollect (c);
}
@ -305,7 +305,8 @@ static bool pushConditional (const bool firstBranchChosen)
ifdef->singleBranch = Cpp.resolveRequired;
ifdef->branchChosen = firstBranchChosen;
ifdef->ignoring = (bool) (ignoreAllBranches || (
! firstBranchChosen && ! BraceFormat));
! firstBranchChosen && ! BraceFormat &&
(ifdef->singleBranch || !Option.if0)));
ignoreBranch = ifdef->ignoring;
}
return ignoreBranch;
@ -342,7 +343,7 @@ static int makeDefineTag (const char *const name, bool parameterized, bool undef
e.isFileScope = isFileScope;
e.truncateLineAfterTag = true;
if (parameterized)
e.extensionFields.signature = lcppGetSignature ();
e.extensionFields.signature = cppGetSignature ();
makeTagEntry (&e);
if (parameterized)
eFree((char *) e.extensionFields.signature);
@ -354,7 +355,7 @@ static int directiveDefine (const int c, bool undef)
{
int r = CORK_NIL;
if (lcppIsident1 (c))
if (cppIsident1 (c))
{
bool parameterized;
int nc;
@ -364,7 +365,7 @@ static int directiveDefine (const int c, bool undef)
parameterized = (nc == '(');
if (parameterized)
{
lcppStartCollectingSignature ();
cppStartCollectingSignature ();
while (nc != EOF)
{
int lastC = nc;
@ -372,7 +373,7 @@ static int directiveDefine (const int c, bool undef)
if (nc == '\n' && lastC != '\\')
break;
}
lcppStopCollectingSignature ();
cppStopCollectingSignature ();
}
ungetcAndCollect (nc);
if (! isIgnore ())
@ -396,7 +397,7 @@ static void directiveUndef (const int c)
static void directivePragma (int c)
{
if (lcppIsident1 (c))
if (cppIsident1 (c))
{
readIdentifier (c, Cpp.directive.name);
if (stringMatch (vStringValue (Cpp.directive.name), "weak"))
@ -406,7 +407,7 @@ static void directivePragma (int c)
{
c = getcAndCollect ();
} while (c == SPACE);
if (lcppIsident1 (c))
if (cppIsident1 (c))
{
readIdentifier (c, Cpp.directive.name);
makeDefineTag (vStringValue (Cpp.directive.name), NULL, false);
@ -507,7 +508,7 @@ static Comment isComment (void)
/* Skips over a C style comment. According to ANSI specification a comment
* is treated as white space, so we perform this substitution.
*/
int lcppSkipOverCComment (void)
int cppSkipOverCComment (void)
{
int c = getcAndCollect ();
@ -669,7 +670,7 @@ static int skipToEndOfChar (void)
* quoted strings. In short, strip anything which places a burden upon
* the tokenizer.
*/
extern int lcppGetc (void)
extern int cppGetc (void)
{
bool directive = false;
bool ignore = false;
@ -735,7 +736,7 @@ process:
const Comment comment = isComment ();
if (comment == COMMENT_C)
c = lcppSkipOverCComment ();
c = cppSkipOverCComment ();
else if (comment == COMMENT_CPLUS)
{
c = skipOverCplusComment ();
@ -859,9 +860,9 @@ process:
int prev2 = getNthPrevCFromInputFile (2, '\0');
int prev3 = getNthPrevCFromInputFile (3, '\0');
if (! lcppIsident (prev) ||
(! lcppIsident (prev2) && (prev == 'L' || prev == 'u' || prev == 'U')) ||
(! lcppIsident (prev3) && (prev2 == 'u' && prev == '8')))
if (! cppIsident (prev) ||
(! cppIsident (prev2) && (prev == 'L' || prev == 'u' || prev == 'U')) ||
(! cppIsident (prev3) && (prev2 == 'u' && prev == '8')))
{
int next = getcAndCollect ();
if (next != DOUBLE_QUOTE)
@ -977,7 +978,7 @@ static void stripCodeBuffer(char *buf)
return;
}
extern char *lcppGetSignature(void)
extern char *cppGetSignature(void)
{
char *start, *end;
int level;
@ -1000,87 +1001,20 @@ extern char *lcppGetSignature(void)
return start;
}
extern void lcppStartCollectingSignature (void)
extern void cppStartCollectingSignature (void)
{
signature = vStringNewOrClear (signature);
vStringPut (signature, '(');
collectingSignature = true;
}
extern void lcppStopCollectingSignature (void)
extern void cppStopCollectingSignature (void)
{
collectingSignature = false;
}
extern void lcppClearSignature (void)
extern void cppClearSignature (void)
{
signature = vStringNewOrClear (signature);
collectingSignature = false;
}
/* tags_ignore is a NULL-terminated array of strings, read from ~/.config/geany/ignore.tags.
* This file contains a space or newline separated list of symbols which should be ignored
* by the C/C++ parser, see -I command line option of ctags for details. */
char **c_tags_ignore = NULL;
/* Determines whether or not "name" should be ignored, per the ignore list.
*/
extern bool cppIsIgnoreToken (const char *const name,
bool *const pIgnoreParens,
const char **const replacement)
{
bool result = false;
if (c_tags_ignore != NULL)
{
const size_t nameLen = strlen (name);
unsigned int i;
unsigned int len = 0;
vString *token = vStringNew();
while (c_tags_ignore[len])
len++;
if (pIgnoreParens != NULL)
*pIgnoreParens = false;
for (i = 0 ; i < len ; ++i)
{
size_t tokenLen;
vStringCopyS (token, c_tags_ignore[i]);
tokenLen = vStringLength (token);
if (tokenLen >= 2 && vStringChar (token, tokenLen - 1) == '*' &&
strncmp (vStringValue (token), name, tokenLen - 1) == 0)
{
result = true;
break;
}
if (strncmp (vStringValue (token), name, nameLen) == 0)
{
if (nameLen == tokenLen)
{
result = true;
break;
}
else if (tokenLen == nameLen + 1 &&
vStringChar (token, tokenLen - 1) == '+')
{
result = true;
if (pIgnoreParens != NULL)
*pIgnoreParens = true;
break;
}
else if (vStringChar (token, nameLen) == '=')
{
if (replacement != NULL)
*replacement = vStringValue (token) + nameLen + 1;
break;
}
}
}
vStringDelete (token);
}
return result;
}

View File

@ -21,15 +21,15 @@
/* Is the character valid as a character of a C identifier?
* VMS allows '$' in identifiers.
*/
#define lcppIsident(c) (isalnum(c) || (c) == '_' || (c) == '$')
#define cppIsident(c) (isalnum(c) || (c) == '_' || (c) == '$')
/* Is the character valid as the first character of a C identifier?
* C++ allows '~' in destructors.
* VMS allows '$' in identifiers.
* Vala allows '@' in identifiers.
*/
#define lcppIsident1(c) ( ((c >= 0) && (c < 0x80) && isalpha(c)) \
|| (c) == '_' || (c) == '~' || (c) == '$' || (c) == '@')
#define cppIsident1(c) ( ((c >= 0) && (c < 0x80) && isalpha(c)) \
|| (c) == '_' || (c) == '~' || (c) == '$' || (c) == '@')
/* NOTE about isident1 profitability
Doing the same as isascii before passing value to isalpha
@ -58,27 +58,23 @@
/*
* FUNCTION PROTOTYPES
*/
extern bool lcppIsBraceFormat (void);
extern unsigned int lcppGetDirectiveNestLevel (void);
extern bool cppIsBraceFormat (void);
extern unsigned int cppGetDirectiveNestLevel (void);
extern void lcppInit (const bool state,
extern void cppInit (const bool state,
const bool hasAtLiteralStrings,
const bool hasCxxRawLiteralStrings,
int defineMacroKindIndex);
extern void lcppTerminate (void);
extern void lcppBeginStatement (void);
extern void lcppEndStatement (void);
extern void lcppUngetc (const int c);
extern int lcppGetc (void);
extern int lcppSkipOverCComment (void);
extern void cppTerminate (void);
extern void cppBeginStatement (void);
extern void cppEndStatement (void);
extern void cppUngetc (const int c);
extern int cppGetc (void);
extern int cppSkipOverCComment (void);
extern char *lcppGetSignature (void);
extern void lcppStartCollectingSignature (void);
extern void lcppStopCollectingSignature (void);
extern void lcppClearSignature (void);
extern bool cppIsIgnoreToken (const char *const name,
bool *const pIgnoreParens,
const char **const replacement);
extern char *cppGetSignature (void);
extern void cppStartCollectingSignature (void);
extern void cppStopCollectingSignature (void);
extern void cppClearSignature (void);
#endif /* CTAGS_MAIN_GET_H */

View File

@ -1,127 +0,0 @@
/*
* Copyright (c) 2000-2003, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* This module contains functions for applying regular expression matching.
*
* The code for utilizing the Gnu regex package with regards to processing the
* regex option and checking for regex matches was adapted from routines in
* Gnu etags.
*/
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include <regex.h>
#include "lregex_p.h"
/*
* FUNCTION DECLARATIONS
*/
static int match (struct regexBackend *backend,
void *code, const char *input, size_t size,
regmatch_t pmatch[BACK_REFERENCE_COUNT]);
static regexCompiledCode compile (struct regexBackend *backend,
const char *const regexp,
int flags);
static void delete_code (void *code);
static void set_icase_flag (int *flags);
/*
* DATA DEFINITIONS
*/
static struct regexBackend defaultRegexBackend = {
.fdefs = NULL,
.fdef_count = 0,
.set_icase_flag = set_icase_flag,
.compile = compile,
.match = match,
.delete_code = delete_code,
};
/*
* FUNCTOIN DEFINITIONS
*/
extern void basic_regex_flag_short (char c, void* data)
{
struct flagDefsDescriptor *desc = data;
if (desc->backend)
error (FATAL, "regex backed is specified twice: %c", c);
desc->backend = &defaultRegexBackend;
desc->flags = (desc->regptype == REG_PARSER_MULTI_TABLE)? 0: REG_NEWLINE;
}
extern void basic_regex_flag_long (const char* const s, const char* const unused CTAGS_ATTR_UNUSED, void* data)
{
struct flagDefsDescriptor *desc = data;
if (desc->backend)
error (FATAL, "regex backed is specified twice: %s", s);
basic_regex_flag_short ('b', data);
}
extern void extend_regex_flag_short (char c, void* data)
{
struct flagDefsDescriptor *desc = data;
if (desc->backend)
error (FATAL, "regex backed is specified twice: %c", c);
desc->backend = &defaultRegexBackend;
desc->flags = REG_EXTENDED;
desc->flags |= (desc->regptype == REG_PARSER_MULTI_TABLE)? 0: REG_NEWLINE;
}
extern void extend_regex_flag_long (const char* const s, const char* const unused CTAGS_ATTR_UNUSED, void* data)
{
struct flagDefsDescriptor *desc = data;
if (desc->backend)
error (FATAL, "regex backed is specified twice: %s", s);
extend_regex_flag_short('e', data);
}
static void delete_code (void *code)
{
regex_t *regex_code = code;
regfree (regex_code);
eFree (regex_code);
}
static regexCompiledCode compile (struct regexBackend *backend,
const char *const regexp,
int flags)
{
regex_t *regex_code = xMalloc (1, regex_t);
int errcode = regcomp (regex_code, regexp, flags);
if (errcode != 0)
{
char errmsg[256];
regerror (errcode, regex_code, errmsg, 256);
error (WARNING, "regcomp: %s", errmsg);
regfree (regex_code);
eFree (regex_code);
return (regexCompiledCode) { .backend = NULL, .code = NULL };
}
return (regexCompiledCode) { .backend = &defaultRegexBackend, .code = regex_code };
}
static int match (struct regexBackend *backend,
void *code, const char *input, size_t size CTAGS_ATTR_UNUSED,
regmatch_t pmatch[BACK_REFERENCE_COUNT])
{
return regexec ((regex_t *)code, input, BACK_REFERENCE_COUNT, pmatch, 0);
}
static void set_icase_flag (int *flags)
{
*flags |= REG_ICASE;
}

View File

@ -1,140 +0,0 @@
/*
* Copyright (c) 2021, Red Hat, Inc.
* Copyright (c) 2021, Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* This module contains functions for applying regular expression matching.
*
* The code for utilizing the Gnu regex package with regards to processing the
* regex option and checking for regex matches was adapted from routines in
* Gnu etags.
*/
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#ifdef HAVE_PCRE2
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#endif
#include "lregex_p.h"
#include "trashbox.h"
#include <string.h>
/*
* FUNCTION DECLARATIONS
*/
static int match (struct regexBackend *backend,
void *code, const char *input, size_t size,
regmatch_t pmatch[BACK_REFERENCE_COUNT]);
static regexCompiledCode compile (struct regexBackend *backend,
const char *const regexp,
int flags);
static void delete_code (void *code);
static void set_icase_flag (int *flags);
/*
* DATA DEFINITIONS
*/
static struct regexBackend pcre2RegexBackend = {
.fdefs = NULL,
.fdef_count = 0,
.set_icase_flag = set_icase_flag,
.compile = compile,
.match = match,
.delete_code = delete_code,
};
/*
* FUNCTOIN DEFINITIONS
*/
extern void pcre2_regex_flag_short (char c, void* data)
{
struct flagDefsDescriptor *desc = data;
if (desc->backend)
error (FATAL, "regex backed is specified twice: %c", c);
desc->backend = &pcre2RegexBackend;
desc->flags = (desc->regptype == REG_PARSER_MULTI_TABLE)? PCRE2_DOTALL: PCRE2_MULTILINE;
}
extern void pcre2_regex_flag_long (const char* const s, const char* const unused CTAGS_ATTR_UNUSED, void* data)
{
struct flagDefsDescriptor *desc = data;
if (desc->backend)
error (FATAL, "regex backed is specified twice: %s", s);
pcre2_regex_flag_short ('p', data);
}
static void delete_code (void *code)
{
pcre2_code_free (code);
}
static regexCompiledCode compile (struct regexBackend *backend,
const char *const regexp,
int flags)
{
int errornumber;
PCRE2_SIZE erroroffset;
pcre2_code *regex_code = pcre2_compile((PCRE2_SPTR)regexp,
PCRE2_ZERO_TERMINATED,
(uint32_t) flags,
&errornumber,
&erroroffset,
NULL);
if (regex_code == NULL)
{
PCRE2_UCHAR buffer[256];
pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
error (WARNING, "PCRE2 compilation failed at offset %d: %s", (int)erroroffset,
buffer);
return (regexCompiledCode) { .backend = NULL, .code = NULL };
}
return (regexCompiledCode) { .backend = &pcre2RegexBackend, .code = regex_code };
}
static int match (struct regexBackend *backend,
void *code, const char *input, size_t size,
regmatch_t pmatch[BACK_REFERENCE_COUNT])
{
static pcre2_match_data *match_data;
if (match_data == NULL)
{
match_data = pcre2_match_data_create (BACK_REFERENCE_COUNT, NULL);
DEFAULT_TRASH_BOX (match_data, pcre2_match_data_free);
}
int rc = pcre2_match (code, (PCRE2_SPTR)input, size,
0, 0, match_data, NULL);
if (rc > 0)
{
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
if (ovector[0] <= ovector[1])
{
memset (pmatch, 0, sizeof(pmatch[0]) * BACK_REFERENCE_COUNT);
for (int i = 0; i < BACK_REFERENCE_COUNT; i++)
{
pmatch [i].rm_so = (i < rc)? ovector [2*i] : -1;
pmatch [i].rm_eo = (i < rc)? ovector [2*i+1]: -1;
}
return 0;
}
}
return 1;
}
static void set_icase_flag (int *flags)
{
*flags |= PCRE2_CASELESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2000-2003, Darren Hiebert
* Copyright (c) 2017, Red Hat, Inc.
* Copyright (c) 2017, Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* This module contains functions for applying regular expression matching.
*
* The code for utilizing the Gnu regex package with regards to processing the
* regex option and checking for regex matches was adapted from routines in
* Gnu etags.
*/
#ifndef CTAGS_MAIN_LREGEX_H
#define CTAGS_MAIN_LREGEX_H
/*
* INCLUDE FILES
*/
#include "general.h"
/*
* DATA DECLARATIONS
*/
typedef struct sTagRegexTable {
const char *const regex;
const char* const name;
const char* const kinds;
const char *const flags;
bool *disabled;
bool mline;
} tagRegexTable;
typedef struct {
size_t start; /* character index in line where match starts */
size_t length; /* length of match */
} regexMatch;
/* Return value is referred when {exclusive} is also specified.
The input line is consumed when "{exclusive}" is specified and
the value returned from the callback function is true. */
typedef bool (*regexCallback) (const char *line, const regexMatch *matches, unsigned int count,
void *userData);
#endif /* CTAGS_MAIN_LREGEX_H */

View File

@ -1,126 +0,0 @@
/*
* Copyright (c) 2000-2003, Darren Hiebert
* Copyright (c) 2017, Red Hat, Inc.
* Copyright (c) 2017, Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* This module contains functions for applying regular expression matching.
*
* The code for utilizing the Gnu regex package with regards to processing the
* regex option and checking for regex matches was adapted from routines in
* Gnu etags.
*/
#ifndef CTAGS_MAIN_LREGEX_PRIVATE_H
#define CTAGS_MAIN_LREGEX_PRIVATE_H
/*
* INCLUDE FILES
*/
#include "general.h"
#include "flags_p.h"
#include "kind_p.h"
#include "lregex.h"
#include "parse.h"
#include <regex.h>
/*
* MACRO DEFINITIONS
*/
/* Back-references \0 through \9 */
#define BACK_REFERENCE_COUNT 10
/*
* DATA DECLARATIONS
*/
enum regexParserType {
REG_PARSER_SINGLE_LINE,
REG_PARSER_MULTI_LINE,
REG_PARSER_MULTI_TABLE,
};
struct lregexControlBlock;
typedef struct sRegexCompiledCode {
struct regexBackend *backend;
void * code;
} regexCompiledCode;
struct regexBackend {
flagDefinition *fdefs;
unsigned int fdef_count;
void (* set_icase_flag) (int *);
regexCompiledCode (* compile) (struct regexBackend *,
const char* const,
int);
int (* match) (struct regexBackend *,
void *, const char *, size_t,
regmatch_t[BACK_REFERENCE_COUNT]);
void (* delete_code) (void *);
};
struct flagDefsDescriptor {
struct regexBackend *backend;
int flags;
enum regexParserType regptype;
};
/*
* FUNCTION PROTOTYPES
*/
extern struct lregexControlBlock* allocLregexControlBlock (parserDefinition *parser);
extern void freeLregexControlBlock (struct lregexControlBlock* lcb);
extern void processTagRegexOption (struct lregexControlBlock *lcb,
enum regexParserType,
const char* const parameter);
extern void addTagRegex (struct lregexControlBlock *lcb, const char* const regex,
const char* const name, const char* const kinds, const char* const flags,
bool *disabled);
extern void addTagMultiLineRegex (struct lregexControlBlock *lcb, const char* const regex,
const char* const name, const char* const kinds, const char* const flags,
bool *disabled);
extern void addTagMultiTableRegex(struct lregexControlBlock *lcb,
const char* const table_name,
const char* const regex,
const char* const name, const char* const kinds, const char* const flags,
bool *disabled);
extern bool matchRegex (struct lregexControlBlock *lcb, const vString* const line);
extern bool doesExpectCorkInRegex (struct lregexControlBlock *lcb);
extern void addCallbackRegex (struct lregexControlBlock *lcb,
const char* const regex,
const char* const flags,
const regexCallback callback,
bool *disabled,
void * userData);
extern bool regexNeedsMultilineBuffer (struct lregexControlBlock *lcb);
extern bool matchMultilineRegex (struct lregexControlBlock *lcb, const vString* const allLines);
extern bool matchMultitableRegex (struct lregexControlBlock *lcb, const vString* const allLines);
extern void notifyRegexInputStart (struct lregexControlBlock *lcb);
extern void notifyRegexInputEnd (struct lregexControlBlock *lcb);
extern void addRegexTable (struct lregexControlBlock *lcb, const char *name);
extern void extendRegexTable (struct lregexControlBlock *lcb, const char *src, const char *dist);
extern void initRegexOptscript (void);
extern void listRegexOpscriptOperators (FILE *fp);
extern void addOptscriptToHook (struct lregexControlBlock *lcb, enum scriptHook hook, const char *code);
extern void printMultitableStatistics (struct lregexControlBlock *lcb);
extern void basic_regex_flag_short (char c, void* data);
extern void basic_regex_flag_long (const char* const s, const char* const unused, void* data);
extern void extend_regex_flag_short (char c, void* data);
extern void extend_regex_flag_long (const char* const s, const char* const unused, void* data);
#ifdef HAVE_PCRE2
extern void pcre2_regex_flag_short (char c, void* data);
extern void pcre2_regex_flag_long (const char* const s, const char* const unused, void* data);
#endif
#endif /* CTAGS_MAIN_LREGEX_PRIVATEH */

1227
ctags/main/lxcmd.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -12,9 +12,8 @@
#include "debug.h"
#include "entry.h"
#include "options.h"
#include "parse_p.h"
#include "parse.h"
#include "read.h"
#include "read_p.h"
#include "routines.h"
#include "xtag.h"
@ -23,43 +22,36 @@
#include <libxml/tree.h>
static void simpleXpathMakeTag (xmlNode *node,
const char *xpath,
const tagXpathMakeTagSpec *spec,
const kindDefinition* const kinds,
void *userData)
{
tagEntryInfo tag;
xmlChar* str;
char *path;
int kind;
str = xmlNodeGetContent(node);
if (str == NULL)
return;
if (spec->kind == KIND_GHOST_INDEX && spec->decideKind)
kind = spec->decideKind (node, xpath, spec, userData);
else
kind = spec->kind;
Assert (kind != KIND_GHOST_INDEX);
if (spec->role == ROLE_DEFINITION_INDEX)
initTagEntry (&tag, (char *)str, kind);
if (spec->role == ROLE_INDEX_DEFINITION)
initTagEntry (&tag, (char *)str, spec->kind);
else if (isXtagEnabled(XTAG_REFERENCE_TAGS))
initRefTagEntry (&tag, (char *)str,
kind,
spec->kind,
spec->role);
else
goto out;
tag.lineNumber = XML_GET_LINE (node);
tag.lineNumber = xmlGetLineNo (node);
tag.filePosition = getInputFilePositionForLine (tag.lineNumber);
path = (char *)xmlGetNodePath (node);
tag.extensionFields.xpath = path;
if (spec->make)
spec->make (node, xpath, spec, &tag, userData);
spec->make (node, spec, &tag, userData);
else
makeTagEntry (&tag);
@ -80,18 +72,9 @@ extern void addTagXpath (const langType language CTAGS_ATTR_UNUSED, tagXpathTabl
error (WARNING, "Failed to compile the Xpath expression: %s", xpathTable->xpath);
}
extern void removeTagXpath (const langType language CTAGS_ATTR_UNUSED, tagXpathTable *xpathTable)
{
if (xpathTable->xpathCompiled)
{
xmlXPathFreeCompExpr (xpathTable->xpathCompiled);
xpathTable->xpathCompiled = NULL;
}
}
static void findXMLTagsCore (xmlXPathContext *ctx, xmlNode *root,
const tagXpathTableTable *xpathTableTable,
void *userData)
const kindDefinition* const kinds,void *userData)
{
unsigned int i;
int j;
@ -112,10 +95,10 @@ static void findXMLTagsCore (xmlXPathContext *ctx, xmlNode *root,
#if 0
/* Older version of libxml2 doesn't have xmlXPathSetContextNode. */
if (xmlXPathSetContextNode (root, ctx) != 0)
{
error (WARNING, "Failed to set node to XpathContext");
return;
}
{
error (WARNING, "Failed to set node to XpathContext");
return;
}
#else
ctx->node = root;
#endif
@ -128,13 +111,13 @@ static void findXMLTagsCore (xmlXPathContext *ctx, xmlNode *root,
if (set)
{
for (j = 0; j < xmlXPathNodeSetGetLength (set); ++j)
for (j = 0; j < set->nodeNr; ++j)
{
node = xmlXPathNodeSetItem(set, j);
node = set->nodeTab[j];
if (elt->specType == LXPATH_TABLE_DO_MAKE)
simpleXpathMakeTag (node, elt->xpath, &(elt->spec.makeTagSpec), userData);
simpleXpathMakeTag (node, &(elt->spec.makeTagSpec), kinds, userData);
else
elt->spec.recurSpec.enter (node, elt->xpath, &(elt->spec.recurSpec), ctx, userData);
elt->spec.recurSpec.enter (node, &(elt->spec.recurSpec), ctx, userData);
}
}
xmlXPathFreeObject (object);
@ -149,7 +132,7 @@ static xmlDocPtr makeXMLDoc (void)
{
const unsigned char* data;
size_t size;
xmlDocPtr doc;
xmlDocPtr doc = NULL;
doc = getInputFileUserData ();
if (doc)
@ -161,7 +144,6 @@ static xmlDocPtr makeXMLDoc (void)
data = getInputFileData (&size);
if (data)
{
xmlSetGenericErrorFunc (NULL, suppressWarning);
xmlLineNumbersDefault (1);
doc = xmlParseMemory((const char*)data, size);
}
@ -169,24 +151,21 @@ static xmlDocPtr makeXMLDoc (void)
return doc;
}
extern void findXMLTagsFull (xmlXPathContext *ctx, xmlNode *root,
int tableTableIndex,
void (* runAfter) (xmlXPathContext *, xmlNode *, void *),
void *userData)
extern void findXMLTags (xmlXPathContext *ctx, xmlNode *root,
const tagXpathTableTable *xpathTableTable,
const kindDefinition* const kinds,void *userData)
{
bool usedAsEntryPoint = false;
xmlDocPtr doc = NULL;
const langType lang = getInputLanguage();
const tagXpathTableTable *xpathTableTable
= getXpathTableTable (lang, tableTableIndex);
if (ctx == NULL)
{
usedAsEntryPoint = true;
findRegexTags ();
xmlSetGenericErrorFunc (NULL, suppressWarning);
doc = makeXMLDoc ();
if (doc == NULL)
@ -207,9 +186,7 @@ extern void findXMLTagsFull (xmlXPathContext *ctx, xmlNode *root,
}
}
findXMLTagsCore (ctx, root, xpathTableTable, userData);
if (runAfter)
(* runAfter) (ctx, root, userData);
findXMLTagsCore (ctx, root, xpathTableTable, kinds, userData);
out:
if (usedAsEntryPoint)
@ -228,22 +205,10 @@ extern void addTagXpath (const langType language, tagXpathTable *xpathTable)
xpathTable->xpathCompiled = NULL;
}
extern void removeTagXpath (const langType language CTAGS_ATTR_UNUSED, tagXpathTable *xpathTable CTAGS_ATTR_UNUSED)
{
}
extern void findXMLTagsFull (xmlXPathContext *ctx, xmlNode *root,
int tableTableIndex,
void (* runAfter) (xmlXPathContext *, xmlNode *, void *),
void *userData)
extern void findXMLTags (xmlXPathContext *ctx, xmlNode *root,
const tagXpathTableTable *xpathTableTable,
const kindDefinition* const kinds, void *userData)
{
}
#endif
extern void findXMLTags (xmlXPathContext *ctx, xmlNode *root,
int tableTableIndex,
void *userData)
{
findXMLTagsFull (ctx, root, tableTableIndex, NULL, userData);
}

View File

@ -1,110 +0,0 @@
/*
* Copyright (c) 2016, Masatake YAMATO
* Copyright (c) 2016, Red Hat, Inc.
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Xpath based parer API
*/
#ifndef CTAGS_LXPATH_PARSE_H
#define CTAGS_LXPATH_PARSE_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "types.h"
#ifdef HAVE_LIBXML
#include <libxml/xpath.h>
#include <libxml/tree.h>
#else
#define xmlNode void
#define xmlXPathCompExpr void
#define xmlXPathContext void
#endif
/*
* DATA DECLARATIONS
*/
typedef struct sTagXpathMakeTagSpec {
/* Kind used in making a tag.
If kind is KIND_GHOST_INDEX, a function
specified with decideKind is called to decide
the kind for the tag. */
int kind;
int role;
/* If make is NULL, just makeTagEntry is used instead. */
void (*make) (xmlNode *node,
const char *xpath,
const struct sTagXpathMakeTagSpec *spec,
tagEntryInfo *tag,
void *userData);
int (*decideKind) (xmlNode *node,
const char *xpath,
const struct sTagXpathMakeTagSpec *spec,
void *userData);
/* TODO: decideRole */
} tagXpathMakeTagSpec;
typedef struct sTagXpathRecurSpec {
void (*enter) (xmlNode *node,
const char *xpath,
const struct sTagXpathRecurSpec *spec,
xmlXPathContext *ctx,
void *userData);
int nextTable; /* A parser can use this field any purpose.
main/lxpath part doesn't touch this. */
} tagXpathRecurSpec;
typedef struct sTagXpathTable
{
const char *const xpath;
enum { LXPATH_TABLE_DO_MAKE, LXPATH_TABLE_DO_RECUR } specType;
union {
tagXpathMakeTagSpec makeTagSpec;
tagXpathRecurSpec recurSpec;
} spec;
xmlXPathCompExpr* xpathCompiled;
} tagXpathTable;
typedef struct sTagXpathTableTable {
tagXpathTable *table;
unsigned int count;
} tagXpathTableTable;
typedef struct sXpathFileSpec {
/*
NULL represents the associated field in DTD is not examined.
"" (an empty string) represents the associated field in DTD
(and root element) must not exist. */
const char *rootElementName;
const char *nameInDTD;
const char *externalID;
const char *systemID;
const char *rootNSPrefix;
const char *rootNSHref;
} xpathFileSpec;
/*
* FUNCTION PROTOTYPES
*/
/* Xpath interface */
extern void findXMLTagsFull (xmlXPathContext *ctx, xmlNode *root,
int tableTableIndex,
void (* runAfter) (xmlXPathContext *, xmlNode *, void *),
void *userData);
extern void findXMLTags (xmlXPathContext *ctx, xmlNode *root,
int tableTableIndex,
void *userData);
#endif /* CTAGS_LXPATH_PARSE_H */

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2016, Masatake YAMATO
* Copyright (c) 2016, Red Hat, Inc.
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Xpath based parer API for the main part
*/
#ifndef CTAGS_LXPATH_PARSE_PRIVATE_H
#define CTAGS_LXPATH_PARSE_PRIVATE_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "types.h"
/*
* FUNCTION PROTOTYPES
*/
extern void addTagXpath (const langType language, tagXpathTable *xpathTable);
extern void removeTagXpath (const langType language, tagXpathTable *xpathTable);
#endif /* CTAGS_LXPATH_PARSE_PRIVATE_H */

View File

@ -28,9 +28,21 @@
#include <crt_externs.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* To provide timings features if available.
*/
#ifdef HAVE_CLOCK
# ifdef HAVE_TIME_H
# include <time.h>
# endif
#else
# ifdef HAVE_TIMES
# ifdef HAVE_SYS_TIMES_H
# include <sys/times.h>
# endif
# endif
#endif
/* To provide directory searching for recursion feature.
*/
@ -44,51 +56,74 @@
#ifdef HAVE_DIRECT_H
# include <direct.h> /* to _getcwd() */
#endif
#ifdef HAVE_DIR_H
# include <dir.h> /* to declare findfirst() and findnext */
#endif
#ifdef HAVE_IO_H
# include <io.h> /* to declare _findfirst() */
#endif
#include "ctags.h"
#include "debug.h"
#include "entry_p.h"
#include "error_p.h"
#include "field_p.h"
#include "keyword_p.h"
#include "main_p.h"
#include "options_p.h"
#include "optscript.h"
#include "parse_p.h"
#include "read_p.h"
#include "routines_p.h"
#include "stats_p.h"
#include "trace.h"
#include "trashbox_p.h"
#include "writer_p.h"
#include "xtag_p.h"
#include "entry.h"
#include "error.h"
#include "field.h"
#include "keyword.h"
#include "main.h"
#include "options.h"
#include "output.h"
#include "read.h"
#include "routines.h"
#ifdef HAVE_JANSSON
#include "interactive_p.h"
#include <jansson.h>
#include <errno.h>
#endif
/*
* MACROS
*/
#define plural(value) (((unsigned long)(value) == 1L) ? "" : "s")
/*
* DATA DEFINITIONS
*/
static struct { long files, lines, bytes; } Totals = { 0, 0, 0 };
#ifndef CTAGS_LIB
static mainLoopFunc mainLoop;
static void *mainData;
#endif
/*
* FUNCTION PROTOTYPES
*/
#ifndef CTAGS_LIB
static bool createTagsForEntry (const char *const entryName);
#endif
/*
* FUNCTION DEFINITIONS
*/
#if defined (HAVE_OPENDIR) && (defined (HAVE_DIRENT_H) || defined (_MSC_VER))
extern void addTotals (
const unsigned int files, const long unsigned int lines,
const long unsigned int bytes)
{
Totals.files += files;
Totals.lines += lines;
Totals.bytes += bytes;
}
extern bool isDestinationStdout (void)
{
bool toStdout = false;
if (outpuFormatUsedStdoutByDefault() || Option.filter ||
(Option.tagFileName != NULL && (strcmp (Option.tagFileName, "-") == 0
|| strcmp (Option.tagFileName, "/dev/stdout") == 0
)))
toStdout = true;
return toStdout;
}
#ifndef CTAGS_LIB
#if defined (HAVE_OPENDIR)
static bool recurseUsingOpendir (const char *const dirName)
{
bool resize = false;
@ -108,10 +143,10 @@ static bool recurseUsingOpendir (const char *const dirName)
if (strcmp (dirName, ".") == 0)
filePath = entry->d_name;
else
{
{
filePath = combinePathAndFile (dirName, entry->d_name);
free_p = true;
}
}
resize |= createTagsForEntry (filePath);
if (free_p)
eFree (filePath);
@ -121,9 +156,8 @@ static bool recurseUsingOpendir (const char *const dirName)
}
return resize;
}
#endif
#ifdef HAVE__FINDFIRST
#elif defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
static bool createTagsForWildcardEntry (
const char *const pattern, const size_t dirLength,
@ -146,8 +180,18 @@ static bool createTagsForWildcardUsingFindfirst (const char *const pattern)
{
bool resize = false;
const size_t dirLength = baseFilename (pattern) - pattern;
#if defined (HAVE_FINDFIRST)
struct ffblk fileInfo;
int result = findfirst (pattern, &fileInfo, FA_DIREC);
while (result == 0)
{
const char *const entry = (const char *) fileInfo.ff_name;
resize |= createTagsForWildcardEntry (pattern, dirLength, entry);
result = findnext (&fileInfo);
}
#elif defined (HAVE__FINDFIRST)
struct _finddata_t fileInfo;
intptr_t hFile = _findfirst (pattern, &fileInfo);
findfirst_t hFile = _findfirst (pattern, &fileInfo);
if (hFile != -1L)
{
do
@ -157,6 +201,7 @@ static bool createTagsForWildcardUsingFindfirst (const char *const pattern)
} while (_findnext (hFile, &fileInfo) == 0);
_findclose (hFile);
}
#endif
return resize;
}
@ -180,9 +225,9 @@ static bool recurseIntoDirectory (const char *const dirName)
else
{
verbose ("RECURSING into directory \"%s\"\n", dirName);
#if defined (HAVE_OPENDIR) && (defined (HAVE_DIRENT_H) || defined (_MSC_VER))
#if defined (HAVE_OPENDIR)
resize = recurseUsingOpendir (dirName);
#elif defined (HAVE__FINDFIRST)
#elif defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
{
vString *const pattern = vStringNew ();
vStringCopyS (pattern, dirName);
@ -205,8 +250,8 @@ static bool createTagsForEntry (const char *const entryName)
fileStatus *status = eStat (entryName);
Assert (entryName != NULL);
if (isExcludedFile (entryName, true))
verbose ("excluding \"%s\" (the early stage)\n", entryName);
if (isExcludedFile (entryName))
verbose ("excluding \"%s\"\n", entryName);
else if (status->isSymbolicLink && ! Option.followLinks)
verbose ("ignoring \"%s\" (symbolic link)\n", entryName);
else if (! status->exists)
@ -215,8 +260,6 @@ static bool createTagsForEntry (const char *const entryName)
resize = recurseIntoDirectory (entryName);
else if (! status->isNormalFile)
verbose ("ignoring \"%s\" (special file)\n", entryName);
else if (isExcludedFile (entryName, false))
verbose ("excluding \"%s\"\n", entryName);
else
resize = parseFile (entryName);
@ -232,9 +275,9 @@ static bool createTagsForWildcardArg (const char *const arg)
vString *const pattern = vStringNewInit (arg);
char *patternS = vStringValue (pattern);
#if defined (HAVE__FINDFIRST)
#if defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
/* We must transform the "." and ".." forms into something that can
* be expanded by the _findfirst function.
* be expanded by the findfirst/_findfirst functions.
*/
if (Option.recurse &&
(strcmp (patternS, ".") == 0 || strcmp (patternS, "..") == 0))
@ -316,6 +359,69 @@ static bool createTagsFromListFile (const char *const fileName)
return resize;
}
#if defined (HAVE_CLOCK)
# define CLOCK_AVAILABLE
# ifndef CLOCKS_PER_SEC
# define CLOCKS_PER_SEC 1000000
# endif
#elif defined (HAVE_TIMES)
# define CLOCK_AVAILABLE
# define CLOCKS_PER_SEC 60
static clock_t clock (void)
{
struct tms buf;
times (&buf);
return (buf.tms_utime + buf.tms_stime);
}
#else
# define clock() (clock_t)0
#endif
static void printTotals (const clock_t *const timeStamps)
{
const unsigned long totalTags = numTagsTotal();
const unsigned long addedTags = numTagsAdded();
fprintf (stderr, "%ld file%s, %ld line%s (%ld kB) scanned",
Totals.files, plural (Totals.files),
Totals.lines, plural (Totals.lines),
Totals.bytes/1024L);
#ifdef CLOCK_AVAILABLE
{
const double interval = ((double) (timeStamps [1] - timeStamps [0])) /
CLOCKS_PER_SEC;
fprintf (stderr, " in %.01f seconds", interval);
if (interval != (double) 0.0)
fprintf (stderr, " (%lu kB/s)",
(unsigned long) (Totals.bytes / interval) / 1024L);
}
#endif
fputc ('\n', stderr);
fprintf (stderr, "%lu tag%s added to tag file",
addedTags, plural(addedTags));
if (Option.append)
fprintf (stderr, " (now %lu tags)", totalTags);
fputc ('\n', stderr);
if (totalTags > 0 && Option.sorted != SO_UNSORTED)
{
fprintf (stderr, "%lu tag%s sorted", totalTags, plural (totalTags));
#ifdef CLOCK_AVAILABLE
fprintf (stderr, " in %.02f seconds",
((double) (timeStamps [2] - timeStamps [1])) / CLOCKS_PER_SEC);
#endif
fputc ('\n', stderr);
}
#ifdef DEBUG
fprintf (stderr, "longest tag line = %lu\n",
(unsigned long) maxTagsLine ());
#endif
}
static bool etagsInclude (void)
{
return (bool)(Option.etags && Option.etagsInclude != NULL);
@ -380,113 +486,10 @@ static void batchMakeTags (cookedArgs *args, void *user CTAGS_ATTR_UNUSED)
timeStamp (2);
if (Option.printTotals)
{
printTotals (timeStamps, Option.append, Option.sorted);
if (Option.printTotals > 1)
for (unsigned int i = 0; i < countParsers(); i++)
printParserStatisticsIfUsed (i);
}
printTotals (timeStamps);
#undef timeStamp
}
#ifdef HAVE_JANSSON
void interactiveLoop (cookedArgs *args CTAGS_ATTR_UNUSED, void *user)
{
struct interactiveModeArgs *iargs = user;
if (iargs->sandbox) {
/* As of jansson 2.6, the object hashing is seeded off
of /dev/urandom, so trigger the hash seeding
before installing the syscall filter.
*/
json_t * tmp = json_object ();
json_decref (tmp);
if (installSyscallFilter ()) {
error (FATAL, "install_syscall_filter failed");
/* The explicit exit call is needed because
"error (FATAL,..." just prints a message in
interactive mode. */
exit (1);
}
}
char buffer[1024];
json_t *request;
fputs ("{\"_type\": \"program\", \"name\": \"" PROGRAM_NAME "\", \"version\": \"" PROGRAM_VERSION "\"}\n", stdout);
fflush (stdout);
while (fgets (buffer, sizeof(buffer), stdin))
{
if (buffer[0] == '\n')
continue;
request = json_loads (buffer, JSON_DISABLE_EOF_CHECK, NULL);
if (! request)
{
error (FATAL, "invalid json");
goto next;
}
json_t *command = json_object_get (request, "command");
if (! command)
{
error (FATAL, "command name not found");
goto next;
}
if (!strcmp ("generate-tags", json_string_value (command)))
{
json_int_t size = -1;
const char *filename;
if (json_unpack (request, "{ss}", "filename", &filename) == -1)
{
error (FATAL, "invalid generate-tags request");
goto next;
}
json_unpack (request, "{sI}", "size", &size);
openTagFile ();
if (size == -1)
{ /* read from disk */
if (iargs->sandbox) {
error (FATAL,
"invalid request in sandbox submode: reading file contents from a file is limited");
closeTagFile (false);
goto next;
}
createTagsForEntry (filename);
}
else
{ /* read nbytes from stream */
unsigned char *data = eMalloc (size);
size = fread (data, 1, size, stdin);
MIO *mio = mio_new_memory (data, size, eRealloc, eFreeNoNullCheck);
parseFileWithMio (filename, mio, NULL);
mio_unref (mio);
}
closeTagFile (false);
fputs ("{\"_type\": \"completed\", \"command\": \"generate-tags\"}\n", stdout);
fflush(stdout);
}
else
{
error (FATAL, "unknown command name");
goto next;
}
next:
json_decref (request);
}
}
#endif
static bool isSafeVar (const char* var)
{
const char *safe_vars[] = {
@ -505,21 +508,17 @@ static bool isSafeVar (const char* var)
static void sanitizeEnviron (void)
{
char **e;
char **e = NULL;
int i;
#if HAVE_DECL___ENVIRON
e = __environ;
#elif HAVE_DECL__NSGETENVIRON
{
char ***ep = _NSGetEnviron();
if (ep)
e = *ep;
else
e = NULL;
}
#else
e = NULL;
{
char ***ep = _NSGetEnviron();
if (ep)
e = *ep;
}
#endif
if (!e)
@ -548,36 +547,25 @@ static void sanitizeEnviron (void)
* Start up code
*/
extern int ctags_cli_main (int argc CTAGS_ATTR_UNUSED, char **argv)
extern int main (int argc CTAGS_ATTR_UNUSED, char **argv)
{
cookedArgs *args;
#if defined(WIN32) && defined(HAVE_MKSTEMP)
/* MinGW-w64's mkstemp() uses rand() for generating temporary files. */
srand ((unsigned int) clock ());
#endif
initDefaultTrashBox ();
DEBUG_INIT();
setErrorPrinter (stderrDefaultErrorPrinter, NULL);
setMainLoop (batchMakeTags, NULL);
setTagWriter (WRITER_U_CTAGS, NULL);
setTagWriter (&ctagsWriter);
setCurrentDirectory ();
setExecutableName (*argv++);
sanitizeEnviron ();
checkRegex ();
initFieldObjects ();
initXtagObjects ();
initFieldDescs ();
args = cArgNewFromArgv (argv);
previewFirstOption (args);
initializeParsing ();
testEtagsInvocation ();
initializeParsing ();
initOptions ();
initRegexOptscript ();
readOptionConfiguration ();
verbose ("Reading initial options from command line\n");
parseCmdlineOptions (args);
@ -595,15 +583,15 @@ extern int ctags_cli_main (int argc CTAGS_ATTR_UNUSED, char **argv)
freeOptionResources ();
freeParserResources ();
freeRegexResources ();
freeXcmdResources ();
#ifdef HAVE_ICONV
freeEncodingResources ();
#endif
finiDefaultTrashBox();
if (Option.printLanguage)
return (Option.printLanguage == true)? 0: 1;
exit (0);
return 0;
}
#endif

26
ctags/main/main.h Normal file
View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 1998-2002, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* External interface to main.c
*/
#ifndef CTAGS_MAIN_MAIN_H
#define CTAGS_MAIN_MAIN_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include <stdio.h>
/*
* FUNCTION PROTOTYPES
*/
extern void addTotals (const unsigned int files, const long unsigned int lines, const long unsigned int bytes);
extern bool isDestinationStdout (void);
extern int main (int argc, char **argv);
#endif /* CTAGS_MAIN_MAIN_H */

View File

@ -1,22 +0,0 @@
/*
* Copyright (c) 1998-2002, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Main part private interface to main.c
*/
#ifndef CTAGS_MAIN_MAIN_PRIVATE_H
#define CTAGS_MAIN_MAIN_PRIVATE_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
/*
* FUNCTION PROTOTYPES
*/
extern int ctags_cli_main (int argc, char **argv);
#endif /* CTAGS_MAIN_MAIN_PRIVATE_H */

View File

@ -1,113 +0,0 @@
/*
* $Id$
*
* Copyright (c) 2015, vim-jp
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* This module contains functions for checking multibyte character set.
*/
/*
* INCLUDE FILES
*/
#ifndef __USE_GNU
# define __USE_GNU
#endif
#include "general.h" /* must always come first */
#ifdef HAVE_ICONV
#include <stdio.h>
#include <string.h>
#include <iconv.h>
#include <errno.h>
#include "options.h"
#include "mbcs.h"
#include "mbcs_p.h"
#include "routines.h"
static iconv_t iconv_fd = (iconv_t) -1;
extern bool openConverter (const char* inputEncoding, const char* outputEncoding)
{
if (!inputEncoding || !outputEncoding)
{
static bool warn = false;
/* --output-encoding is specified but not --input-encoding provided */
if (!warn && outputEncoding)
{
error (WARNING, "--input-encoding is not specified");
warn = true;
}
return false;
}
iconv_fd = iconv_open(outputEncoding, inputEncoding);
if (iconv_fd == (iconv_t) -1)
{
error (FATAL,
"failed opening encoding from '%s' to '%s'", inputEncoding, outputEncoding);
return false;
}
return true;
}
extern bool isConverting ()
{
return iconv_fd != (iconv_t) -1;
}
extern bool convertString (vString *const string)
{
size_t dest_len, src_len;
char *dest, *dest_ptr, *src;
if (iconv_fd == (iconv_t) -1)
return false;
src_len = vStringLength (string);
/* Should be longest length of bytes. so maybe utf8. */
dest_len = src_len * 4;
dest_ptr = dest = xCalloc (dest_len, char);
if (!dest)
return false;
src = vStringValue (string);
retry:
if (iconv (iconv_fd, &src, &src_len, &dest_ptr, &dest_len) == (size_t) -1)
{
if (errno == EILSEQ)
{
*dest_ptr++ = '?';
dest_len--;
src++;
src_len--;
verbose (" Encoding: %s\n", strerror(errno));
goto retry;
}
eFree (dest);
return false;
}
dest_len = dest_ptr - dest;
vStringClear (string);
if (vStringSize (string) < dest_len + 1)
vStringResize (string, dest_len + 1);
memcpy (vStringValue (string), dest, dest_len + 1);
vStringLength (string) = dest_len;
eFree (dest);
iconv (iconv_fd, NULL, NULL, NULL, NULL);
return true;
}
extern void closeConverter ()
{
if (iconv_fd != (iconv_t) -1)
{
iconv_close(iconv_fd);
iconv_fd = (iconv_t) -1;
}
}
#endif /* HAVE_ICONV */

View File

@ -1,28 +1 @@
/*
* $Id$
*
* Copyright (c) 2015, vim-jp
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* This module contains functions for checking multibyte character set.
*/
#ifndef CTAGS_MAIN_MBCS_H
#define CTAGS_MAIN_MBCS_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#ifdef HAVE_ICONV
/*
* FUNCTION PROTOTYPES
*/
extern bool isConverting (void);
#endif /* HAVE_ICONV */
#endif /* CTAGS_MAIN_MBCS_H */
/* Dummy header - only included by some parsers */

View File

@ -1,32 +0,0 @@
/*
* $Id$
*
* Copyright (c) 2015, vim-jp
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* This module contains functions for checking multibyte character set.
*/
#ifndef CTAGS_MAIN_MBCS_PRIVATE_H
#define CTAGS_MAIN_MBCS_PRIVATE_H
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "vstring.h"
#ifdef HAVE_ICONV
/*
* FUNCTION PROTOTYPES
*/
extern bool openConverter (const char*, const char*);
extern bool convertString (vString *const);
extern void closeConverter (void);
#endif /* HAVE_ICONV */
#endif /* CTAGS_MAIN_MBCS_PRIVATE_H */

View File

@ -1,346 +0,0 @@
/*
* Copyright (c) 2019, Jiri Techet
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Provides a simple application using ctags as a library and using the same
* set of ctags functions as the Geany editor
*/
#include "general.h" /* must always come first */
#include "types.h"
#include "routines.h"
#include "mio.h"
#include "error_p.h"
#include "writer_p.h"
#include "parse_p.h"
#include "options_p.h"
#include "trashbox_p.h"
#include "field_p.h"
#include "xtag_p.h"
#include "entry_p.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
static int writeEntry (tagWriter *writer, MIO * mio, const tagEntryInfo *const tag, void *clientData);
static void rescanFailed (tagWriter *writer, unsigned long validTagNum, void *clientData);
/* we need to be able to provide a custom writer using which we collect the tags */
tagWriter customWriter = {
.writeEntry = writeEntry,
.writePtagEntry = NULL,
.preWriteEntry = NULL,
.postWriteEntry = NULL,
.rescanFailedEntry = rescanFailed,
.treatFieldAsFixed = NULL,
.defaultFileName = "tags_file_which_should_never_appear_anywhere",
.private = NULL,
};
/* we need to be able to provide an error printer which doesn't crash Geany on error */
static bool nofatalErrorPrinter (const errorSelection selection,
const char *const format,
va_list ap, void *data CTAGS_ATTR_UNUSED)
{
fprintf (stderr, "%s: ", (selection & WARNING) ? "Warning: " : "Error");
vfprintf (stderr, format, ap);
if (selection & PERROR)
#ifdef HAVE_STRERROR
fprintf (stderr, " : %s", strerror (errno));
#else
perror (" ");
#endif
fputs ("\n", stderr);
return false;
}
/* we need to be able to enable all kinds for all languages (some are disabled by default) */
static void enableAllLangKinds()
{
unsigned int lang;
for (lang = 0; lang < countParsers(); lang++)
{
unsigned int kindNum = countLanguageKinds(lang);
unsigned int kind;
for (kind = 0; kind < kindNum; kind++)
{
kindDefinition *def = getLanguageKind(lang, kind);
enableKind(def, true);
}
}
}
/* we need to be able to initialize ctags like in main() but skipping some things */
static void ctagsInit(void)
{
initDefaultTrashBox ();
setErrorPrinter (nofatalErrorPrinter, NULL);
setTagWriter (WRITER_CUSTOM, &customWriter);
checkRegex ();
initFieldObjects ();
initXtagObjects ();
initializeParsing ();
initOptions ();
/* make sure all parsers are initialized */
initializeParser (LANG_AUTO);
/* change default value which is false */
enableXtag(XTAG_TAGS_GENERATED_BY_GUEST_PARSERS, true);
enableXtag(XTAG_REFERENCE_TAGS, true);
/* some kinds we are interested in are disabled by default */
enableAllLangKinds();
}
/* we need to be able to get a name of a given language */
static const char *ctagsGetLangName(int lang)
{
return getLanguageName(lang);
}
/* we need to be able to get an int representing a given language */
static int ctagsGetNamedLang(const char *name)
{
return getNamedLanguage(name, 0);
}
/* we need to be able to get kind letters provided by a given language */
static const char *ctagsGetLangKinds(int lang)
{
unsigned int kindNum = countLanguageKinds(lang);
static char kinds[257];
unsigned int i;
for (i = 0; i < kindNum; i++)
kinds[i] = getLanguageKind(lang, i)->letter;
kinds[i] = '\0';
return kinds;
}
/* we need to be able to get kind name from a kind letter for a given language */
static const char *ctagsGetKindName(char kind, int lang)
{
kindDefinition *def = getLanguageKindForLetter (lang, kind);
return def ? def->name : "unknown";
}
/* we need to be able to get kind letter from a kind name for a given language */
static char ctagsGetKindFromName(const char *name, int lang)
{
kindDefinition *def = getLanguageKindForName (lang, name);
return def ? def->letter : '-';
}
/* we need to be able to get kind letter from a kind index */
static char ctagsGetKindFromIndex(int index, int lang)
{
return getLanguageKind(lang, index)->letter;
}
/* we need to be able to get the number of parsers */
static unsigned int ctagsGetLangCount(void)
{
return countParsers();
}
/*******************************************************************************
* So let's just use what we have for our great client...
******************************************************************************/
/* our internal tag representation - this is all the tag information we use in Geany */
typedef struct {
char *name;
char *signature;
char *scopeName;
char *inheritance;
char *varType;
char *access;
char *implementation;
char kindLetter;
bool isFileScope;
unsigned long lineNumber;
int lang;
} Tag;
static Tag *createTag(const tagEntryInfo *info)
{
Tag *tag = xCalloc(1, Tag);
if (info->name)
tag->name = eStrdup(info->name);
if (info->extensionFields.signature)
tag->signature = eStrdup(info->extensionFields.signature);
if (info->extensionFields.scopeName)
tag->scopeName = eStrdup(info->extensionFields.scopeName);
if (info->extensionFields.inheritance)
tag->inheritance = eStrdup(info->extensionFields.inheritance);
if (info->extensionFields.typeRef[1])
tag->varType = eStrdup(info->extensionFields.typeRef[1]);
if (info->extensionFields.access)
tag->access = eStrdup(info->extensionFields.access);
if (info->extensionFields.implementation)
tag->implementation = eStrdup(info->extensionFields.implementation);
tag->kindLetter = ctagsGetKindFromIndex(info->kindIndex, info->langType);
tag->isFileScope = info->isFileScope;
tag->lineNumber = info->lineNumber;
tag->lang = info->langType;
return tag;
}
static void destroyTag(Tag *tag)
{
if (tag->name)
eFree(tag->name);
if (tag->signature)
eFree(tag->signature);
if (tag->scopeName)
eFree(tag->scopeName);
if (tag->inheritance)
eFree(tag->inheritance);
if (tag->varType)
eFree(tag->varType);
if (tag->access)
eFree(tag->access);
if (tag->implementation)
eFree(tag->implementation);
eFree(tag);
}
/* callback from ctags informing us about a new tag */
static int writeEntry (tagWriter *writer, MIO *mio, const tagEntryInfo *const tag, void *clientData)
{
Tag *t;
/* apparently we have to call this to get the scope info - maybe we can
* specify some option during initialization so we don't have to cal this
* ?????? */
getTagScopeInformation((tagEntryInfo *)tag, NULL, NULL);
/* convert tags into our internal representation and store them into an array */
t = createTag(tag);
ptrArrayAdd((ptrArray *)clientData, t);
/* output length - we don't write anything to the MIO */
return 0;
}
/* scan has failed so we have invalid tags in our array - validTagNum should
* tell us the number of valid tags so remove all the extra tags and shrink the array */
static void rescanFailed (tagWriter *writer, unsigned long validTagNum, void *clientData)
{
ptrArray *tagArray = clientData;
int num = ptrArrayCount(tagArray);
if (num > validTagNum)
{
int i;
for (i = validTagNum; i < num; i++)
{
Tag *tag = ptrArrayLast(tagArray);
destroyTag(tag);
ptrArrayRemoveLast(tagArray);
}
}
}
/* do whatever we want to do with the tags */
static void processCollectedTags(ptrArray *tagArray)
{
int i;
int num = ptrArrayCount(tagArray);
for (i = 0; i < num; i++)
{
Tag *tag = ptrArrayItem(tagArray, i);
printf("%s\tline: %lu\tkind: %s\t lang: %s\n",
tag->name,
tag->lineNumber,
ctagsGetKindName(tag->kindLetter, tag->lang),
ctagsGetLangName(tag->lang));
}
/* prepare for the next parsing by clearing the tag array */
ptrArrayClear(tagArray);
}
extern int main (int argc, char **argv)
{
/* called once when Geany starts */
ctagsInit();
/* create empty tag array *
* this is where we store the collected tags
* NOTE: Geany doesn't use the ptrArray type - it is used just for the purpose of this demo */
ptrArray *tagArray = ptrArrayNew((ptrArrayDeleteFunc)destroyTag);
printf("This parser only parses C files - provide them as arguments on the "
"command line or get a hard-coded buffer parsed when no arguments "
"are provided\n\n");
if (argc == 1) /* parsing contents of a buffer */
{
char *program = "int foo() {}\n\n int bar() {}\n\n int main() {}\n";
int lang = ctagsGetNamedLang("C");
const char *kinds = ctagsGetLangKinds(lang);
int i;
printf("Number of all parsers is: %d\n", ctagsGetLangCount());
printf("We are parsing %s which provides the following kinds:\n",
ctagsGetLangName(lang));
for (i = 0; kinds[i] != '\0'; i++)
{
printf("%c: %s\n",
/* back and forth conversion - the same like just kinds[i] */
ctagsGetKindFromName(ctagsGetKindName(kinds[i], lang), lang),
ctagsGetKindName(kinds[i], lang));
}
printf("\nParsing buffer:\n");
/* we always specify the language by ourselves and don't use ctags detection */
parseRawBuffer("whatever", (unsigned char *)program, strlen(program), lang, tagArray);
processCollectedTags(tagArray);
}
else /* parsing contents of a file */
{
int i;
for (i = 1; i < argc; i++)
{
printf("\nParsing %s:\n", argv[i]);
/* parseRawBuffer() is called repeatadly during Geany execution */
parseRawBuffer(argv[i], NULL, 0, getNamedLanguage("C", 0), tagArray);
processCollectedTags(tagArray);
}
}
ptrArrayDelete(tagArray);
return 0;
}

View File

@ -18,7 +18,7 @@
*
*/
#ifndef READTAGS_DSL
#ifndef QUALIFIER
#include "general.h" /* must always come first */
#include "routines.h"
@ -29,10 +29,10 @@
#include <config.h>
#endif
#ifdef HAVE_STDBOOL_H
#ifdef USE_STDBOOL_H
#include <stdbool.h>
#endif
#endif /* READTAGS_DSL */
#endif
#include "mio.h"
@ -43,13 +43,9 @@
#include <stdlib.h>
#include <limits.h>
#ifndef _MSC_VER
#define MAY_HAVE_FTRUNCATE
#include <unistd.h>
#endif
#ifdef READTAGS_DSL
#ifdef QUALIFIER
#define xMalloc(n,Type) (Type *)eMalloc((size_t)(n) * sizeof (Type))
#define xCalloc(n,Type) (Type *)eCalloc((size_t)(n), sizeof (Type))
#define xRealloc(p,n,Type) (Type *)eRealloc((p), (n) * sizeof (Type))
static void *eMalloc (const size_t size)
@ -65,6 +61,19 @@ static void *eMalloc (const size_t size)
return buffer;
}
static void *eCalloc (const size_t count, const size_t size)
{
void *buffer = calloc (count, size);
if (buffer == NULL)
{
fprintf(stderr, "out of memory");
abort ();
}
return buffer;
}
static void *eRealloc (void *const ptr, const size_t size)
{
void *buffer;
@ -86,11 +95,10 @@ static void eFree (void *const ptr)
{
free (ptr);
}
#define eFreeNoNullCheck eFree
# define Assert(c) do {} while(0)
# define AssertNotReached() do {} while(0)
#endif /* READTAGS_DSL */
#endif
/* minimal reallocation chunk size */
#define MIO_CHUNK_SIZE 4096
@ -110,9 +118,9 @@ static void eFree (void *const ptr)
* A #MIO object is created using mio_new_file(), mio_new_memory() or mio_new_mio(),
* depending on whether you want file or in-memory operations.
* Its life is managed by reference counting. Just after calling one of functions
* for creating, the count is 1. mio_ref() increments the counter. mio_unref()
* for creating, the count is 1. mio_ref() increments the counter. mio_free()
* decrements it. When the counter becomes 0, the #MIO object will be destroyed
* in mio_unref(). There is also some other convenient API to create file-based
* in mio_free(). There is also some other convenient API to create file-based
* #MIO objects for more complex cases, such as mio_new_file_full() and
* mio_new_fp().
*
@ -181,10 +189,10 @@ struct _MIO {
* as a close function. The former is useful e.g. if you need to wrap fopen()
* for some reason (like filename encoding conversion for example), and the
* latter allows you both to match your custom open function and to choose
* whether the underlying #FILE object should or not be closed when mio_unref()
* whether the underlying #FILE object should or not be closed when mio_free()
* is called on the returned object.
*
* Free-function: mio_unref()
* Free-function: mio_free()
*
* Returns: A new #MIO on success, or %NULL on failure.
*/
@ -232,7 +240,7 @@ MIO *mio_new_file_full (const char *filename,
* This function simply calls mio_new_file_full() with the libc's fopen() and
* fclose() functions.
*
* Free-function: mio_unref()
* Free-function: mio_free()
*
* Returns: A new #MIO on success, or %NULL on failure.
*/
@ -257,7 +265,7 @@ MIO *mio_new_file (const char *filename, const char *mode)
* </programlisting>
* </example>
*
* Free-function: mio_unref()
* Free-function: mio_free()
*
* Returns: A new #MIO on success or %NULL on failure.
*/
@ -314,7 +322,7 @@ MIO *mio_new_fp (FILE *fp, MIOFCloseFunc close_func)
* </programlisting>
* </example>
*
* Free-function: mio_unref()
* Free-function: mio_free()
*
* Returns: A new #MIO on success, or %NULL on failure.
*/
@ -362,7 +370,7 @@ MIO *mio_new_memory (unsigned char *data,
*
* The function doesn't move the file position of @base.
*
* Free-function: mio_unref()
* Free-function: mio_free()
*
*/
@ -396,7 +404,7 @@ MIO *mio_new_mio (MIO *base, long start, long size)
if (r != size)
goto cleanup;
submio = mio_new_memory (data, size, eRealloc, eFreeNoNullCheck);
submio = mio_new_memory (data, size, eRealloc, eFree);
if (! submio)
goto cleanup;
@ -428,7 +436,7 @@ MIO *mio_ref (MIO *mio)
* Gets the underlying #FILE object associated with a #MIO file stream.
*
* <warning><para>The returned object may become invalid after a call to
* mio_unref() if the stream was configured to close the file when
* mio_free() if the stream was configured to close the file when
* destroyed.</para></warning>
*
* Returns: The underlying #FILE object of the given stream, or %NULL if the
@ -453,7 +461,7 @@ FILE *mio_file_get_fp (MIO *mio)
* Gets the underlying memory buffer associated with a #MIO memory stream.
*
* <warning><para>The returned pointer and size may become invalid after a
* successful write on the stream or after a call to mio_unref() if the stream
* successful write on the stream or after a call to mio_free() if the stream
* was configured to free the memory when destroyed.</para></warning>
*
* Returns: The memory buffer of the given #MIO stream, or %NULL if the stream
@ -474,7 +482,7 @@ unsigned char *mio_memory_get_data (MIO *mio, size_t *size)
}
/**
* mio_unref:
* mio_free:
* @mio: A #MIO object
*
* Decrements the reference counter of a #MIO and destroys the #MIO
@ -482,7 +490,7 @@ unsigned char *mio_memory_get_data (MIO *mio, size_t *size)
*
* Returns: Error code obtained from the registered MIOFCloseFunc or 0 on success.
*/
int mio_unref (MIO *mio)
int mio_free (MIO *mio)
{
int rv = 0;
@ -654,31 +662,6 @@ static int mem_try_resize (MIO *mio, size_t new_size)
return success;
}
static int file_try_resize (MIO *mio, size_t new_size)
{
mio_flush (mio);
FILE *fp = mio_file_get_fp (mio);
#ifdef MAY_HAVE_FTRUNCATE
if (ftruncate(fileno(fp), (off_t)new_size) < 0)
return false;
#else
/* See https://stackoverflow.com/questions/873454/how-to-truncate-a-file-in-c/874704#874704 */
if ((errno = _chsize_s(_fileno(fp), (__int64)new_size)) != 0)
return false;
#endif
return true;
}
int mio_try_resize (MIO *mio, size_t new_size)
{
if (mio->type == MIO_TYPE_MEMORY)
return mem_try_resize (mio, new_size);
else
return file_try_resize (mio, new_size);
}
/*
* mem_try_ensure_space:
* @mio: A #MIO object
@ -839,7 +822,7 @@ int mio_vprintf (MIO *mio, const char *format, va_list ap)
old_size = mio->impl.mem.size;
va_copy (ap_copy, ap);
/* compute the size we will need into the buffer */
n = vsnprintf (&dummy, 1, format, ap_copy) + 1;
n = vsnprintf (&dummy, 1, format, ap_copy);
va_end (ap_copy);
if (mem_try_ensure_space (mio, n))
{

View File

@ -126,7 +126,7 @@ MIO *mio_new_memory (unsigned char *data,
MIO *mio_new_mio (MIO *base, long start, long size);
MIO *mio_ref (MIO *mio);
int mio_unref (MIO *mio);
int mio_free (MIO *mio);
FILE *mio_file_get_fp (MIO *mio);
unsigned char *mio_memory_get_data (MIO *mio, size_t *size);
size_t mio_read (MIO *mio,
@ -159,6 +159,4 @@ int mio_flush (MIO *mio);
void mio_attach_user_data (MIO *mio, void *user_data, MIODestroyNotify user_data_free_func);
void *mio_get_user_data (MIO *mio);
int mio_try_resize (MIO *mio, size_t new_size);
#endif /* MIO_H */

View File

@ -13,13 +13,11 @@
*/
#include "general.h" /* must always come first */
#include "main.h"
#include "debug.h"
#include "entry.h"
#include "routines.h"
#include "nestlevel.h"
#include <string.h>
/* TODO: Alignment */
#define NL_SIZE(nls) (sizeof(NestingLevel) + (nls)->userDataSize)
#define NL_NTH(nls,n) (NestingLevel *)(((char *)((nls)->levels)) + ((n) * NL_SIZE (nls)))
@ -28,30 +26,21 @@
* FUNCTION DEFINITIONS
*/
extern NestingLevels *nestingLevelsNewFull(size_t userDataSize,
void (* deleteUserData)(NestingLevel *))
extern NestingLevels *nestingLevelsNew(size_t userDataSize)
{
NestingLevels *nls = xCalloc (1, NestingLevels);
nls->userDataSize = userDataSize;
nls->deleteUserData = deleteUserData;
return nls;
}
extern NestingLevels *nestingLevelsNew(size_t userDataSize)
{
return nestingLevelsNewFull (userDataSize, NULL);
}
extern void nestingLevelsFree(NestingLevels *nls)
{
int i;
NestingLevel *nl;
for (i = 0; i < nls->n; i++)
for (i = 0; i < nls->allocated; i++)
{
nl = NL_NTH(nls, i);
if (nls->deleteUserData)
nls->deleteUserData (nl);
nl->corkIndex = CORK_NIL;
}
if (nls->levels) eFree(nls->levels);
@ -72,9 +61,6 @@ extern NestingLevel * nestingLevelsPush(NestingLevels *nls, int corkIndex)
nls->n++;
nl->corkIndex = corkIndex;
if (nls->userDataSize > 0)
memset (nl->userData, 0, nls->userDataSize);
return nl;
}
@ -94,13 +80,21 @@ extern void nestingLevelsPop(NestingLevels *nls)
NestingLevel *nl = nestingLevelsGetCurrent(nls);
Assert (nl != NULL);
if (nls->deleteUserData)
nls->deleteUserData (nl);
nl->corkIndex = CORK_NIL;
nls->n--;
}
extern NestingLevel *nestingLevelsGetNthFromRoot (const NestingLevels *nls, int n)
extern NestingLevel *nestingLevelsGetCurrent(const NestingLevels *nls)
{
Assert (nls != NULL);
if (nls->n < 1)
return NULL;
return NL_NTH(nls, (nls->n - 1));
}
extern NestingLevel *nestingLevelsGetNth(const NestingLevels *nls, int n)
{
Assert (nls != NULL);
if (nls->n > n && n >= 0)
@ -109,12 +103,6 @@ extern NestingLevel *nestingLevelsGetNthFromRoot (const NestingLevels *nls, int
return NULL;
}
extern NestingLevel *nestingLevelsGetNthParent (const NestingLevels *nls, int n)
{
Assert (nls != NULL);
return nestingLevelsGetNthFromRoot (nls, nls->n - 1 - n);
}
extern void *nestingLevelGetUserData (const NestingLevel *nl)
{
return (void *)nl->userData;

View File

@ -35,22 +35,18 @@ struct NestingLevels
int n; /* number of levels in use */
int allocated;
size_t userDataSize;
void (* deleteUserData) (NestingLevel *);
};
/*
* FUNCTION PROTOTYPES
*/
extern NestingLevels *nestingLevelsNew(size_t userDataSize);
extern NestingLevels *nestingLevelsNewFull(size_t userDataSize,
void (* deleteUserData)(NestingLevel *));
extern void nestingLevelsFree(NestingLevels *nls);
extern NestingLevel *nestingLevelsPush(NestingLevels *nls, int corkIndex);
extern NestingLevel * nestingLevelsTruncate(NestingLevels *nls, int depth, int corkIndex);
extern void nestingLevelsPop(NestingLevels *nls);
#define nestingLevelsGetCurrent(NLS) nestingLevelsGetNthParent((NLS), 0)
extern NestingLevel *nestingLevelsGetNthFromRoot(const NestingLevels *nls, int n);
extern NestingLevel *nestingLevelsGetNthParent(const NestingLevels *nls, int n);
extern NestingLevel *nestingLevelsGetCurrent(const NestingLevels *nls);
extern NestingLevel *nestingLevelsGetNth(const NestingLevels *nls, int n);
extern void *nestingLevelGetUserData (const NestingLevel *nl);

View File

@ -36,7 +36,7 @@
return result; \
} \
\
extern unsigned int prefix##ArrayAdd (prefix##Array *const current, type num) \
extern void prefix##ArrayAdd (prefix##Array *const current, type num) \
{ \
Assert (current != NULL); \
if (current->count == current->max) \
@ -44,8 +44,7 @@
current->max *= 2; \
current->array = xRealloc (current->array, current->max, type); \
} \
current->array [current->count] = num; \
return current->count++; \
current->array [current->count++] = num; \
} \
\
extern void prefix##ArrayRemoveLast (prefix##Array *const current) \
@ -168,9 +167,9 @@
}
/* We expect the linker we use is enough clever to delete dead code. */
impNumArray(char, Char, char)
impNumArray(uchar, Uchar, unsigned char)
impNumArray(int, Int, int)
impNumArray(uint, Uint, unsigned int)
impNumArray(long, Long, long)
impNumArray(ulong, Ulong, unsigned long)
impNumArray(char, Char, char);
impNumArray(uchar, Uchar, unsigned char);
impNumArray(int, Int, int);
impNumArray(uint, Uint, unsigned int);
impNumArray(long, Long, long);
impNumArray(ulong, Ulong, unsigned long);

View File

@ -21,7 +21,7 @@
typedef struct s##Prefix##Array prefix##Array; \
\
extern prefix##Array *prefix##ArrayNew (void); \
extern unsigned int prefix##ArrayAdd (prefix##Array *const current, type num); \
extern void prefix##ArrayAdd (prefix##Array *const current, type num); \
extern void prefix##ArrayRemoveLast (prefix##Array *const current); \
extern void prefix##ArrayCombine (prefix##Array *const current, prefix##Array *const from); \
extern void prefix##ArrayClear (prefix##Array *const current); \
@ -38,11 +38,11 @@
\
extern void prefix##ArraySort (prefix##Array *const current, bool descendingOrder);
declNumArray(char, Char, char)
declNumArray(uchar, Uchar, unsigned char)
declNumArray(int, Int, int)
declNumArray(uint, Uint, unsigned int)
declNumArray(long, Long, long)
declNumArray(ulong, Ulong, unsigned long)
declNumArray(char, Char, char);
declNumArray(uchar, Uchar, unsigned char);
declNumArray(int, Int, int);
declNumArray(uint, Uint, unsigned int);
declNumArray(long, Long, long);
declNumArray(ulong, Ulong, unsigned long);
#endif /* CTAGS_MAIN_NUMARRAY_H */

View File

@ -13,7 +13,6 @@
*/
#include "general.h" /* must always come first */
#include "debug.h"
#include "routines.h"
#include "objpool.h"
@ -76,12 +75,7 @@ extern void objPoolPut (objPool *pool, void *obj)
if (obj == NULL)
return;
if (
#ifdef DISABLE_OBJPOOL
0 &&
#endif
ptrArrayCount (pool->array) < pool->size
)
if (ptrArrayCount (pool->array) < pool->size)
ptrArrayAdd (pool->array, obj);
else
pool->deleteFunc (obj);

File diff suppressed because it is too large Load Diff

View File

@ -9,35 +9,190 @@
#ifndef CTAGS_MAIN_OPTIONS_H
#define CTAGS_MAIN_OPTIONS_H
#if defined(OPTION_WRITE)
# define CONST_OPTION
#else
# define CONST_OPTION const
#endif
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "gvars.h"
#include <stdarg.h>
#include "args.h"
#include "field.h"
#include "fmt.h"
#include "parse.h"
#include "strlist.h"
#include "htable.h"
#include "vstring.h"
/*
* DATA DECLARATIONS
*/
typedef enum { OPTION_NONE, OPTION_SHORT, OPTION_LONG } optionType;
typedef struct sCookedArgs {
/* private */
Arguments* args;
char *shortOptions;
char simple[2];
bool isOption;
bool longOption;
const char* parameter;
/* public */
char* item;
} cookedArgs;
typedef enum eLocate {
EX_MIX, /* line numbers for defines, patterns otherwise */
EX_LINENUM, /* -n only line numbers in tag file */
EX_PATTERN /* -N only patterns in tag file */
} exCmd;
typedef enum sortType {
SO_UNSORTED,
SO_SORTED,
SO_FOLDSORTED
} sortType;
typedef struct sIgnoredTokenInfo {
bool ignoreFollowingParenthesis; /* -I SOMETHING+ */
char * replacement; /* -I SOMETHING=REPLACEMENT */
} ignoredTokenInfo;
/* This stores the command line options.
*/
typedef struct sOptionValues {
hashTable * ignore; /* -I name of file containing tokens to ignore */
bool append; /* -a append to "tags" file */
bool backward; /* -B regexp patterns search backwards */
bool etags; /* -e output Emacs style tags file */
exCmd locate; /* --excmd EX command used to locate tag */
bool recurse; /* -R recurse into directories */
sortType sorted; /* -u,--sort sort tags */
bool verbose; /* -V verbose */
bool xref; /* -x generate xref output instead */
fmtElement *customXfmt; /* compiled code for --xformat=XFMT */
char *fileList; /* -L name of file containing names of files */
char *tagFileName; /* -o name of tags file */
stringList* headerExt; /* -h header extensions */
char* configFilename; /* --config-filename use instead of 'ctags' in option file names */
stringList* etagsInclude;/* --etags-include list of TAGS files to include*/
unsigned int tagFileFormat;/* --format tag file format (level) */
#ifdef HAVE_ICONV
char *inputEncoding; /* --input-encoding convert text into --output-encoding */
char *outputEncoding; /* --output-encoding write tags file as this encoding */
#endif
bool if0; /* --if0 examine code within "#if 0" branch */
langType language; /* --lang specified language override */
bool followLinks; /* --link follow symbolic links? */
bool filter; /* --filter behave as filter: files in, tags out */
char* filterTerminator; /* --filter-terminator string to output */
bool tagRelative; /* --tag-relative file paths relative to tag file */
bool printTotals; /* --totals print cumulative statistics */
bool lineDirectives; /* --linedirectives process #line directives */
bool printLanguage; /* --print-language */
bool guessLanguageEagerly; /* --guess-language-eagerly|-G */
bool quiet; /* --quiet */
bool allowXcmdInHomeDir; /* --_allow-xcmd-in-homedir */
bool fatalWarnings; /* --_fatal-warnings */
unsigned int patternLengthLimit; /* --pattern-length-limit=N */
bool putFieldPrefix; /* --put-field-prefix */
unsigned int maxRecursionDepth; /* --maxdepth=<max-recursion-depth> */
bool machinable; /* --machinable */
bool withListHeader; /* --with-list-header */
#ifdef DEBUG
long debugLevel; /* -D debugging output */
unsigned long breakLine;/* -b input line at which to call lineBreak() */
#endif
} optionValues;
typedef enum eOptionLoadingStage {
OptionLoadingStageNone,
OptionLoadingStageCustom,
OptionLoadingStageDosCnf,
OptionLoadingStageEtc,
OptionLoadingStageLocalEtc,
OptionLoadingStageHomeRecursive,
OptionLoadingStageCurrentRecursive,
OptionLoadingStagePreload,
OptionLoadingStageEnvVar,
OptionLoadingStageCmdline,
} OptionLoadingStage;
/*
* GLOBAL VARIABLES
*/
extern CONST_OPTION optionValues Option;
/*
* FUNCTION PROTOTYPES
*/
extern void notice (const char *const format, ...) CTAGS_ATTR_PRINTF (1, 2);
extern void verbose (const char *const format, ...) CTAGS_ATTR_PRINTF (1, 2);
#define BEGIN_VERBOSE(VFP) do { if (ctags_verbose) { \
#define BEGIN_VERBOSE(VFP) do { if (Option.verbose) { \
FILE* VFP = stderr
#define END_VERBOSE() } } while (0)
#define BEGIN_VERBOSE_IF(COND,VFP) do { if (ctags_verbose || (COND)) { \
FILE* VFP = stderr
extern void freeList (stringList** const pString);
extern void setDefaultTagFileName (void);
extern void checkOptions (void);
extern bool filesRequired (void);
extern void testEtagsInvocation (void);
extern cookedArgs* cArgNewFromString (const char* string);
extern cookedArgs* cArgNewFromArgv (char* const* const argv);
extern cookedArgs* cArgNewFromFile (FILE* const fp);
extern cookedArgs* cArgNewFromLineFile (FILE* const fp);
extern void cArgDelete (cookedArgs* const current);
extern bool cArgOff (cookedArgs* const current);
extern bool cArgIsOption (cookedArgs* const current);
extern const char* cArgItem (cookedArgs* const current);
extern void cArgForth (cookedArgs* const current);
extern bool isExcludedFile (const char* const name);
extern bool isIncludeFile (const char *const fileName);
/* GEANY DIFF */
/* extern const ignoredTokenInfo * isIgnoreToken (const char *const name); */
extern bool isIgnoreToken (const char *const name, bool *const pIgnoreParens, const char **const replacement);
/* GEANY DIFF END */
extern void parseCmdlineOptions (cookedArgs* const cargs);
extern void previewFirstOption (cookedArgs* const cargs);
extern void readOptionConfiguration (void);
extern void initOptions (void);
extern void freeOptionResources (void);
#ifdef HAVE_ICONV
extern void freeEncodingResources (void);
#endif
/* Return vString must be freed by caller side. */
extern vString* expandOnCorpusPathList (const char* leaf);
extern vString* expandOnDriversPathList (const char* leaf);
extern bool inSandbox (void);
extern langType getLanguageComponentInOption (const char *const option,
const char *const prefix);
/* This is for emitting a tag for a common block of Fortran parser*/
extern void processLanguageDefineOption (const char *const option, const char *const parameter);
extern bool processMapOption (const char *const option, const char *const parameter);
extern bool processKindDefinition (const char *const option, const char *const parameter);
extern bool processCorpusOption (const char *const option, const char *const parameter);
extern bool processAliasOption (const char *const option, const char *const parameter);
#ifdef HAVE_ICONV
extern bool processLanguageEncodingOption (const char *const option, const char *const parameter);
#endif
extern bool processRegexOption (const char *const option, const char *const parameter);
extern bool processXcmdOption (const char *const option, const char *const parameter, OptionLoadingStage stage);
typedef void (* mainLoopFunc) (cookedArgs *args, void *data);
extern void setMainLoop (mainLoopFunc func, void *data);
/* This is for emitting a tag for a commnn block of Fortran parser*/
extern bool canUseLineNumberAsLocator (void);
#endif /* CTAGS_MAIN_OPTIONS_H */

View File

@ -1,187 +0,0 @@
/*
* Copyright (c) 1998-2003, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* Defines internal interface to option processing.
*/
#ifndef CTAGS_MAIN_OPTIONS_PRIVATE_H
#define CTAGS_MAIN_OPTIONS_PRIVATE_H
#if defined(OPTION_WRITE)
# define CONST_OPTION
#else
# define CONST_OPTION const
#endif
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "args_p.h"
#include "field.h"
#include "fmt_p.h"
#include "options.h"
#include "parse.h"
#include "strlist.h"
#include "vstring.h"
/*
* MACROS
*/
#define includeExtensionFlags() (Option.tagFileFormat > 1)
/*
* DATA DECLARATIONS
*/
typedef enum { OPTION_NONE, OPTION_SHORT, OPTION_LONG } optionType;
typedef struct sCookedArgs {
/* private */
Arguments* args;
char *shortOptions;
char simple[2];
bool isOption;
bool longOption;
const char* parameter;
/* public */
char* item;
} cookedArgs;
typedef enum eLocate {
EX_MIX, /* line numbers for defines, patterns otherwise */
EX_LINENUM, /* -n only line numbers in tag file */
EX_PATTERN, /* -N only patterns in tag file */
EX_COMBINE, /* Combine linenum and pattern with `;'*/
} exCmd;
typedef enum sortType {
SO_UNSORTED,
SO_SORTED,
SO_FOLDSORTED
} sortType;
typedef enum eTagRelative {
TREL_NO,
TREL_YES,
TREL_ALWAYS,
TREL_NEVER,
} tagRelative;
/* This stores the command line options.
*/
typedef struct sOptionValues {
bool append; /* -a append to "tags" file */
bool backward; /* -B regexp patterns search backwards */
bool etags; /* -e output Emacs style tags file */
exCmd locate; /* --excmd EX command used to locate tag */
bool recurse; /* -R recurse into directories */
sortType sorted; /* -u,--sort sort tags */
bool xref; /* -x generate xref output instead */
fmtElement *customXfmt; /* compiled code for --xformat=XFMT */
char *fileList; /* -L name of file containing names of files */
char *tagFileName; /* -o name of tags file */
stringList* headerExt; /* -h header extensions */
stringList* etagsInclude;/* --etags-include list of TAGS files to include*/
unsigned int tagFileFormat;/* --format tag file format (level) */
#ifdef HAVE_ICONV
char *inputEncoding; /* --input-encoding convert text into --output-encoding */
char *outputEncoding; /* --output-encoding write tags file as this encoding */
#endif
langType language; /* --lang specified language override */
bool followLinks; /* --link follow symbolic links? */
bool filter; /* --filter behave as filter: files in, tags out */
char* filterTerminator; /* --filter-terminator string to output */
tagRelative tagRelative; /* --tag-relative file paths relative to tag file */
int printTotals; /* --totals print cumulative statistics */
bool lineDirectives; /* --linedirectives process #line directives */
bool printLanguage; /* --print-language */
bool guessLanguageEagerly; /* --guess-language-eagerly|-G */
bool quiet; /* --quiet */
bool fatalWarnings; /* --_fatal-warnings */
unsigned int patternLengthLimit; /* --pattern-length-limit=N */
bool putFieldPrefix; /* --put-field-prefix */
unsigned int maxRecursionDepth; /* --maxdepth=<max-recursion-depth> */
bool fieldsReset; /* --fields=[^+-] */
enum interactiveMode { INTERACTIVE_NONE = 0,
INTERACTIVE_DEFAULT,
INTERACTIVE_SANDBOX, } interactive; /* --interactive */
#ifdef WIN32
enum filenameSepOp { FILENAME_SEP_NO_REPLACE = false,
FILENAME_SEP_USE_SLASH = true,
FILENAME_SEP_UNSET,
} useSlashAsFilenameSeparator; /* --use-slash-as-filename-separator */
#endif
#ifdef DEBUG
unsigned long breakLine;/* -b input line at which to call lineBreak() */
#endif
} optionValues;
typedef void (* mainLoopFunc) (cookedArgs *args, void *data);
/*
* GLOBAL VARIABLES
*/
extern CONST_OPTION optionValues Option;
/*
* FUNCTION PROTOTYPES
*/
extern void freeList (stringList** const pString);
extern void setDefaultTagFileName (void);
extern void checkOptions (void);
extern bool filesRequired (void);
extern void testEtagsInvocation (void);
extern cookedArgs* cArgNewFromString (const char* string);
extern cookedArgs* cArgNewFromArgv (char* const* const argv);
extern cookedArgs* cArgNewFromFile (FILE* const fp);
extern cookedArgs* cArgNewFromLineFile (FILE* const fp);
extern void cArgDelete (cookedArgs* const current);
extern bool cArgOff (cookedArgs* const current);
extern bool cArgIsOption (cookedArgs* const current);
extern const char* cArgItem (cookedArgs* const current);
extern void cArgForth (cookedArgs* const current);
extern bool isExcludedFile (const char* const name,
bool falseIfExceptionsAreDefeind);
extern bool isIncludeFile (const char *const fileName);
extern void parseCmdlineOptions (cookedArgs* const cargs);
extern void previewFirstOption (cookedArgs* const cargs);
extern void readOptionConfiguration (void);
extern void initOptions (void);
extern void freeOptionResources (void);
extern langType getLanguageComponentInOption (const char *const option,
const char *const prefix);
extern langType getLanguageComponentInOptionFull (const char *const option,
const char *const prefix, bool noPretending);
extern void processLanguageDefineOption (const char *const option, const char *const parameter);
extern bool processMapOption (const char *const option, const char *const parameter);
extern bool processParamOption (const char *const option, const char *const value);
extern bool processKinddefOption (const char *const option, const char *const parameter);
extern bool processKindsOption (const char *const option, const char *const parameter);
extern bool processExtradefOption (const char *const option, const char *const parameter);
extern bool processFielddefOption (const char *const option, const char *const parameter);
extern bool processAliasOption (const char *const option, const char *const parameter);
extern bool processTabledefOption (const char *const option, const char *const parameter);
#ifdef HAVE_ICONV
extern bool processLanguageEncodingOption (const char *const option, const char *const parameter);
#endif
extern bool processRoledefOption (const char *const option, const char *const parameter);
extern bool processScopesepOption (const char *const option, const char *const parameter);
extern bool processPreludeOption (const char *const option, const char *const parameter);
extern bool processSequelOption (const char *const option, const char *const parameter);
extern bool processPretendOption (const char *const option, const char *const parameter);
extern bool processRolesOption (const char *const option, const char *const parameter);
extern bool isDestinationStdout (void);
extern void setMainLoop (mainLoopFunc func, void *data);
extern bool ptagMakePatternLengthLimit (ptagDesc *pdesc, langType langType, const void *data);
#endif /* CTAGS_MAIN_OPTIONS_PRIVATE_H */

59
ctags/main/output-ctags.c Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 1998-2002, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
* External interface to entry.c
*/
#include "general.h" /* must always come first */
#include "entry.h"
#include "mio.h"
#include "options.h"
#include "output.h"
#include "read.h"
#include "ptag.h"
/* GEANY DIFF */
/* Dummy definitions of writers as we don't need them */
tagWriter etagsWriter = {
.writeEntry = NULL,
.writePtagEntry = NULL,
.preWriteEntry = NULL,
.postWriteEntry = NULL,
.useStdoutByDefault = false,
};
tagWriter ctagsWriter = {
.writeEntry = NULL,
.writePtagEntry = NULL,
.preWriteEntry = NULL,
.postWriteEntry = NULL,
.useStdoutByDefault = false,
};
tagWriter xrefWriter = {
.writeEntry = NULL,
.writePtagEntry = NULL,
.preWriteEntry = NULL,
.postWriteEntry = NULL,
.useStdoutByDefault = false,
};
tagWriter jsonWriter = {
.writeEntry = NULL,
.writePtagEntry = NULL,
.preWriteEntry = NULL,
.postWriteEntry = NULL,
.useStdoutByDefault = false,
};
extern bool ptagMakeJsonOutputVersion (ptagDesc *desc, void *data CTAGS_ATTR_UNUSED)
{
return false;
}
/* GEANY DIFF END */

50
ctags/main/output.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2016, Red Hat, Inc.
* Copyright (c) 2016, Masatake YAMATO
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#ifndef CTAGS_MAIN_OUTPUT_H
#define CTAGS_MAIN_OUTPUT_H
#include "general.h" /* must always come first */
/* Other than writeEntry can be NULL.
The value returned from preWriteEntry is passed to writeEntry,
and postWriteEntry. If a resource is allocated in
preWriteEntry, postWriteEntry should free it. */
struct sTagWriter;
typedef struct sTagWriter tagWriter;
struct sTagWriter {
int (* writeEntry) (MIO * mio, const tagEntryInfo *const tag, void *data);
int (* writePtagEntry) (MIO * mio, const ptagDesc *desc,
const char *const fileName,
const char *const pattern,
const char *const parserName, void *data);
void * (* preWriteEntry) (MIO * mio);
void (* postWriteEntry) (MIO * mio, const char* filename, void *data);
bool useStdoutByDefault;
};
extern void setTagWriter (tagWriter *tagWriter);
extern tagWriter etagsWriter;
extern tagWriter ctagsWriter;
extern tagWriter xrefWriter;
extern tagWriter jsonWriter;
extern bool outpuFormatUsedStdoutByDefault (void);
extern int makePatternStringCommon (const tagEntryInfo *const tag,
int putc_func (char , void *),
int puts_func (const char* , void *),
void *output);
extern void truncateTagLine (char *const line, const char *const token,
const bool discardNewline);
extern void abort_if_ferror(MIO *const fp);
extern bool ptagMakeJsonOutputVersion (ptagDesc *desc, void *data CTAGS_ATTR_UNUSED);
#endif

View File

@ -1,58 +0,0 @@
/*
*
* Copyright (c) 2016, Red Hat, Inc.
* Copyright (c) 2016, Masatake YAMATO
*
* Author: Masatake YAMATO <yamato@redhat.com>
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#include "general.h"
#include "param.h"
#include "param_p.h"
#include "parse.h"
#include <string.h>
extern struct colprintTable * paramColprintTableNew (void)
{
return colprintTableNew ("L:LANGUAGE", "L:NAME","L:DESCRIPTION", NULL);
}
extern void paramColprintAddParameter (struct colprintTable *table,
langType language,
const parameterHandlerTable *const paramHandler)
{
struct colprintLine *line = colprintTableGetNewLine(table);
colprintLineAppendColumnCString (line, getLanguageName (language));
colprintLineAppendColumnCString (line, paramHandler->name);
colprintLineAppendColumnCString (line, paramHandler->desc);
}
static int paramColprintCompareLines (struct colprintLine *a , struct colprintLine *b)
{
const char *a_parser = colprintLineGetColumn (a, 0);
const char *b_parser = colprintLineGetColumn (b, 0);
int r;
r = strcmp (a_parser, b_parser);
if (r != 0)
return r;
const char *a_name = colprintLineGetColumn (a, 1);
const char *b_name = colprintLineGetColumn (b, 1);
return strcmp(a_name, b_name);
}
extern void paramColprintTablePrint (struct colprintTable *table, bool noparser,
bool withListHeader, bool machinable, FILE *fp)
{
colprintTableSort (table, paramColprintCompareLines);
colprintTablePrint (table, noparser? 1: 0, withListHeader, machinable, fp);
}

View File

@ -1,38 +0,0 @@
/*
*
* Copyright (c) 2016, Red Hat, Inc.
* Copyright (c) 2016, Masatake YAMATO
*
* Author: Masatake YAMATO <yamato@redhat.com>
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#ifndef CTAGS_MAIN_PARAM_H
#define CTAGS_MAIN_PARAM_H
/*
* INCLUDE FILES
*/
#include "general.h"
#include "types.h"
/*
* DATA DECLARATIONS
*/
struct sParameterHandlerTable {
const char *name;
const char *desc;
void (* handleParameter) (langType lang, const char *name, const char *arg);
};
/*
* FUNCTION PROTOTYPES
*/
extern bool paramParserBool (const char *value, bool fallback,
const char *errWhat, const char *errCategory);
#endif /* CTAGS_MAIN_PARAM_H */

View File

@ -1,36 +0,0 @@
/*
*
* Copyright (c) 2016, Red Hat, Inc.
* Copyright (c) 2016, Masatake YAMATO
*
* Author: Masatake YAMATO <yamato@redhat.com>
*
* This source code is released for free distribution under the terms of the
* GNU General Public License version 2 or (at your option) any later version.
*
*/
#ifndef CTAGS_MAIN_PARAM_PRIVATE_H
#define CTAGS_MAIN_PARAM_PRIVATE_H
/*
* INCLUDE FILES
*/
#include "general.h"
#include "types.h"
#include "colprint_p.h"
/*
* FUNCTION PROTOTYPES
*/
extern void applyParameter (const langType language, const char *name, const char *args);
extern struct colprintTable * paramColprintTableNew (void);
extern void paramColprintAddParameter (struct colprintTable *table,
langType language,
const parameterHandlerTable *const paramHandler);
extern void paramColprintTablePrint (struct colprintTable *table, bool noparser,
bool withListHeader, bool machinable, FILE *fp);
#endif /* CTAGS_MAIN_PARAM_PRIVATE_H */

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More