Compare commits
1 Commits
master
...
libreapay-
Author | SHA1 | Date | |
---|---|---|---|
|
40fcc7984c |
228
.github/workflows/build.yml
vendored
228
.github/workflows/build.yml
vendored
@ -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
46
.gitignore
vendored
@ -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
43
.travis.yml
Normal 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
2
FUNDING.yml
Normal file
@ -0,0 +1,2 @@
|
||||
# These are supported funding model platforms
|
||||
liberapay: Geany
|
88
HACKING
88
HACKING
@ -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
404
INSTALL
@ -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.
|
||||
|
16
Makefile.am
16
Makefile.am
@ -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
44
NEWS
@ -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
48
README
@ -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
3
THANKS
@ -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
|
||||
|
67
autogen.sh
67
autogen.sh
@ -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
|
||||
|
||||
|
89
configure.ac
89
configure.ac
@ -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
|
||||
])
|
||||
|
@ -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
|
||||
|
3332
ctags/dsl/es.c
3332
ctags/dsl/es.c
File diff suppressed because it is too large
Load Diff
274
ctags/dsl/es.h
274
ctags/dsl/es.h
@ -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
@ -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
|
@ -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;
|
||||
}
|
@ -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 */
|
@ -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
@ -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
|
@ -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
@ -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
@ -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"
|
||||
;
|
@ -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);
|
||||
|
@ -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 */
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
144
ctags/main/ctags-api.c
Normal 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
57
ctags/main/ctags-api.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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
|
||||
|
1249
ctags/main/entry.c
1249
ctags/main/entry.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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 */
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
1703
ctags/main/field.c
1703
ctags/main/field.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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 */
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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: */
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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;
|
||||
}
|
@ -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 */
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
4045
ctags/main/lregex.c
4045
ctags/main/lregex.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
@ -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
1227
ctags/main/lxcmd.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
@ -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 */
|
@ -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
26
ctags/main/main.h
Normal 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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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;
|
||||
}
|
@ -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))
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
2774
ctags/main/options.c
2774
ctags/main/options.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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
59
ctags/main/output-ctags.c
Normal 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
50
ctags/main/output.h
Normal 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
|
@ -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);
|
||||
}
|
@ -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 */
|
@ -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 */
|
4188
ctags/main/parse.c
4188
ctags/main/parse.c
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
Loading…
x
Reference in New Issue
Block a user