1 /*
2 *
3 * Copyright (c) 2015, Red Hat, Inc.
4 * Copyright (c) 2015, Masatake YAMATO
5 *
6 * Author: Masatake YAMATO <yamato@redhat.com>
7 *
8 * This source code is released for free distribution under the terms of the
9 * GNU General Public License version 2 or (at your option) any later version.
10 *
11 */
12
13 #include "general.h" /* must always come first */
14 #include "ctags.h"
15 #include "debug.h"
16 #include "options.h"
17 #include "options_p.h"
18 #include "parse_p.h"
19 #include "routines.h"
20 #include "trashbox.h"
21 #include "writer_p.h"
22 #include "xtag.h"
23 #include "xtag_p.h"
24
25 #include <string.h>
26 #include <ctype.h>
27
28 typedef struct sXtagObject {
29 xtagDefinition *def;
30 langType language;
31 xtagType sibling;
32 } xtagObject;
33
isPseudoTagsEnabled(xtagDefinition * pdef CTAGS_ATTR_UNUSED)34 static bool isPseudoTagsEnabled (xtagDefinition *pdef CTAGS_ATTR_UNUSED)
35 {
36 if (!writerCanPrintPtag())
37 return false;
38 if (!writerPrintPtagByDefault())
39 return false;
40
41 return ! isDestinationStdout ();
42 }
43
isPseudoTagsFixed(xtagDefinition * pdef CTAGS_ATTR_UNUSED)44 static bool isPseudoTagsFixed (xtagDefinition *pdef CTAGS_ATTR_UNUSED)
45 {
46 if (!writerCanPrintPtag())
47 return true;
48 else
49 return false;
50 }
51
enableFileKind(xtagDefinition * pdef,bool state)52 static void enableFileKind (xtagDefinition *pdef, bool state)
53 {
54 enableDefaultFileKind(state);
55 pdef->enabled = state;
56 }
57
58 static xtagDefinition xtagDefinitions [] = {
59 { true, 'F', "fileScope",
60 "Include tags of file scope" },
61 { false, 'f', "inputFile",
62 "Include an entry for the base file name of every input file",
63 NULL,
64 NULL,
65 enableFileKind},
66 { false, 'p', "pseudo",
67 "Include pseudo tags",
68 isPseudoTagsEnabled,
69 isPseudoTagsFixed},
70 { false, 'q', "qualified",
71 "Include an extra class-qualified tag entry for each tag"},
72 { false, 'r', "reference",
73 "Include reference tags"},
74 { false, 'g', "guest",
75 "Include tags generated by guest parsers"},
76 { true, 's', "subparser",
77 "Include tags generated by subparsers"},
78 { true, '\0', "anonymous",
79 "Include tags for non-named objects like lambda"},
80 };
81
82 static unsigned int xtagObjectUsed;
83 static unsigned int xtagObjectAllocated;
84 static xtagObject* xtagObjects;
85
getXtagObject(xtagType type)86 static xtagObject* getXtagObject (xtagType type)
87 {
88 Assert ((0 <= type) && ((unsigned int)type < xtagObjectUsed));
89 return (xtagObjects + type);
90 }
91
getXtagDefinition(xtagType type)92 extern xtagDefinition* getXtagDefinition (xtagType type)
93 {
94 Assert ((0 <= type) && ((unsigned int)type < xtagObjectUsed));
95
96 return getXtagObject (type)->def;
97 }
98
99 typedef bool (* xtagPredicate) (xtagObject *pobj, langType language, const void *user_data);
getXtagTypeGeneric(xtagPredicate predicate,langType language,const void * user_data)100 static xtagType getXtagTypeGeneric (xtagPredicate predicate, langType language, const void *user_data)
101 {
102 static bool initialized = false;
103 unsigned int i;
104
105 if (language == LANG_AUTO && (initialized == false))
106 {
107 initialized = true;
108 initializeParser (LANG_AUTO);
109 }
110 else if (language != LANG_IGNORE && (initialized == false))
111 initializeParser (language);
112
113 for (i = 0; i < xtagObjectUsed; i++)
114 {
115 if (predicate (xtagObjects + i, language, user_data))
116 return i;
117 }
118 return XTAG_UNKNOWN;
119 }
120
xtagEqualByLetter(xtagObject * pobj,langType language CTAGS_ATTR_UNUSED,const void * user_data)121 static bool xtagEqualByLetter (xtagObject *pobj, langType language CTAGS_ATTR_UNUSED,
122 const void *user_data)
123 {
124 return (pobj->def->letter == *((char *)user_data))? true: false;
125 }
126
getXtagTypeForLetter(char letter)127 extern xtagType getXtagTypeForLetter (char letter)
128 {
129 return getXtagTypeGeneric (xtagEqualByLetter, LANG_IGNORE, &letter);
130 }
131
xtagEqualByNameAndLanguage(xtagObject * pobj,langType language,const void * user_data)132 static bool xtagEqualByNameAndLanguage (xtagObject *pobj, langType language, const void *user_data)
133 {
134 const char* name = user_data;
135
136 if ((language == LANG_AUTO || pobj->language == language)
137 && (strcmp (pobj->def->name, name) == 0))
138 return true;
139 else
140 return false;
141 }
142
getXtagTypeForNameAndLanguage(const char * name,langType language)143 extern xtagType getXtagTypeForNameAndLanguage (const char *name, langType language)
144 {
145 return getXtagTypeGeneric (xtagEqualByNameAndLanguage, language, name);
146 }
147
xtagColprintTableNew(void)148 extern struct colprintTable * xtagColprintTableNew (void)
149 {
150 return colprintTableNew ("L:LETTER", "L:NAME", "L:ENABLED",
151 "L:LANGUAGE", "L:FIXED", "L:DESCRIPTION", NULL);
152 }
153
xtagColprintAddLine(struct colprintTable * table,int xtype)154 static void xtagColprintAddLine (struct colprintTable *table, int xtype)
155 {
156 xtagObject* xobj = getXtagObject (xtype);
157 xtagDefinition *xdef = xobj->def;
158
159 struct colprintLine *line = colprintTableGetNewLine(table);
160
161 colprintLineAppendColumnChar (line,
162 (xdef->letter == NUL_XTAG_LETTER)
163 ? '-'
164 : xdef->letter);
165 colprintLineAppendColumnCString (line, xdef->name);
166 colprintLineAppendColumnBool (line, isXtagEnabled(xdef->xtype));
167 colprintLineAppendColumnCString (line,
168 xobj->language == LANG_IGNORE
169 ? RSV_NONE
170 : getLanguageName (xobj->language));
171 colprintLineAppendColumnBool (line, isXtagFixed(xdef->xtype));
172 colprintLineAppendColumnCString (line, xdef->description);
173 }
174
xtagColprintAddCommonLines(struct colprintTable * table)175 extern void xtagColprintAddCommonLines (struct colprintTable *table)
176 {
177 for (int i = 0; i < XTAG_COUNT; i++)
178 xtagColprintAddLine (table, i);
179 }
180
xtagColprintAddLanguageLines(struct colprintTable * table,langType language)181 extern void xtagColprintAddLanguageLines (struct colprintTable *table, langType language)
182 {
183 for (unsigned int i = XTAG_COUNT; i < xtagObjectUsed; i++)
184 {
185 xtagObject* xobj = getXtagObject (i);
186
187 if (xobj->language == language)
188 xtagColprintAddLine (table, i);
189 }
190 }
191
xtagColprintCompareLines(struct colprintLine * a,struct colprintLine * b)192 static int xtagColprintCompareLines (struct colprintLine *a , struct colprintLine *b)
193 {
194 const char *a_parser = colprintLineGetColumn (a, 3);
195 const char *b_parser = colprintLineGetColumn (b, 3);
196
197 if (strcmp (a_parser, RSV_NONE) == 0
198 && strcmp (b_parser, RSV_NONE) != 0)
199 return -1;
200 else if (strcmp (a_parser, RSV_NONE) != 0
201 && strcmp (b_parser, RSV_NONE) == 0)
202 return 1;
203 else if (strcmp (a_parser, RSV_NONE) != 0
204 && strcmp (b_parser, RSV_NONE) != 0)
205 {
206 int r;
207 r = strcmp (a_parser, b_parser);
208 if (r != 0)
209 return r;
210 }
211 else
212 {
213 int r;
214
215 const char *a_letter = colprintLineGetColumn (a, 0);
216 const char *b_letter = colprintLineGetColumn (b, 0);
217 r = strcmp(a_letter, b_letter);
218 if (r != 0)
219 return r;
220 }
221
222 const char *a_name = colprintLineGetColumn (a, 1);
223 const char *b_name = colprintLineGetColumn (b, 1);
224
225 return strcmp(a_name, b_name);
226 }
227
xtagColprintTablePrint(struct colprintTable * table,bool withListHeader,bool machinable,FILE * fp)228 extern void xtagColprintTablePrint (struct colprintTable *table,
229 bool withListHeader, bool machinable, FILE *fp)
230 {
231 colprintTableSort (table, xtagColprintCompareLines);
232 colprintTablePrint (table, 0, withListHeader, machinable, fp);
233 }
234
isXtagEnabled(xtagType type)235 extern bool isXtagEnabled (xtagType type)
236 {
237 xtagDefinition* def = getXtagDefinition (type);
238
239 Assert (def);
240
241 if (def->isEnabled)
242 return def->isEnabled (def);
243 else
244 return def->enabled;
245 }
246
isXtagFixed(xtagType type)247 extern bool isXtagFixed (xtagType type)
248 {
249 xtagDefinition* def = getXtagDefinition (type);
250
251 Assert (def);
252
253 if (def->isFixed)
254 return def->isFixed (def);
255
256 return false;
257 }
258
enableXtag(xtagType type,bool state)259 extern bool enableXtag (xtagType type, bool state)
260 {
261 bool old;
262 xtagDefinition* def = getXtagDefinition (type);
263
264 Assert (def);
265
266 old = isXtagEnabled (type);
267
268 if (isXtagFixed(type))
269 def->enabled = old;
270 else if (def->enable)
271 def->enable (def, state);
272 else
273 def->enabled = state;
274
275 def->isEnabled = NULL;
276
277 return old;
278 }
279
isCommonXtag(xtagType type)280 extern bool isCommonXtag (xtagType type)
281 {
282 return (type < XTAG_COUNT)? true: false;
283 }
284
getXtagOwner(xtagType type)285 extern langType getXtagOwner (xtagType type)
286 {
287 return getXtagObject (type)->language;
288 }
289
getXtagName(xtagType type)290 extern const char* getXtagName (xtagType type)
291 {
292 xtagDefinition* def = getXtagDefinition (type);
293 if (def)
294 return def->name;
295 else
296 return NULL;
297 }
298
getXtagDescription(xtagType type)299 extern const char* getXtagDescription (xtagType type)
300 {
301 xtagDefinition* def = getXtagDefinition (type);
302 if (def)
303 return def->description;
304 else
305 return NULL;
306 }
307
initXtagObjects(void)308 extern void initXtagObjects (void)
309 {
310 xtagObject *xobj;
311
312 xtagObjectAllocated = ARRAY_SIZE (xtagDefinitions);
313 xtagObjects = xMalloc (xtagObjectAllocated, xtagObject);
314 DEFAULT_TRASH_BOX(&xtagObjects, eFreeIndirect);
315
316 for (unsigned int i = 0; i < ARRAY_SIZE (xtagDefinitions); i++)
317 {
318 xobj = xtagObjects + i;
319 xobj->def = xtagDefinitions + i;
320 xobj->def->xtype = i;
321 xobj->language = LANG_IGNORE;
322 xobj->sibling = XTAG_UNKNOWN;
323 xtagObjectUsed++;
324 }
325 }
326
countXtags(void)327 extern int countXtags (void)
328 {
329 return xtagObjectUsed;
330 }
331
updateSiblingXtag(xtagType type,const char * name)332 static void updateSiblingXtag (xtagType type, const char* name)
333 {
334 int i;
335 xtagObject *xobj;
336
337 for (i = type; i > 0; i--)
338 {
339 xobj = xtagObjects + i - 1;
340 if (xobj->def->name && (strcmp (xobj->def->name, name) == 0))
341 {
342 Assert (xobj->sibling == XTAG_UNKNOWN);
343 xobj->sibling = type;
344 break;
345 }
346 }
347 }
348
defineXtag(xtagDefinition * def,langType language)349 extern int defineXtag (xtagDefinition *def, langType language)
350 {
351 xtagObject *xobj;
352 size_t i;
353
354 Assert (def);
355 Assert (def->name);
356 for (i = 0; i < strlen (def->name); i++)
357 {
358 Assert ( isalnum (def->name [i]) );
359 }
360 def->letter = NUL_XTAG_LETTER;
361
362 if (xtagObjectUsed == xtagObjectAllocated)
363 {
364 xtagObjectAllocated *= 2;
365 xtagObjects = xRealloc (xtagObjects, xtagObjectAllocated, xtagObject);
366 }
367 xobj = xtagObjects + (xtagObjectUsed);
368 def->xtype = xtagObjectUsed++;
369 xobj->def = def;
370 xobj->language = language;
371 xobj->sibling = XTAG_UNKNOWN;
372
373 updateSiblingXtag (def->xtype, def->name);
374
375 verbose ("Add extra[%d]: %s,%s in %s\n",
376 def->xtype,
377 def->name, def->description,
378 getLanguageName (language));
379
380 return def->xtype;
381 }
382
nextSiblingXtag(xtagType type)383 extern xtagType nextSiblingXtag (xtagType type)
384 {
385 xtagObject *xobj;
386
387 xobj = xtagObjects + type;
388 return xobj->sibling;
389 }
390