geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

writer-ctags.c
Go to the documentation of this file.
1/*
2* Copyright (c) 1998-2002, Darren Hiebert
3*
4* This source code is released for free distribution under the terms of the
5* GNU General Public License version 2 or (at your option) any later version.
6*
7* External interface to entry.c
8*/
9
10#include "general.h" /* must always come first */
11
12#include "entry_p.h"
13#include "field.h"
14#include "field_p.h"
15#include "mio.h"
16#include "options_p.h"
17#include "parse_p.h"
18#include "ptag_p.h"
19#include "read.h"
20#include "writer_p.h"
21#include "xtag.h"
22#include "xtag_p.h"
23
24
25#define CTAGS_FILE "tags"
26
27
29 MIO * mio, const tagEntryInfo *const tag,
30 void *clientData);
32 MIO * mio, const ptagDesc *desc,
33 const char *const fileName,
34 const char *const pattern,
35 const char *const parserName,
36 void *clientData);
37static bool treatFieldAsFixed (int fieldType);
39
40#ifdef WIN32
41static enum filenameSepOp overrideFilenameSeparator (enum filenameSepOp currentSetting);
42#endif /* WIN32 */
43
44struct rejection {
46};
47
50 .writePtagEntry = writeCtagsPtagEntry,
51 .printPtagByDefault = true,
52 .preWriteEntry = NULL,
53 .postWriteEntry = NULL,
54 .rescanFailedEntry = NULL,
55 .treatFieldAsFixed = treatFieldAsFixed,
56 .checkOptions = checkCtagsOptions,
57#ifdef WIN32
58 .overrideFilenameSeparator = overrideFilenameSeparator,
59#endif
60 .defaultFileName = CTAGS_FILE,
61};
62
64 void *clientData CTAGS_ATTR_UNUSED)
65{
66 static struct rejection rej;
67
68 rej.rejectionInThisInput = false;
69
70 return &rej;
71}
72
74 void *clientData CTAGS_ATTR_UNUSED)
75{
76 struct rejection *rej = writer->private;
77 return rej->rejectionInThisInput;
78}
79
80#ifdef WIN32
81static enum filenameSepOp overrideFilenameSeparator (enum filenameSepOp currentSetting)
82{
83 if (currentSetting == FILENAME_SEP_UNSET)
84 return FILENAME_SEP_USE_SLASH;
85 return currentSetting;
86}
87#endif
88
91 .writePtagEntry = writeCtagsPtagEntry,
92 .printPtagByDefault = true,
93 .preWriteEntry = beginECtagsFile,
94 .postWriteEntry = endECTagsFile,
95 .rescanFailedEntry = NULL,
96 .treatFieldAsFixed = treatFieldAsFixed,
97 .defaultFileName = CTAGS_FILE,
98 .checkOptions = checkCtagsOptions,
99};
100
101static bool hasTagEntryTabOrNewlineChar (const tagEntryInfo * const tag)
102{
103
106 return true;
107
108 if (tag->lineNumberEntry)
109 {
111 {
113 return true;
114 }
115 }
117 {
118 /* Pattern may have a tab char. However, doesFieldHaveTabOrNewlineChar returns
119 * false because NO_PARSER_FIELD may not have doesContainAnyChar handler.
120 */
121 return true;
122 }
123
125 {
129 return true;
132 return true;
135 return true;
136
137 int f[] = { FIELD_INHERITANCE,
145 -1};
146 for (unsigned int i = 0; f[i] >= 0; i++)
147 {
148 if (isFieldEnabled (f[i]) && doesFieldHaveValue (f[i], tag)
150 return true;
151 }
152 }
153
154 for (unsigned int i = 0; i < tag->usedParserFields; i++)
155 {
156 const tagField *f = getParserFieldForIndex(tag, i);
157 fieldType ftype = f->ftype;
158 if (isFieldEnabled (ftype))
159 {
160 if (doesFieldHaveTabOrNewlineChar (ftype, tag, i))
161 return true;
162 }
163 }
164 return false;
165}
166
167
168static const char* escapeFieldValueFull (tagWriter *writer, const tagEntryInfo * tag, fieldType ftype, int fieldIndex)
169{
170 const char *v;
171 if (writer->type == WRITER_E_CTAGS && doesFieldHaveRenderer(ftype, true))
172 v = renderFieldNoEscaping (ftype, tag, fieldIndex);
173 else
174 v = renderField (ftype, tag, fieldIndex);
175
176 return v;
177}
178
179static const char* escapeFieldValue (tagWriter *writer, const tagEntryInfo * tag, fieldType ftype)
180{
181 return escapeFieldValueFull (writer, tag, ftype, NO_PARSER_FIELD);
182}
183
184static int renderExtensionFieldMaybe (tagWriter *writer, int xftype, const tagEntryInfo *const tag, char sep[2], MIO *mio)
185{
186 if (isFieldEnabled (xftype) && doesFieldHaveValue (xftype, tag))
187 {
188 int len;
189 len = mio_printf (mio, "%s\t%s:%s", sep,
190 getFieldName (xftype),
191 escapeFieldValue (writer, tag, xftype));
192 sep[0] = '\0';
193 return len;
194 }
195 else
196 return 0;
197}
198
199static int addParserFields (tagWriter *writer, MIO * mio, const tagEntryInfo *const tag)
200{
201 unsigned int i;
202 int length = 0;
203
204 for (i = 0; i < tag->usedParserFields; i++)
205 {
206 const tagField *f = getParserFieldForIndex(tag, i);
207 fieldType ftype = f->ftype;
208 if (! isFieldEnabled (ftype))
209 continue;
210
211 length += mio_printf(mio, "\t%s:%s",
212 getFieldName (ftype),
213 escapeFieldValueFull (writer, tag, ftype, i));
214 }
215 return length;
216}
217
218static int writeLineNumberEntry (tagWriter *writer, MIO * mio, const tagEntryInfo *const tag)
219{
221 return mio_printf (mio, "%s", escapeFieldValue (writer, tag, FIELD_LINE_NUMBER));
222 else
223 return mio_printf (mio, "%lu", tag->lineNumber);
224}
225
226static int addExtensionFields (tagWriter *writer, MIO *mio, const tagEntryInfo *const tag)
227{
228 bool isKindKeyEnabled = isFieldEnabled (FIELD_KIND_KEY);
229 bool isScopeEnabled = isFieldEnabled (FIELD_SCOPE_KEY);
230
231 const char* const kindKey = isKindKeyEnabled
233 :"";
234 const char* const kindFmt = isKindKeyEnabled
235 ?"%s\t%s:%s"
236 :"%s\t%s%s";
237 const char* const scopeKey = isScopeEnabled
239 :"";
240 const char* const scopeFmt = isScopeEnabled
241 ?"%s\t%s:%s:%s"
242 :"%s\t%s%s:%s";
243
244 char sep [] = {';', '"', '\0'};
245 int length = 0;
246
247 const char *str = NULL;;
249 const char kind_letter_str[2] = {kdef->letter, '\0'};
250
251 if (kdef->name != NULL && (isFieldEnabled (FIELD_KIND_LONG) ||
253 {
254 /* Use kind long name */
255 str = kdef->name;
256 }
257 else if (kdef->letter != KIND_NULL_LETTER && (isFieldEnabled (FIELD_KIND) ||
258 (isFieldEnabled (FIELD_KIND_LONG) && kdef->name == NULL)))
259 {
260 /* Use kind letter */
261 str = kind_letter_str;
262 }
263
264 if (str)
265 {
266 length += mio_printf (mio, kindFmt, sep, kindKey, str);
267 sep [0] = '\0';
268 }
269
271 {
272 length += mio_printf (mio, "%s\t%s:%ld", sep,
274 tag->lineNumber);
275 sep [0] = '\0';
276 }
277
278 length += renderExtensionFieldMaybe (writer, FIELD_LANGUAGE, tag, sep, mio);
279
281 {
282 const char* k, *v;
283
286 if (k && v)
287 {
288 length += mio_printf (mio, scopeFmt, sep, scopeKey, k, v);
289 sep [0] = '\0';
290 }
291 }
292
294 {
295 length += mio_printf (mio, "%s\t%s:%s", sep,
298 sep [0] = '\0';
299 }
300
302 {
303 length += mio_printf (mio, "%s\t%s:", sep,
305 sep [0] = '\0';
306 }
307
308 length += renderExtensionFieldMaybe (writer, FIELD_INHERITANCE, tag, sep, mio);
309 length += renderExtensionFieldMaybe (writer, FIELD_ACCESS, tag, sep, mio);
310 length += renderExtensionFieldMaybe (writer, FIELD_IMPLEMENTATION, tag, sep, mio);
311 length += renderExtensionFieldMaybe (writer, FIELD_SIGNATURE, tag, sep, mio);
312 length += renderExtensionFieldMaybe (writer, FIELD_ROLES, tag, sep, mio);
313 length += renderExtensionFieldMaybe (writer, FIELD_EXTRAS, tag, sep, mio);
314 length += renderExtensionFieldMaybe (writer, FIELD_XPATH, tag, sep, mio);
315 length += renderExtensionFieldMaybe (writer, FIELD_END_LINE, tag, sep, mio);
316
317 return length;
318}
319
321 MIO * mio, const tagEntryInfo *const tag,
322 void *clientData CTAGS_ATTR_UNUSED)
323{
324 if (writer->private)
325 {
326 struct rejection *rej = writer->private;
328 {
329 rej->rejectionInThisInput = true;
330 return 0;
331 }
332 }
333
334 int length = mio_printf (mio, "%s\t%s\t",
337
338 /* This is for handling 'common' of 'fortran'. See the
339 description of --excmd=mixed in ctags.1. In tags output, what
340 we call "pattern" is instructions for vi.
341
342 However, in the other formats, pattern should be pattern as its name. */
343 if (tag->lineNumberEntry)
344 length += writeLineNumberEntry (writer, mio, tag);
345 else
346 {
347 if (Option.locate == EX_COMBINE)
348 length += mio_printf(mio, "%lu;", tag->lineNumber + (Option.backward? 1: -1));
349 length += mio_puts(mio, escapeFieldValue(writer, tag, FIELD_PATTERN));
350 }
351
353 {
354 length += addExtensionFields (writer, mio, tag);
355 length += addParserFields (writer, mio, tag);
356 }
357
358 length += mio_printf (mio, "\n");
359
360 return length;
361}
362
364 MIO * mio, const ptagDesc *desc,
365 const char *const fileName,
366 const char *const pattern,
367 const char *const parserName,
368 void *clientData CTAGS_ATTR_UNUSED)
369{
370
372 const char *xsep = extras? ";\" ": "";
373 const char *fsep = extras? ":": "";
374 const char *fieldx = extras? getFieldName (FIELD_EXTRAS): "";
375 const char *xptag = extras? getXtagName (XTAG_PSEUDO_TAGS): "";
376
377 return parserName
378
379#define OPT(X) ((X)?(X):"")
380 ? mio_printf (mio, "%s%s%s%s\t%s\t/%s/%s%s%s%s\n",
381 PSEUDO_TAG_PREFIX, desc->name, PSEUDO_TAG_SEPARATOR, parserName,
382 OPT(fileName), OPT(pattern),
383 xsep, fieldx, fsep, xptag)
384 : mio_printf (mio, "%s%s\t%s\t/%s/%s%s%s%s\n",
385 PSEUDO_TAG_PREFIX, desc->name,
386 OPT(fileName), OPT(pattern),
387 xsep, fieldx, fsep, xptag);
388#undef OPT
389}
390
392{
393 switch (fieldType)
394 {
395 case FIELD_NAME:
396 case FIELD_INPUT_FILE:
397 case FIELD_PATTERN:
398 return true;
399 default:
400 return false;
401 }
402}
403
405{
409 {
410 error (WARNING, "though %c/%s field is enabled, neither %c nor %c field is not enabled",
415 error (WARNING, "enable the %c field to make the %c/%s field printable",
419 enableField (FIELD_KIND_LONG, true, true);
420 }
423 {
424 error (WARNING, "though %c/%s field is enabled, %c field is not enabled",
428 error (WARNING, "enable the %c field to make the %c/%s field printable",
432 enableField (FIELD_SCOPE, true, true);
433 }
434}
const tagField * getParserFieldForIndex(const tagEntryInfo *tag, int index)
Definition: entry.c:996
#define NO_PARSER_FIELD
Definition: entry.h:108
void error(const errorSelection selection, const char *const format,...)
Definition: error.c:53
unsigned char getFieldLetter(fieldType type)
Definition: field.c:372
bool doesFieldHaveTabOrNewlineChar(fieldType type, const tagEntryInfo *tag, int index)
Definition: field.c:596
const char * renderField(fieldType type, const tagEntryInfo *tag, int index)
Definition: field.c:581
bool doesFieldHaveRenderer(fieldType type, bool noEscaping)
Definition: field.c:1003
bool isFieldEnabled(fieldType type)
Definition: field.c:945
bool doesFieldHaveValue(fieldType type, const tagEntryInfo *tag)
Definition: field.c:381
bool enableField(fieldType type, bool state, bool warnIfFixedField)
Definition: field.c:950
const char * renderFieldNoEscaping(fieldType type, const tagEntryInfo *tag, int index)
Definition: field.c:586
const char * getFieldName(fieldType type)
Definition: field.c:361
enum eFieldType fieldType
@ FIELD_TYPE_REF
Definition: field.h:49
@ FIELD_INPUT_FILE
Definition: field.h:33
@ FIELD_EXTRAS
Definition: field.h:56
@ FIELD_XPATH
Definition: field.h:57
@ FIELD_ROLES
Definition: field.h:53
@ FIELD_FILE_SCOPE
Definition: field.h:40
@ FIELD_KIND
Definition: field.h:43
@ FIELD_KIND_LONG
Definition: field.h:42
@ FIELD_LINE_NUMBER
Definition: field.h:46
@ FIELD_PATTERN
Definition: field.h:34
@ FIELD_KIND_KEY
Definition: field.h:50
@ FIELD_SCOPE_KEY
Definition: field.h:55
@ FIELD_ACCESS
Definition: field.h:39
@ FIELD_SCOPE_KIND_LONG
Definition: field.h:58
@ FIELD_END_LINE
Definition: field.h:59
@ FIELD_SCOPE
Definition: field.h:48
@ FIELD_IMPLEMENTATION
Definition: field.h:45
@ FIELD_NAME
Definition: field.h:32
@ FIELD_LANGUAGE
Definition: field.h:44
@ FIELD_INHERITANCE
Definition: field.h:41
@ FIELD_SIGNATURE
Definition: field.h:47
#define CTAGS_ATTR_UNUSED
Definition: gcc-attr.h:22
#define KIND_NULL_LETTER
Definition: kind.h:37
int mio_printf(MIO *mio, const char *format,...)
mio_printf: @mio: A MIO object @format: A print format string ...: Arguments of the format
Definition: mio.c:863
int mio_puts(MIO *mio, const char *s)
mio_puts: @mio: A MIO object @s: The string to write
Definition: mio.c:762
optionValues Option
Definition: options.c:137
@ EX_COMBINE
Definition: options_p.h:57
#define includeExtensionFlags()
Definition: options_p.h:34
kindDefinition * getLanguageKind(const langType language, int kindIndex)
Definition: parse.c:317
#define PSEUDO_TAG_SEPARATOR
Definition: ptag_p.h:19
#define PSEUDO_TAG_PREFIX
Definition: ptag_p.h:18
#define NULL
Definition: rbtree.h:150
@ WARNING
Definition: routines.h:37
const gchar filename[]
Definition: stash-example.c:4
MIO:
Definition: mio.c:136
bool rejectionInThisInput
Definition: writer-ctags.c:45
char letter
Definition: kind.h:73
char * name
Definition: kind.h:74
bool backward
Definition: options_p.h:91
bool lineDirectives
Definition: options_p.h:113
exCmd locate
Definition: options_p.h:93
const char * name
Definition: ptag_p.h:58
unsigned int lineNumberEntry
Definition: entry.h:44
unsigned long lineNumber
Definition: entry.h:56
int kindIndex
Definition: entry.h:64
langType langType
Definition: entry.h:61
unsigned int usedParserFields
Definition: entry.h:106
fieldType ftype
Definition: entry.h:34
int(* writeEntry)(tagWriter *writer, MIO *mio, const tagEntryInfo *const tag, void *clientData)
Definition: writer_p.h:36
void * private
Definition: writer_p.h:65
writerType type
Definition: writer_p.h:66
static int renderExtensionFieldMaybe(tagWriter *writer, int xftype, const tagEntryInfo *const tag, char sep[2], MIO *mio)
Definition: writer-ctags.c:184
#define CTAGS_FILE
Definition: writer-ctags.c:25
static int addParserFields(tagWriter *writer, MIO *mio, const tagEntryInfo *const tag)
Definition: writer-ctags.c:199
static int writeCtagsPtagEntry(tagWriter *writer, MIO *mio, const ptagDesc *desc, const char *const fileName, const char *const pattern, const char *const parserName, void *clientData)
Definition: writer-ctags.c:363
tagWriter eCtagsWriter
Definition: writer-ctags.c:89
static int addExtensionFields(tagWriter *writer, MIO *mio, const tagEntryInfo *const tag)
Definition: writer-ctags.c:226
static void * beginECtagsFile(tagWriter *writer, MIO *mio, void *clientData)
Definition: writer-ctags.c:63
static const char * escapeFieldValueFull(tagWriter *writer, const tagEntryInfo *tag, fieldType ftype, int fieldIndex)
Definition: writer-ctags.c:168
static int writeCtagsEntry(tagWriter *writer, MIO *mio, const tagEntryInfo *const tag, void *clientData)
Definition: writer-ctags.c:320
static bool hasTagEntryTabOrNewlineChar(const tagEntryInfo *const tag)
Definition: writer-ctags.c:101
static void checkCtagsOptions(tagWriter *writer)
Definition: writer-ctags.c:404
static int writeLineNumberEntry(tagWriter *writer, MIO *mio, const tagEntryInfo *const tag)
Definition: writer-ctags.c:218
#define OPT(X)
tagWriter uCtagsWriter
Definition: writer-ctags.c:48
static bool treatFieldAsFixed(int fieldType)
Definition: writer-ctags.c:391
static bool endECTagsFile(tagWriter *writer, MIO *mio, const char *filename, void *clientData)
Definition: writer-ctags.c:73
static const char * escapeFieldValue(tagWriter *writer, const tagEntryInfo *tag, fieldType ftype)
Definition: writer-ctags.c:179
static tagWriter * writer
Definition: writer.c:32
@ WRITER_E_CTAGS
Definition: writer_p.h:25
const char * getXtagName(xtagType type)
Definition: xtag.c:290
@ XTAG_PSEUDO_TAGS
Definition: xtag.h:30