ctags.rb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -0
- data/Rakefile +23 -0
- data/ctags.rb.gemspec +23 -0
- data/ext/.gitignore +3 -0
- data/ext/extconf.rb +15 -0
- data/ext/vendor/exuberant-ctags/.gitignore +6 -0
- data/ext/vendor/exuberant-ctags/.indent.pro +31 -0
- data/ext/vendor/exuberant-ctags/COPYING +340 -0
- data/ext/vendor/exuberant-ctags/EXTENDING.html +386 -0
- data/ext/vendor/exuberant-ctags/FAQ +371 -0
- data/ext/vendor/exuberant-ctags/INSTALL +215 -0
- data/ext/vendor/exuberant-ctags/INSTALL.oth +73 -0
- data/ext/vendor/exuberant-ctags/MAINTAINERS +88 -0
- data/ext/vendor/exuberant-ctags/Makefile.in +222 -0
- data/ext/vendor/exuberant-ctags/NEWS +871 -0
- data/ext/vendor/exuberant-ctags/README +73 -0
- data/ext/vendor/exuberant-ctags/ant.c +42 -0
- data/ext/vendor/exuberant-ctags/argproc.c +505 -0
- data/ext/vendor/exuberant-ctags/args.c +274 -0
- data/ext/vendor/exuberant-ctags/args.h +63 -0
- data/ext/vendor/exuberant-ctags/asm.c +387 -0
- data/ext/vendor/exuberant-ctags/asp.c +328 -0
- data/ext/vendor/exuberant-ctags/awk.c +81 -0
- data/ext/vendor/exuberant-ctags/basic.c +203 -0
- data/ext/vendor/exuberant-ctags/beta.c +321 -0
- data/ext/vendor/exuberant-ctags/c.c +2932 -0
- data/ext/vendor/exuberant-ctags/cobol.c +50 -0
- data/ext/vendor/exuberant-ctags/config.h.in +277 -0
- data/ext/vendor/exuberant-ctags/configure +7704 -0
- data/ext/vendor/exuberant-ctags/configure.ac +532 -0
- data/ext/vendor/exuberant-ctags/ctags.1 +1186 -0
- data/ext/vendor/exuberant-ctags/ctags.h +28 -0
- data/ext/vendor/exuberant-ctags/ctags.html +2087 -0
- data/ext/vendor/exuberant-ctags/ctags.spec +40 -0
- data/ext/vendor/exuberant-ctags/debug.c +113 -0
- data/ext/vendor/exuberant-ctags/debug.h +70 -0
- data/ext/vendor/exuberant-ctags/descrip.mms +68 -0
- data/ext/vendor/exuberant-ctags/dosbatch.c +42 -0
- data/ext/vendor/exuberant-ctags/e_amiga.h +24 -0
- data/ext/vendor/exuberant-ctags/e_djgpp.h +47 -0
- data/ext/vendor/exuberant-ctags/e_mac.h +143 -0
- data/ext/vendor/exuberant-ctags/e_msoft.h +76 -0
- data/ext/vendor/exuberant-ctags/e_os2.h +37 -0
- data/ext/vendor/exuberant-ctags/e_qdos.h +34 -0
- data/ext/vendor/exuberant-ctags/e_riscos.h +58 -0
- data/ext/vendor/exuberant-ctags/e_vms.h +31 -0
- data/ext/vendor/exuberant-ctags/eiffel.c +1352 -0
- data/ext/vendor/exuberant-ctags/entry.c +847 -0
- data/ext/vendor/exuberant-ctags/entry.h +103 -0
- data/ext/vendor/exuberant-ctags/erlang.c +189 -0
- data/ext/vendor/exuberant-ctags/flex.c +2243 -0
- data/ext/vendor/exuberant-ctags/fortran.c +2197 -0
- data/ext/vendor/exuberant-ctags/general.h +127 -0
- data/ext/vendor/exuberant-ctags/get.c +669 -0
- data/ext/vendor/exuberant-ctags/get.h +50 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/all-wcprops +47 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/entries +112 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/README.txt.svn-base +5 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regcomp.c.svn-base +3818 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.c.svn-base +74 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.h.svn-base +575 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.c.svn-base +1713 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.h.svn-base +773 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regexec.c.svn-base +4338 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/README.txt +5 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regcomp.c +3818 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex.c +74 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex.h +575 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.c +1713 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.h +773 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regexec.c +4338 -0
- data/ext/vendor/exuberant-ctags/html.c +49 -0
- data/ext/vendor/exuberant-ctags/jscript.c +1572 -0
- data/ext/vendor/exuberant-ctags/keyword.c +258 -0
- data/ext/vendor/exuberant-ctags/keyword.h +34 -0
- data/ext/vendor/exuberant-ctags/lisp.c +139 -0
- data/ext/vendor/exuberant-ctags/lregex.c +704 -0
- data/ext/vendor/exuberant-ctags/lua.c +133 -0
- data/ext/vendor/exuberant-ctags/mac.c +273 -0
- data/ext/vendor/exuberant-ctags/magic.diff +21 -0
- data/ext/vendor/exuberant-ctags/main.c +584 -0
- data/ext/vendor/exuberant-ctags/main.h +32 -0
- data/ext/vendor/exuberant-ctags/maintainer.mak +476 -0
- data/ext/vendor/exuberant-ctags/make.c +217 -0
- data/ext/vendor/exuberant-ctags/matlab.c +44 -0
- data/ext/vendor/exuberant-ctags/mk_bc3.mak +46 -0
- data/ext/vendor/exuberant-ctags/mk_bc5.mak +49 -0
- data/ext/vendor/exuberant-ctags/mk_djg.mak +18 -0
- data/ext/vendor/exuberant-ctags/mk_manx.mak +65 -0
- data/ext/vendor/exuberant-ctags/mk_mingw.mak +31 -0
- data/ext/vendor/exuberant-ctags/mk_mpw.mak +130 -0
- data/ext/vendor/exuberant-ctags/mk_mvc.mak +40 -0
- data/ext/vendor/exuberant-ctags/mk_os2.mak +104 -0
- data/ext/vendor/exuberant-ctags/mk_qdos.mak +100 -0
- data/ext/vendor/exuberant-ctags/mk_sas.mak +63 -0
- data/ext/vendor/exuberant-ctags/mkinstalldirs +40 -0
- data/ext/vendor/exuberant-ctags/ocaml.c +1842 -0
- data/ext/vendor/exuberant-ctags/options.c +1842 -0
- data/ext/vendor/exuberant-ctags/options.h +155 -0
- data/ext/vendor/exuberant-ctags/parse.c +677 -0
- data/ext/vendor/exuberant-ctags/parse.h +129 -0
- data/ext/vendor/exuberant-ctags/parsers.h +63 -0
- data/ext/vendor/exuberant-ctags/pascal.c +267 -0
- data/ext/vendor/exuberant-ctags/perl.c +382 -0
- data/ext/vendor/exuberant-ctags/php.c +237 -0
- data/ext/vendor/exuberant-ctags/python.c +771 -0
- data/ext/vendor/exuberant-ctags/qdos.c +106 -0
- data/ext/vendor/exuberant-ctags/read.c +569 -0
- data/ext/vendor/exuberant-ctags/read.h +116 -0
- data/ext/vendor/exuberant-ctags/readtags.c +959 -0
- data/ext/vendor/exuberant-ctags/readtags.h +252 -0
- data/ext/vendor/exuberant-ctags/rexx.c +39 -0
- data/ext/vendor/exuberant-ctags/routines.c +891 -0
- data/ext/vendor/exuberant-ctags/routines.h +134 -0
- data/ext/vendor/exuberant-ctags/ruby.c +408 -0
- data/ext/vendor/exuberant-ctags/scheme.c +111 -0
- data/ext/vendor/exuberant-ctags/sh.c +115 -0
- data/ext/vendor/exuberant-ctags/slang.c +41 -0
- data/ext/vendor/exuberant-ctags/sml.c +212 -0
- data/ext/vendor/exuberant-ctags/sort.c +230 -0
- data/ext/vendor/exuberant-ctags/sort.h +32 -0
- data/ext/vendor/exuberant-ctags/source.mak +122 -0
- data/ext/vendor/exuberant-ctags/sql.c +2112 -0
- data/ext/vendor/exuberant-ctags/strlist.c +281 -0
- data/ext/vendor/exuberant-ctags/strlist.h +54 -0
- data/ext/vendor/exuberant-ctags/tcl.c +116 -0
- data/ext/vendor/exuberant-ctags/tex.c +524 -0
- data/ext/vendor/exuberant-ctags/verilog.c +340 -0
- data/ext/vendor/exuberant-ctags/vhdl.c +835 -0
- data/ext/vendor/exuberant-ctags/vim.c +636 -0
- data/ext/vendor/exuberant-ctags/vstring.c +232 -0
- data/ext/vendor/exuberant-ctags/vstring.h +85 -0
- data/ext/vendor/exuberant-ctags/yacc.c +40 -0
- data/lib/ctags/exuberant.rb +45 -0
- data/lib/ctags/version.rb +3 -0
- data/lib/ctags.rb +6 -0
- data/test/test_ctags.rb +24 -0
- metadata +233 -0
|
@@ -0,0 +1,847 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* $Id: entry.c 443 2006-05-30 04:37:13Z darren $
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 1996-2002, Darren Hiebert
|
|
5
|
+
*
|
|
6
|
+
* This source code is released for free distribution under the terms of the
|
|
7
|
+
* GNU General Public License.
|
|
8
|
+
*
|
|
9
|
+
* This module contains functions for creating tag entries.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* INCLUDE FILES
|
|
14
|
+
*/
|
|
15
|
+
#include "general.h" /* must always come first */
|
|
16
|
+
|
|
17
|
+
#include <string.h>
|
|
18
|
+
#include <ctype.h> /* to define isspace () */
|
|
19
|
+
#include <errno.h>
|
|
20
|
+
|
|
21
|
+
#if defined (HAVE_SYS_TYPES_H)
|
|
22
|
+
# include <sys/types.h> /* to declare off_t on some hosts */
|
|
23
|
+
#endif
|
|
24
|
+
#if defined (HAVE_TYPES_H)
|
|
25
|
+
# include <types.h> /* to declare off_t on some hosts */
|
|
26
|
+
#endif
|
|
27
|
+
#if defined (HAVE_UNISTD_H)
|
|
28
|
+
# include <unistd.h> /* to declare close (), ftruncate (), truncate () */
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
/* These header files provide for the functions necessary to do file
|
|
32
|
+
* truncation.
|
|
33
|
+
*/
|
|
34
|
+
#ifdef HAVE_FCNTL_H
|
|
35
|
+
# include <fcntl.h>
|
|
36
|
+
#endif
|
|
37
|
+
#ifdef HAVE_IO_H
|
|
38
|
+
# include <io.h>
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
#include "debug.h"
|
|
42
|
+
#include "ctags.h"
|
|
43
|
+
#include "entry.h"
|
|
44
|
+
#include "main.h"
|
|
45
|
+
#include "options.h"
|
|
46
|
+
#include "read.h"
|
|
47
|
+
#include "routines.h"
|
|
48
|
+
#include "sort.h"
|
|
49
|
+
#include "strlist.h"
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
* MACROS
|
|
53
|
+
*/
|
|
54
|
+
#define PSEUDO_TAG_PREFIX "!_"
|
|
55
|
+
|
|
56
|
+
#define includeExtensionFlags() (Option.tagFileFormat > 1)
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
* Portability defines
|
|
60
|
+
*/
|
|
61
|
+
#if !defined(HAVE_TRUNCATE) && !defined(HAVE_FTRUNCATE) && !defined(HAVE_CHSIZE)
|
|
62
|
+
# define USE_REPLACEMENT_TRUNCATE
|
|
63
|
+
#endif
|
|
64
|
+
|
|
65
|
+
/* Hack for rediculous practice of Microsoft Visual C++.
|
|
66
|
+
*/
|
|
67
|
+
#if defined (WIN32) && defined (_MSC_VER)
|
|
68
|
+
# define chsize _chsize
|
|
69
|
+
# define open _open
|
|
70
|
+
# define close _close
|
|
71
|
+
# define O_RDWR _O_RDWR
|
|
72
|
+
#endif
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
* DATA DEFINITIONS
|
|
76
|
+
*/
|
|
77
|
+
|
|
78
|
+
tagFile TagFile = {
|
|
79
|
+
NULL, /* tag file name */
|
|
80
|
+
NULL, /* tag file directory (absolute) */
|
|
81
|
+
NULL, /* file pointer */
|
|
82
|
+
{ 0, 0 }, /* numTags */
|
|
83
|
+
{ 0, 0, 0 }, /* max */
|
|
84
|
+
{ NULL, NULL, 0 }, /* etags */
|
|
85
|
+
NULL /* vLine */
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
static boolean TagsToStdout = FALSE;
|
|
89
|
+
|
|
90
|
+
/*
|
|
91
|
+
* FUNCTION PROTOTYPES
|
|
92
|
+
*/
|
|
93
|
+
#ifdef NEED_PROTO_TRUNCATE
|
|
94
|
+
extern int truncate (const char *path, off_t length);
|
|
95
|
+
#endif
|
|
96
|
+
|
|
97
|
+
#ifdef NEED_PROTO_FTRUNCATE
|
|
98
|
+
extern int ftruncate (int fd, off_t length);
|
|
99
|
+
#endif
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* FUNCTION DEFINITIONS
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
extern void freeTagFileResources (void)
|
|
106
|
+
{
|
|
107
|
+
if (TagFile.directory != NULL)
|
|
108
|
+
eFree (TagFile.directory);
|
|
109
|
+
vStringDelete (TagFile.vLine);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
extern const char *tagFileName (void)
|
|
113
|
+
{
|
|
114
|
+
return TagFile.name;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
* Pseudo tag support
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
static void rememberMaxLengths (const size_t nameLength, const size_t lineLength)
|
|
122
|
+
{
|
|
123
|
+
if (nameLength > TagFile.max.tag)
|
|
124
|
+
TagFile.max.tag = nameLength;
|
|
125
|
+
|
|
126
|
+
if (lineLength > TagFile.max.line)
|
|
127
|
+
TagFile.max.line = lineLength;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
static void writePseudoTag (
|
|
131
|
+
const char *const tagName,
|
|
132
|
+
const char *const fileName,
|
|
133
|
+
const char *const pattern)
|
|
134
|
+
{
|
|
135
|
+
const int length = fprintf (
|
|
136
|
+
TagFile.fp, "%s%s\t%s\t/%s/\n",
|
|
137
|
+
PSEUDO_TAG_PREFIX, tagName, fileName, pattern);
|
|
138
|
+
++TagFile.numTags.added;
|
|
139
|
+
rememberMaxLengths (strlen (tagName), (size_t) length);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
static void addPseudoTags (void)
|
|
143
|
+
{
|
|
144
|
+
if (! Option.xref)
|
|
145
|
+
{
|
|
146
|
+
char format [11];
|
|
147
|
+
const char *formatComment = "unknown format";
|
|
148
|
+
|
|
149
|
+
sprintf (format, "%u", Option.tagFileFormat);
|
|
150
|
+
|
|
151
|
+
if (Option.tagFileFormat == 1)
|
|
152
|
+
formatComment = "original ctags format";
|
|
153
|
+
else if (Option.tagFileFormat == 2)
|
|
154
|
+
formatComment =
|
|
155
|
+
"extended format; --format=1 will not append ;\" to lines";
|
|
156
|
+
|
|
157
|
+
writePseudoTag ("TAG_FILE_FORMAT", format, formatComment);
|
|
158
|
+
writePseudoTag ("TAG_FILE_SORTED",
|
|
159
|
+
Option.sorted == SO_FOLDSORTED ? "2" :
|
|
160
|
+
(Option.sorted == SO_SORTED ? "1" : "0"),
|
|
161
|
+
"0=unsorted, 1=sorted, 2=foldcase");
|
|
162
|
+
writePseudoTag ("TAG_PROGRAM_AUTHOR", AUTHOR_NAME, AUTHOR_EMAIL);
|
|
163
|
+
writePseudoTag ("TAG_PROGRAM_NAME", PROGRAM_NAME, "");
|
|
164
|
+
writePseudoTag ("TAG_PROGRAM_URL", PROGRAM_URL, "official site");
|
|
165
|
+
writePseudoTag ("TAG_PROGRAM_VERSION", PROGRAM_VERSION, "");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
static void updateSortedFlag (
|
|
170
|
+
const char *const line, FILE *const fp, fpos_t startOfLine)
|
|
171
|
+
{
|
|
172
|
+
const char *const tab = strchr (line, '\t');
|
|
173
|
+
|
|
174
|
+
if (tab != NULL)
|
|
175
|
+
{
|
|
176
|
+
const long boolOffset = tab - line + 1; /* where it should be */
|
|
177
|
+
|
|
178
|
+
if (line [boolOffset] == '0' || line [boolOffset] == '1')
|
|
179
|
+
{
|
|
180
|
+
fpos_t nextLine;
|
|
181
|
+
|
|
182
|
+
if (fgetpos (fp, &nextLine) == -1 || fsetpos (fp, &startOfLine) == -1)
|
|
183
|
+
error (WARNING, "Failed to update 'sorted' pseudo-tag");
|
|
184
|
+
else
|
|
185
|
+
{
|
|
186
|
+
fpos_t flagLocation;
|
|
187
|
+
int c, d;
|
|
188
|
+
|
|
189
|
+
do
|
|
190
|
+
c = fgetc (fp);
|
|
191
|
+
while (c != '\t' && c != '\n');
|
|
192
|
+
fgetpos (fp, &flagLocation);
|
|
193
|
+
d = fgetc (fp);
|
|
194
|
+
if (c == '\t' && (d == '0' || d == '1') &&
|
|
195
|
+
d != (int) Option.sorted)
|
|
196
|
+
{
|
|
197
|
+
fsetpos (fp, &flagLocation);
|
|
198
|
+
fputc (Option.sorted == SO_FOLDSORTED ? '2' :
|
|
199
|
+
(Option.sorted == SO_SORTED ? '1' : '0'), fp);
|
|
200
|
+
}
|
|
201
|
+
fsetpos (fp, &nextLine);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* Look through all line beginning with "!_TAG_FILE", and update those which
|
|
208
|
+
* require it.
|
|
209
|
+
*/
|
|
210
|
+
static long unsigned int updatePseudoTags (FILE *const fp)
|
|
211
|
+
{
|
|
212
|
+
enum { maxEntryLength = 20 };
|
|
213
|
+
char entry [maxEntryLength + 1];
|
|
214
|
+
unsigned long linesRead = 0;
|
|
215
|
+
fpos_t startOfLine;
|
|
216
|
+
size_t entryLength;
|
|
217
|
+
const char *line;
|
|
218
|
+
|
|
219
|
+
sprintf (entry, "%sTAG_FILE", PSEUDO_TAG_PREFIX);
|
|
220
|
+
entryLength = strlen (entry);
|
|
221
|
+
Assert (entryLength < maxEntryLength);
|
|
222
|
+
|
|
223
|
+
fgetpos (fp, &startOfLine);
|
|
224
|
+
line = readLine (TagFile.vLine, fp);
|
|
225
|
+
while (line != NULL && line [0] == entry [0])
|
|
226
|
+
{
|
|
227
|
+
++linesRead;
|
|
228
|
+
if (strncmp (line, entry, entryLength) == 0)
|
|
229
|
+
{
|
|
230
|
+
char tab, classType [16];
|
|
231
|
+
|
|
232
|
+
if (sscanf (line + entryLength, "%15s%c", classType, &tab) == 2 &&
|
|
233
|
+
tab == '\t')
|
|
234
|
+
{
|
|
235
|
+
if (strcmp (classType, "_SORTED") == 0)
|
|
236
|
+
updateSortedFlag (line, fp, startOfLine);
|
|
237
|
+
}
|
|
238
|
+
fgetpos (fp, &startOfLine);
|
|
239
|
+
}
|
|
240
|
+
line = readLine (TagFile.vLine, fp);
|
|
241
|
+
}
|
|
242
|
+
while (line != NULL) /* skip to end of file */
|
|
243
|
+
{
|
|
244
|
+
++linesRead;
|
|
245
|
+
line = readLine (TagFile.vLine, fp);
|
|
246
|
+
}
|
|
247
|
+
return linesRead;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/*
|
|
251
|
+
* Tag file management
|
|
252
|
+
*/
|
|
253
|
+
|
|
254
|
+
static boolean isValidTagAddress (const char *const excmd)
|
|
255
|
+
{
|
|
256
|
+
boolean isValid = FALSE;
|
|
257
|
+
|
|
258
|
+
if (strchr ("/?", excmd [0]) != NULL)
|
|
259
|
+
isValid = TRUE;
|
|
260
|
+
else
|
|
261
|
+
{
|
|
262
|
+
char *address = xMalloc (strlen (excmd) + 1, char);
|
|
263
|
+
if (sscanf (excmd, "%[^;\n]", address) == 1 &&
|
|
264
|
+
strspn (address,"0123456789") == strlen (address))
|
|
265
|
+
isValid = TRUE;
|
|
266
|
+
eFree (address);
|
|
267
|
+
}
|
|
268
|
+
return isValid;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
static boolean isCtagsLine (const char *const line)
|
|
272
|
+
{
|
|
273
|
+
enum fieldList { TAG, TAB1, SRC_FILE, TAB2, EXCMD, NUM_FIELDS };
|
|
274
|
+
boolean ok = FALSE; /* we assume not unless confirmed */
|
|
275
|
+
const size_t fieldLength = strlen (line) + 1;
|
|
276
|
+
char *const fields = xMalloc (NUM_FIELDS * fieldLength, char);
|
|
277
|
+
|
|
278
|
+
if (fields == NULL)
|
|
279
|
+
error (FATAL, "Cannot analyze tag file");
|
|
280
|
+
else
|
|
281
|
+
{
|
|
282
|
+
#define field(x) (fields + ((size_t) (x) * fieldLength))
|
|
283
|
+
|
|
284
|
+
const int numFields = sscanf (
|
|
285
|
+
line, "%[^\t]%[\t]%[^\t]%[\t]%[^\r\n]",
|
|
286
|
+
field (TAG), field (TAB1), field (SRC_FILE),
|
|
287
|
+
field (TAB2), field (EXCMD));
|
|
288
|
+
|
|
289
|
+
/* There must be exactly five fields: two tab fields containing
|
|
290
|
+
* exactly one tab each, the tag must not begin with "#", and the
|
|
291
|
+
* file name should not end with ";", and the excmd must be
|
|
292
|
+
* accceptable.
|
|
293
|
+
*
|
|
294
|
+
* These conditions will reject tag-looking lines like:
|
|
295
|
+
* int a; <C-comment>
|
|
296
|
+
* #define LABEL <C-comment>
|
|
297
|
+
*/
|
|
298
|
+
if (numFields == NUM_FIELDS &&
|
|
299
|
+
strlen (field (TAB1)) == 1 &&
|
|
300
|
+
strlen (field (TAB2)) == 1 &&
|
|
301
|
+
field (TAG) [0] != '#' &&
|
|
302
|
+
field (SRC_FILE) [strlen (field (SRC_FILE)) - 1] != ';' &&
|
|
303
|
+
isValidTagAddress (field (EXCMD)))
|
|
304
|
+
ok = TRUE;
|
|
305
|
+
|
|
306
|
+
eFree (fields);
|
|
307
|
+
}
|
|
308
|
+
return ok;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
static boolean isEtagsLine (const char *const line)
|
|
312
|
+
{
|
|
313
|
+
boolean result = FALSE;
|
|
314
|
+
if (line [0] == '\f')
|
|
315
|
+
result = (boolean) (line [1] == '\n' || line [1] == '\r');
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
static boolean isTagFile (const char *const filename)
|
|
320
|
+
{
|
|
321
|
+
boolean ok = FALSE; /* we assume not unless confirmed */
|
|
322
|
+
FILE *const fp = fopen (filename, "rb");
|
|
323
|
+
|
|
324
|
+
if (fp == NULL && errno == ENOENT)
|
|
325
|
+
ok = TRUE;
|
|
326
|
+
else if (fp != NULL)
|
|
327
|
+
{
|
|
328
|
+
const char *line = readLine (TagFile.vLine, fp);
|
|
329
|
+
|
|
330
|
+
if (line == NULL)
|
|
331
|
+
ok = TRUE;
|
|
332
|
+
else
|
|
333
|
+
ok = (boolean) (isCtagsLine (line) || isEtagsLine (line));
|
|
334
|
+
fclose (fp);
|
|
335
|
+
}
|
|
336
|
+
return ok;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
extern void copyBytes (FILE* const fromFp, FILE* const toFp, const long size)
|
|
340
|
+
{
|
|
341
|
+
enum { BufferSize = 1000 };
|
|
342
|
+
long toRead, numRead;
|
|
343
|
+
char* buffer = xMalloc (BufferSize, char);
|
|
344
|
+
long remaining = size;
|
|
345
|
+
do
|
|
346
|
+
{
|
|
347
|
+
toRead = (0 < remaining && remaining < BufferSize) ?
|
|
348
|
+
remaining : (long) BufferSize;
|
|
349
|
+
numRead = fread (buffer, (size_t) 1, (size_t) toRead, fromFp);
|
|
350
|
+
if (fwrite (buffer, (size_t)1, (size_t)numRead, toFp) < (size_t)numRead)
|
|
351
|
+
error (FATAL | PERROR, "cannot complete write");
|
|
352
|
+
if (remaining > 0)
|
|
353
|
+
remaining -= numRead;
|
|
354
|
+
} while (numRead == toRead && remaining != 0);
|
|
355
|
+
eFree (buffer);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
extern void copyFile (const char *const from, const char *const to, const long size)
|
|
359
|
+
{
|
|
360
|
+
FILE* const fromFp = fopen (from, "rb");
|
|
361
|
+
if (fromFp == NULL)
|
|
362
|
+
error (FATAL | PERROR, "cannot open file to copy");
|
|
363
|
+
else
|
|
364
|
+
{
|
|
365
|
+
FILE* const toFp = fopen (to, "wb");
|
|
366
|
+
if (toFp == NULL)
|
|
367
|
+
error (FATAL | PERROR, "cannot open copy destination");
|
|
368
|
+
else
|
|
369
|
+
{
|
|
370
|
+
copyBytes (fromFp, toFp, size);
|
|
371
|
+
fclose (toFp);
|
|
372
|
+
}
|
|
373
|
+
fclose (fromFp);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
extern void openTagFile (void)
|
|
378
|
+
{
|
|
379
|
+
setDefaultTagFileName ();
|
|
380
|
+
TagsToStdout = isDestinationStdout ();
|
|
381
|
+
|
|
382
|
+
if (TagFile.vLine == NULL)
|
|
383
|
+
TagFile.vLine = vStringNew ();
|
|
384
|
+
|
|
385
|
+
/* Open the tags file.
|
|
386
|
+
*/
|
|
387
|
+
if (TagsToStdout)
|
|
388
|
+
TagFile.fp = tempFile ("w", &TagFile.name);
|
|
389
|
+
else
|
|
390
|
+
{
|
|
391
|
+
boolean fileExists;
|
|
392
|
+
|
|
393
|
+
setDefaultTagFileName ();
|
|
394
|
+
TagFile.name = eStrdup (Option.tagFileName);
|
|
395
|
+
fileExists = doesFileExist (TagFile.name);
|
|
396
|
+
if (fileExists && ! isTagFile (TagFile.name))
|
|
397
|
+
error (FATAL,
|
|
398
|
+
"\"%s\" doesn't look like a tag file; I refuse to overwrite it.",
|
|
399
|
+
TagFile.name);
|
|
400
|
+
|
|
401
|
+
if (Option.etags)
|
|
402
|
+
{
|
|
403
|
+
if (Option.append && fileExists)
|
|
404
|
+
TagFile.fp = fopen (TagFile.name, "a+b");
|
|
405
|
+
else
|
|
406
|
+
TagFile.fp = fopen (TagFile.name, "w+b");
|
|
407
|
+
}
|
|
408
|
+
else
|
|
409
|
+
{
|
|
410
|
+
if (Option.append && fileExists)
|
|
411
|
+
{
|
|
412
|
+
TagFile.fp = fopen (TagFile.name, "r+");
|
|
413
|
+
if (TagFile.fp != NULL)
|
|
414
|
+
{
|
|
415
|
+
TagFile.numTags.prev = updatePseudoTags (TagFile.fp);
|
|
416
|
+
fclose (TagFile.fp);
|
|
417
|
+
TagFile.fp = fopen (TagFile.name, "a+");
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
else
|
|
421
|
+
{
|
|
422
|
+
TagFile.fp = fopen (TagFile.name, "w");
|
|
423
|
+
if (TagFile.fp != NULL)
|
|
424
|
+
addPseudoTags ();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (TagFile.fp == NULL)
|
|
428
|
+
{
|
|
429
|
+
error (FATAL | PERROR, "cannot open tag file");
|
|
430
|
+
exit (1);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
if (TagsToStdout)
|
|
434
|
+
TagFile.directory = eStrdup (CurrentDirectory);
|
|
435
|
+
else
|
|
436
|
+
TagFile.directory = absoluteDirname (TagFile.name);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
#ifdef USE_REPLACEMENT_TRUNCATE
|
|
440
|
+
|
|
441
|
+
/* Replacement for missing library function.
|
|
442
|
+
*/
|
|
443
|
+
static int replacementTruncate (const char *const name, const long size)
|
|
444
|
+
{
|
|
445
|
+
char *tempName = NULL;
|
|
446
|
+
FILE *fp = tempFile ("w", &tempName);
|
|
447
|
+
fclose (fp);
|
|
448
|
+
copyFile (name, tempName, size);
|
|
449
|
+
copyFile (tempName, name, WHOLE_FILE);
|
|
450
|
+
remove (tempName);
|
|
451
|
+
eFree (tempName);
|
|
452
|
+
|
|
453
|
+
return 0;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
#endif
|
|
457
|
+
|
|
458
|
+
static void sortTagFile (void)
|
|
459
|
+
{
|
|
460
|
+
if (TagFile.numTags.added > 0L)
|
|
461
|
+
{
|
|
462
|
+
if (Option.sorted != SO_UNSORTED)
|
|
463
|
+
{
|
|
464
|
+
verbose ("sorting tag file\n");
|
|
465
|
+
#ifdef EXTERNAL_SORT
|
|
466
|
+
externalSortTags (TagsToStdout);
|
|
467
|
+
#else
|
|
468
|
+
internalSortTags (TagsToStdout);
|
|
469
|
+
#endif
|
|
470
|
+
}
|
|
471
|
+
else if (TagsToStdout)
|
|
472
|
+
catFile (tagFileName ());
|
|
473
|
+
}
|
|
474
|
+
if (TagsToStdout)
|
|
475
|
+
remove (tagFileName ()); /* remove temporary file */
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
static void resizeTagFile (const long newSize)
|
|
479
|
+
{
|
|
480
|
+
int result;
|
|
481
|
+
|
|
482
|
+
#ifdef USE_REPLACEMENT_TRUNCATE
|
|
483
|
+
result = replacementTruncate (TagFile.name, newSize);
|
|
484
|
+
#else
|
|
485
|
+
# ifdef HAVE_TRUNCATE
|
|
486
|
+
result = truncate (TagFile.name, (off_t) newSize);
|
|
487
|
+
# else
|
|
488
|
+
const int fd = open (TagFile.name, O_RDWR);
|
|
489
|
+
|
|
490
|
+
if (fd == -1)
|
|
491
|
+
result = -1;
|
|
492
|
+
else
|
|
493
|
+
{
|
|
494
|
+
# ifdef HAVE_FTRUNCATE
|
|
495
|
+
result = ftruncate (fd, (off_t) newSize);
|
|
496
|
+
# else
|
|
497
|
+
# ifdef HAVE_CHSIZE
|
|
498
|
+
result = chsize (fd, newSize);
|
|
499
|
+
# endif
|
|
500
|
+
# endif
|
|
501
|
+
close (fd);
|
|
502
|
+
}
|
|
503
|
+
# endif
|
|
504
|
+
#endif
|
|
505
|
+
if (result == -1)
|
|
506
|
+
fprintf (errout, "Cannot shorten tag file: errno = %d\n", errno);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
static void writeEtagsIncludes (FILE *const fp)
|
|
510
|
+
{
|
|
511
|
+
if (Option.etagsInclude)
|
|
512
|
+
{
|
|
513
|
+
unsigned int i;
|
|
514
|
+
for (i = 0 ; i < stringListCount (Option.etagsInclude) ; ++i)
|
|
515
|
+
{
|
|
516
|
+
vString *item = stringListItem (Option.etagsInclude, i);
|
|
517
|
+
fprintf (fp, "\f\n%s,include\n", vStringValue (item));
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
extern void closeTagFile (const boolean resize)
|
|
523
|
+
{
|
|
524
|
+
long desiredSize, size;
|
|
525
|
+
|
|
526
|
+
if (Option.etags)
|
|
527
|
+
writeEtagsIncludes (TagFile.fp);
|
|
528
|
+
desiredSize = ftell (TagFile.fp);
|
|
529
|
+
fseek (TagFile.fp, 0L, SEEK_END);
|
|
530
|
+
size = ftell (TagFile.fp);
|
|
531
|
+
fclose (TagFile.fp);
|
|
532
|
+
if (resize && desiredSize < size)
|
|
533
|
+
{
|
|
534
|
+
DebugStatement (
|
|
535
|
+
debugPrintf (DEBUG_STATUS, "shrinking %s from %ld to %ld bytes\n",
|
|
536
|
+
TagFile.name, size, desiredSize); )
|
|
537
|
+
resizeTagFile (desiredSize);
|
|
538
|
+
}
|
|
539
|
+
sortTagFile ();
|
|
540
|
+
eFree (TagFile.name);
|
|
541
|
+
TagFile.name = NULL;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
extern void beginEtagsFile (void)
|
|
545
|
+
{
|
|
546
|
+
TagFile.etags.fp = tempFile ("w+b", &TagFile.etags.name);
|
|
547
|
+
TagFile.etags.byteCount = 0;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
extern void endEtagsFile (const char *const name)
|
|
551
|
+
{
|
|
552
|
+
const char *line;
|
|
553
|
+
|
|
554
|
+
fprintf (TagFile.fp, "\f\n%s,%ld\n", name, (long) TagFile.etags.byteCount);
|
|
555
|
+
if (TagFile.etags.fp != NULL)
|
|
556
|
+
{
|
|
557
|
+
rewind (TagFile.etags.fp);
|
|
558
|
+
while ((line = readLine (TagFile.vLine, TagFile.etags.fp)) != NULL)
|
|
559
|
+
fputs (line, TagFile.fp);
|
|
560
|
+
fclose (TagFile.etags.fp);
|
|
561
|
+
remove (TagFile.etags.name);
|
|
562
|
+
eFree (TagFile.etags.name);
|
|
563
|
+
TagFile.etags.fp = NULL;
|
|
564
|
+
TagFile.etags.name = NULL;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/*
|
|
569
|
+
* Tag entry management
|
|
570
|
+
*/
|
|
571
|
+
|
|
572
|
+
/* This function copies the current line out to a specified file. It has no
|
|
573
|
+
* effect on the fileGetc () function. During copying, any '\' characters
|
|
574
|
+
* are doubled and a leading '^' or trailing '$' is also quoted. End of line
|
|
575
|
+
* characters (line feed or carriage return) are dropped.
|
|
576
|
+
*/
|
|
577
|
+
static size_t writeSourceLine (FILE *const fp, const char *const line)
|
|
578
|
+
{
|
|
579
|
+
size_t length = 0;
|
|
580
|
+
const char *p;
|
|
581
|
+
|
|
582
|
+
/* Write everything up to, but not including, a line end character.
|
|
583
|
+
*/
|
|
584
|
+
for (p = line ; *p != '\0' ; ++p)
|
|
585
|
+
{
|
|
586
|
+
const int next = *(p + 1);
|
|
587
|
+
const int c = *p;
|
|
588
|
+
|
|
589
|
+
if (c == CRETURN || c == NEWLINE)
|
|
590
|
+
break;
|
|
591
|
+
|
|
592
|
+
/* If character is '\', or a terminal '$', then quote it.
|
|
593
|
+
*/
|
|
594
|
+
if (c == BACKSLASH || c == (Option.backward ? '?' : '/') ||
|
|
595
|
+
(c == '$' && (next == NEWLINE || next == CRETURN)))
|
|
596
|
+
{
|
|
597
|
+
putc (BACKSLASH, fp);
|
|
598
|
+
++length;
|
|
599
|
+
}
|
|
600
|
+
putc (c, fp);
|
|
601
|
+
++length;
|
|
602
|
+
}
|
|
603
|
+
return length;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/* Writes "line", stripping leading and duplicate white space.
|
|
607
|
+
*/
|
|
608
|
+
static size_t writeCompactSourceLine (FILE *const fp, const char *const line)
|
|
609
|
+
{
|
|
610
|
+
boolean lineStarted = FALSE;
|
|
611
|
+
size_t length = 0;
|
|
612
|
+
const char *p;
|
|
613
|
+
int c;
|
|
614
|
+
|
|
615
|
+
/* Write everything up to, but not including, the newline.
|
|
616
|
+
*/
|
|
617
|
+
for (p = line, c = *p ; c != NEWLINE && c != '\0' ; c = *++p)
|
|
618
|
+
{
|
|
619
|
+
if (lineStarted || ! isspace (c)) /* ignore leading spaces */
|
|
620
|
+
{
|
|
621
|
+
lineStarted = TRUE;
|
|
622
|
+
if (isspace (c))
|
|
623
|
+
{
|
|
624
|
+
int next;
|
|
625
|
+
|
|
626
|
+
/* Consume repeating white space.
|
|
627
|
+
*/
|
|
628
|
+
while (next = *(p+1) , isspace (next) && next != NEWLINE)
|
|
629
|
+
++p;
|
|
630
|
+
c = ' '; /* force space character for any white space */
|
|
631
|
+
}
|
|
632
|
+
if (c != CRETURN || *(p + 1) != NEWLINE)
|
|
633
|
+
{
|
|
634
|
+
putc (c, fp);
|
|
635
|
+
++length;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
return length;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
static int writeXrefEntry (const tagEntryInfo *const tag)
|
|
643
|
+
{
|
|
644
|
+
const char *const line =
|
|
645
|
+
readSourceLine (TagFile.vLine, tag->filePosition, NULL);
|
|
646
|
+
int length;
|
|
647
|
+
|
|
648
|
+
if (Option.tagFileFormat == 1)
|
|
649
|
+
length = fprintf (TagFile.fp, "%-16s %4lu %-16s ", tag->name,
|
|
650
|
+
tag->lineNumber, tag->sourceFileName);
|
|
651
|
+
else
|
|
652
|
+
length = fprintf (TagFile.fp, "%-16s %-10s %4lu %-16s ", tag->name,
|
|
653
|
+
tag->kindName, tag->lineNumber, tag->sourceFileName);
|
|
654
|
+
|
|
655
|
+
length += writeCompactSourceLine (TagFile.fp, line);
|
|
656
|
+
putc (NEWLINE, TagFile.fp);
|
|
657
|
+
++length;
|
|
658
|
+
|
|
659
|
+
return length;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/* Truncates the text line containing the tag at the character following the
|
|
663
|
+
* tag, providing a character which designates the end of the tag.
|
|
664
|
+
*/
|
|
665
|
+
static void truncateTagLine (
|
|
666
|
+
char *const line, const char *const token, const boolean discardNewline)
|
|
667
|
+
{
|
|
668
|
+
char *p = strstr (line, token);
|
|
669
|
+
|
|
670
|
+
if (p != NULL)
|
|
671
|
+
{
|
|
672
|
+
p += strlen (token);
|
|
673
|
+
if (*p != '\0' && ! (*p == '\n' && discardNewline))
|
|
674
|
+
++p; /* skip past character terminating character */
|
|
675
|
+
*p = '\0';
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
static int writeEtagsEntry (const tagEntryInfo *const tag)
|
|
680
|
+
{
|
|
681
|
+
int length;
|
|
682
|
+
|
|
683
|
+
if (tag->isFileEntry)
|
|
684
|
+
length = fprintf (TagFile.etags.fp, "\177%s\001%lu,0\n",
|
|
685
|
+
tag->name, tag->lineNumber);
|
|
686
|
+
else
|
|
687
|
+
{
|
|
688
|
+
long seekValue;
|
|
689
|
+
char *const line =
|
|
690
|
+
readSourceLine (TagFile.vLine, tag->filePosition, &seekValue);
|
|
691
|
+
|
|
692
|
+
if (tag->truncateLine)
|
|
693
|
+
truncateTagLine (line, tag->name, TRUE);
|
|
694
|
+
else
|
|
695
|
+
line [strlen (line) - 1] = '\0';
|
|
696
|
+
|
|
697
|
+
length = fprintf (TagFile.etags.fp, "%s\177%s\001%lu,%ld\n", line,
|
|
698
|
+
tag->name, tag->lineNumber, seekValue);
|
|
699
|
+
}
|
|
700
|
+
TagFile.etags.byteCount += length;
|
|
701
|
+
|
|
702
|
+
return length;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
static int addExtensionFields (const tagEntryInfo *const tag)
|
|
706
|
+
{
|
|
707
|
+
const char* const kindKey = Option.extensionFields.kindKey ? "kind:" : "";
|
|
708
|
+
boolean first = TRUE;
|
|
709
|
+
const char* separator = ";\"";
|
|
710
|
+
const char* const empty = "";
|
|
711
|
+
int length = 0;
|
|
712
|
+
/* "sep" returns a value only the first time it is evaluated */
|
|
713
|
+
#define sep (first ? (first = FALSE, separator) : empty)
|
|
714
|
+
|
|
715
|
+
if (tag->kindName != NULL && (Option.extensionFields.kindLong ||
|
|
716
|
+
(Option.extensionFields.kind && tag->kind == '\0')))
|
|
717
|
+
length += fprintf (TagFile.fp,"%s\t%s%s", sep, kindKey, tag->kindName);
|
|
718
|
+
else if (tag->kind != '\0' && (Option.extensionFields.kind ||
|
|
719
|
+
(Option.extensionFields.kindLong && tag->kindName == NULL)))
|
|
720
|
+
length += fprintf (TagFile.fp, "%s\t%s%c", sep, kindKey, tag->kind);
|
|
721
|
+
|
|
722
|
+
if (Option.extensionFields.lineNumber)
|
|
723
|
+
length += fprintf (TagFile.fp, "%s\tline:%ld", sep, tag->lineNumber);
|
|
724
|
+
|
|
725
|
+
if (Option.extensionFields.language && tag->language != NULL)
|
|
726
|
+
length += fprintf (TagFile.fp, "%s\tlanguage:%s", sep, tag->language);
|
|
727
|
+
|
|
728
|
+
if (Option.extensionFields.scope &&
|
|
729
|
+
tag->extensionFields.scope [0] != NULL &&
|
|
730
|
+
tag->extensionFields.scope [1] != NULL)
|
|
731
|
+
length += fprintf (TagFile.fp, "%s\t%s:%s", sep,
|
|
732
|
+
tag->extensionFields.scope [0],
|
|
733
|
+
tag->extensionFields.scope [1]);
|
|
734
|
+
|
|
735
|
+
if (Option.extensionFields.typeRef &&
|
|
736
|
+
tag->extensionFields.typeRef [0] != NULL &&
|
|
737
|
+
tag->extensionFields.typeRef [1] != NULL)
|
|
738
|
+
length += fprintf (TagFile.fp, "%s\ttyperef:%s:%s", sep,
|
|
739
|
+
tag->extensionFields.typeRef [0],
|
|
740
|
+
tag->extensionFields.typeRef [1]);
|
|
741
|
+
|
|
742
|
+
if (Option.extensionFields.fileScope && tag->isFileScope)
|
|
743
|
+
length += fprintf (TagFile.fp, "%s\tfile:", sep);
|
|
744
|
+
|
|
745
|
+
if (Option.extensionFields.inheritance &&
|
|
746
|
+
tag->extensionFields.inheritance != NULL)
|
|
747
|
+
length += fprintf (TagFile.fp, "%s\tinherits:%s", sep,
|
|
748
|
+
tag->extensionFields.inheritance);
|
|
749
|
+
|
|
750
|
+
if (Option.extensionFields.access && tag->extensionFields.access != NULL)
|
|
751
|
+
length += fprintf (TagFile.fp, "%s\taccess:%s", sep,
|
|
752
|
+
tag->extensionFields.access);
|
|
753
|
+
|
|
754
|
+
if (Option.extensionFields.implementation &&
|
|
755
|
+
tag->extensionFields.implementation != NULL)
|
|
756
|
+
length += fprintf (TagFile.fp, "%s\timplementation:%s", sep,
|
|
757
|
+
tag->extensionFields.implementation);
|
|
758
|
+
|
|
759
|
+
if (Option.extensionFields.signature &&
|
|
760
|
+
tag->extensionFields.signature != NULL)
|
|
761
|
+
length += fprintf (TagFile.fp, "%s\tsignature:%s", sep,
|
|
762
|
+
tag->extensionFields.signature);
|
|
763
|
+
|
|
764
|
+
return length;
|
|
765
|
+
#undef sep
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
static int writePatternEntry (const tagEntryInfo *const tag)
|
|
769
|
+
{
|
|
770
|
+
char *const line = readSourceLine (TagFile.vLine, tag->filePosition, NULL);
|
|
771
|
+
const int searchChar = Option.backward ? '?' : '/';
|
|
772
|
+
boolean newlineTerminated;
|
|
773
|
+
int length = 0;
|
|
774
|
+
|
|
775
|
+
if (tag->truncateLine)
|
|
776
|
+
truncateTagLine (line, tag->name, FALSE);
|
|
777
|
+
newlineTerminated = (boolean) (line [strlen (line) - 1] == '\n');
|
|
778
|
+
|
|
779
|
+
length += fprintf (TagFile.fp, "%c^", searchChar);
|
|
780
|
+
length += writeSourceLine (TagFile.fp, line);
|
|
781
|
+
length += fprintf (TagFile.fp, "%s%c", newlineTerminated ? "$":"", searchChar);
|
|
782
|
+
|
|
783
|
+
return length;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
static int writeLineNumberEntry (const tagEntryInfo *const tag)
|
|
787
|
+
{
|
|
788
|
+
return fprintf (TagFile.fp, "%lu", tag->lineNumber);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
static int writeCtagsEntry (const tagEntryInfo *const tag)
|
|
792
|
+
{
|
|
793
|
+
int length = fprintf (TagFile.fp, "%s\t%s\t",
|
|
794
|
+
tag->name, tag->sourceFileName);
|
|
795
|
+
|
|
796
|
+
if (tag->lineNumberEntry)
|
|
797
|
+
length += writeLineNumberEntry (tag);
|
|
798
|
+
else
|
|
799
|
+
length += writePatternEntry (tag);
|
|
800
|
+
|
|
801
|
+
if (includeExtensionFlags ())
|
|
802
|
+
length += addExtensionFields (tag);
|
|
803
|
+
|
|
804
|
+
length += fprintf (TagFile.fp, "\n");
|
|
805
|
+
|
|
806
|
+
return length;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
extern void makeTagEntry (const tagEntryInfo *const tag)
|
|
810
|
+
{
|
|
811
|
+
Assert (tag->name != NULL);
|
|
812
|
+
if (tag->name [0] == '\0')
|
|
813
|
+
error (WARNING, "ignoring null tag in %s", vStringValue (File.name));
|
|
814
|
+
else
|
|
815
|
+
{
|
|
816
|
+
int length = 0;
|
|
817
|
+
|
|
818
|
+
DebugStatement ( debugEntry (tag); )
|
|
819
|
+
if (Option.xref)
|
|
820
|
+
{
|
|
821
|
+
if (! tag->isFileEntry)
|
|
822
|
+
length = writeXrefEntry (tag);
|
|
823
|
+
}
|
|
824
|
+
else if (Option.etags)
|
|
825
|
+
length = writeEtagsEntry (tag);
|
|
826
|
+
else
|
|
827
|
+
length = writeCtagsEntry (tag);
|
|
828
|
+
|
|
829
|
+
++TagFile.numTags.added;
|
|
830
|
+
rememberMaxLengths (strlen (tag->name), (size_t) length);
|
|
831
|
+
DebugStatement ( fflush (TagFile.fp); )
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
extern void initTagEntry (tagEntryInfo *const e, const char *const name)
|
|
836
|
+
{
|
|
837
|
+
Assert (File.source.name != NULL);
|
|
838
|
+
memset (e, 0, sizeof (tagEntryInfo));
|
|
839
|
+
e->lineNumberEntry = (boolean) (Option.locate == EX_LINENUM);
|
|
840
|
+
e->lineNumber = getSourceLineNumber ();
|
|
841
|
+
e->language = getSourceLanguageName ();
|
|
842
|
+
e->filePosition = getInputFilePosition ();
|
|
843
|
+
e->sourceFileName = getSourceFileTagPath ();
|
|
844
|
+
e->name = name;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/* vi:set tabstop=4 shiftwidth=4: */
|