xref: /Universal-ctags/main/ptag.c (revision cea85fadf7cf99e1279d706fe757df84f4730426)
1 /*
2  *
3  *  Copyright (c) 1996-2002, Darren Hiebert
4  *  Copyright (c) 2016, Red Hat, Inc.
5  *  Copyright (c) 2016, Masatake YAMATO
6  *
7  *  Author: Masatake YAMATO <yamato@redhat.com>
8  *
9  *   This source code is released for free distribution under the terms of the
10  *   GNU General Public License version 2 or (at your option) any later version.
11  *
12  */
13 
14 #include "general.h"  /* must always come first */
15 
16 #include "colprint_p.h"
17 #include "ctags.h"
18 #include "debug.h"
19 #include "entry_p.h"
20 #include "options_p.h"
21 #include "parse_p.h"
22 #include "ptag_p.h"
23 #include "routines_p.h"
24 #include "writer_p.h"
25 #include <string.h>
26 
27 
ptagMakeFormat(ptagDesc * desc,langType language CTAGS_ATTR_UNUSED,const void * data CTAGS_ATTR_UNUSED)28 static bool ptagMakeFormat (ptagDesc *desc, langType language CTAGS_ATTR_UNUSED,
29 							const void *data CTAGS_ATTR_UNUSED)
30 {
31 	char format [11];
32 	const char *formatComment = "unknown format";
33 	const optionValues *opt = data;
34 
35 	sprintf (format, "%u", opt->tagFileFormat);
36 	if (opt->tagFileFormat == 1)
37 		formatComment = "original ctags format";
38 	else if (opt->tagFileFormat == 2)
39 		formatComment =
40 			"extended format; --format=1 will not append ;\" to lines";
41 	return writePseudoTag (desc, format, formatComment, NULL);
42 }
43 
ptagMakeHowSorted(ptagDesc * desc,langType language CTAGS_ATTR_UNUSED,const void * data CTAGS_ATTR_UNUSED)44 static bool ptagMakeHowSorted (ptagDesc *desc, langType language CTAGS_ATTR_UNUSED,
45 							   const void *data CTAGS_ATTR_UNUSED)
46 {
47 	const optionValues *opt = data;
48 	return writePseudoTag (desc,
49 			       opt->sorted == SO_FOLDSORTED ? "2" :
50 			       (opt->sorted == SO_SORTED ? "1" : "0"),
51 			       "0=unsorted, 1=sorted, 2=foldcase",
52 			       NULL);
53 }
54 
ptagMakeAuthor(ptagDesc * desc,langType language CTAGS_ATTR_UNUSED,const void * data CTAGS_ATTR_UNUSED)55 static bool ptagMakeAuthor (ptagDesc *desc, langType language CTAGS_ATTR_UNUSED,
56 							const void *data CTAGS_ATTR_UNUSED)
57 {
58 	return writePseudoTag (desc,
59 						   AUTHOR_NAME,  "", NULL);
60 }
61 
ptagMakeProgName(ptagDesc * desc,langType language CTAGS_ATTR_UNUSED,const void * data CTAGS_ATTR_UNUSED)62 static bool ptagMakeProgName (ptagDesc *desc, langType language CTAGS_ATTR_UNUSED,
63 							  const void *data CTAGS_ATTR_UNUSED)
64 {
65 	return writePseudoTag (desc,
66 						   PROGRAM_NAME,  "Derived from Exuberant Ctags", NULL);
67 }
68 
ptagMakeProgURL(ptagDesc * desc,langType language CTAGS_ATTR_UNUSED,const void * data CTAGS_ATTR_UNUSED)69 static bool ptagMakeProgURL (ptagDesc *desc, langType language CTAGS_ATTR_UNUSED,
70 							 const void *data CTAGS_ATTR_UNUSED)
71 {
72 	return writePseudoTag (desc,
73 						   PROGRAM_URL, "official site", NULL);
74 }
75 
ptagMakeProgVersion(ptagDesc * desc,langType language CTAGS_ATTR_UNUSED,const void * data CTAGS_ATTR_UNUSED)76 static bool ptagMakeProgVersion (ptagDesc *desc, langType language CTAGS_ATTR_UNUSED,
77 								 const void *data CTAGS_ATTR_UNUSED)
78 {
79 	const char* repoinfo = ctags_repoinfo? ctags_repoinfo: "";
80 	return writePseudoTag (desc, PROGRAM_VERSION, repoinfo, NULL);
81 }
82 
83 #ifdef HAVE_ICONV
ptagMakeFileEncoding(ptagDesc * desc,langType language CTAGS_ATTR_UNUSED,const void * data)84 static bool ptagMakeFileEncoding (ptagDesc *desc, langType language CTAGS_ATTR_UNUSED,
85 								  const void *data)
86 {
87 	const optionValues *opt = data;
88 	if (! opt->outputEncoding)
89 		return false;
90 
91 	return writePseudoTag (desc, opt->outputEncoding, "", NULL);
92 }
93 #endif
94 
ptagMakeKindSeparators(ptagDesc * desc,langType language,const void * data CTAGS_ATTR_UNUSED)95 static bool ptagMakeKindSeparators (ptagDesc *desc, langType language,
96 									const void *data CTAGS_ATTR_UNUSED)
97 {
98 	return makeKindSeparatorsPseudoTags (language, desc);
99 }
100 
ptagMakeKindDescriptions(ptagDesc * desc,langType language,const void * data CTAGS_ATTR_UNUSED)101 static bool ptagMakeKindDescriptions (ptagDesc *desc, langType language,
102 									  const void *data CTAGS_ATTR_UNUSED)
103 {
104 	return makeKindDescriptionsPseudoTags (language, desc);
105 }
106 
ptagMakeFieldDescriptions(ptagDesc * desc,langType language,const void * data CTAGS_ATTR_UNUSED)107 static bool ptagMakeFieldDescriptions (ptagDesc *desc, langType language,
108 									   const void *data CTAGS_ATTR_UNUSED)
109 {
110 	return makeFieldDescriptionsPseudoTags (language, desc);
111 }
112 
ptagMakeExtraDescriptions(ptagDesc * desc,langType language,const void * data CTAGS_ATTR_UNUSED)113 static bool ptagMakeExtraDescriptions (ptagDesc *desc, langType language,
114 									   const void *data CTAGS_ATTR_UNUSED)
115 {
116 	return makeExtraDescriptionsPseudoTags (language, desc);
117 }
118 
ptagMakeRoleDescriptions(ptagDesc * desc,langType language,const void * data CTAGS_ATTR_UNUSED)119 static bool ptagMakeRoleDescriptions (ptagDesc *desc, langType language,
120 									  const void *data CTAGS_ATTR_UNUSED)
121 {
122 	return makeRoleDescriptionsPseudoTags (language, desc);
123 }
124 
ptagMakeProcCwd(ptagDesc * desc,langType language,const void * data CTAGS_ATTR_UNUSED)125 static bool ptagMakeProcCwd (ptagDesc *desc, langType language,
126 									   const void *data CTAGS_ATTR_UNUSED)
127 {
128 	return writePseudoTag (desc, CurrentDirectory, "", NULL);
129 }
130 
131 static ptagDesc ptagDescs [] = {
132 	{
133 	  /* The prefix is not "TAG_".
134 	     Only --output-format=json use this ptag. */
135 	  false, "JSON_OUTPUT_VERSION",
136 	  "the version of json output stream format",
137 	  ptagMakeJsonOutputVersion,
138 	  PTAGF_COMMON },
139 	{ true, "TAG_FILE_FORMAT",
140 	  "the version of tags file format",
141 	  ptagMakeFormat,
142 	  PTAGF_COMMON },
143 	{ true, "TAG_FILE_SORTED",
144 	  "how tags are sorted",
145 	  ptagMakeHowSorted,
146 	  PTAGF_COMMON },
147 	{ true, "TAG_PROGRAM_AUTHOR",
148 	  "the author of this ctags implementation",
149 	  ptagMakeAuthor,
150 	  PTAGF_COMMON },
151 	{ true, "TAG_PROGRAM_NAME",
152 	  "the name of this ctags implementation",
153 	  ptagMakeProgName,
154 	  PTAGF_COMMON },
155 	{ true, "TAG_PROGRAM_URL",
156 	  "the official site URL of this ctags implementation",
157 	  ptagMakeProgURL,
158 	  PTAGF_COMMON },
159 	{ true, "TAG_PROGRAM_VERSION",
160 	  "the version of this ctags implementation",
161 	  ptagMakeProgVersion,
162 	  PTAGF_COMMON },
163 #ifdef HAVE_ICONV
164 	{ true, "TAG_FILE_ENCODING",
165 	  "the encoding used in output tags file",
166 	  ptagMakeFileEncoding,
167 	  PTAGF_COMMON },
168 #endif
169 	{ false, "TAG_KIND_SEPARATOR",
170 	  "the separators used in kinds",
171 	  ptagMakeKindSeparators,
172 	  PTAGF_PARSER },
173 	{ false, "TAG_KIND_DESCRIPTION",
174 	  "the letters, names and descriptions of enabled kinds in the language",
175 	  ptagMakeKindDescriptions,
176 	  PTAGF_PARSER },
177 	{ false, "TAG_FIELD_DESCRIPTION",
178 	  "the names and descriptions of enabled fields",
179 	  ptagMakeFieldDescriptions,
180 	  PTAGF_COMMON|PTAGF_PARSER },
181 	{ false, "TAG_EXTRA_DESCRIPTION",
182 	  "the names and descriptions of enabled extras",
183 	  ptagMakeExtraDescriptions,
184 	  PTAGF_COMMON|PTAGF_PARSER },
185 	{ false, "TAG_ROLE_DESCRIPTION",
186 	  "the names and descriptions of enabled roles",
187 	  ptagMakeRoleDescriptions,
188 	  PTAGF_PARSER },
189 	{ true, "TAG_OUTPUT_MODE",
190 	  "the output mode: u-ctags or e-ctags",
191 	  ptagMakeCtagsOutputMode,
192 	  PTAGF_COMMON },
193 	{ true, "TAG_OUTPUT_FILESEP",
194 	  "the separator used in file name (slash or backslash)",
195 	  ptagMakeCtagsOutputFilesep,
196 	  PTAGF_COMMON },
197 	{ true, "TAG_PATTERN_LENGTH_LIMIT",
198 	  "the limit of pattern length",
199 	  ptagMakePatternLengthLimit,
200 	  PTAGF_COMMON },
201 	{ true, "TAG_PROC_CWD",
202 	  "the current working directory of the tags generator",
203 	  ptagMakeProcCwd,
204 	  PTAGF_COMMON },
205 	{ true, "TAG_OUTPUT_EXCMD",
206 	  "the excmd: number, pattern, mixed, or combine",
207 	  ptagMakeCtagsOutputExcmd,
208 	  PTAGF_COMMON },
209 };
210 
makePtagIfEnabled(ptagType type,langType language,const void * data)211 extern bool makePtagIfEnabled (ptagType type, langType language, const void *data)
212 {
213 	ptagDesc *desc;
214 
215 	Assert (0 <= type && type < PTAG_COUNT);
216 
217 	desc = ptagDescs + type;
218 	if (desc->enabled)
219 		return desc->makeTag (desc, language, data);
220 	else
221 		return false;
222 }
223 
isPtagEnabled(ptagType type)224 extern bool isPtagEnabled (ptagType type)
225 {
226 	ptagDesc *desc;
227 
228 	Assert (0 <= type && type < PTAG_COUNT);
229 
230 	desc = ptagDescs + type;
231 	return desc->enabled;
232 
233 }
234 
enablePtag(ptagType type,bool state)235 extern bool enablePtag (ptagType type, bool state)
236 {
237 	bool oldstate;
238 	ptagDesc *desc;
239 
240 	Assert (0 <= type && type < PTAG_COUNT);
241 
242 	desc = ptagDescs + type;
243 	oldstate = desc->enabled;
244 	desc->enabled = state;
245 	return oldstate;
246 }
247 
getPtagDesc(ptagType type)248 extern ptagDesc* getPtagDesc (ptagType type)
249 {
250 	if (type == PTAG_UNKNOWN
251 	    || type >= PTAG_COUNT)
252 		return NULL;
253 
254 	return ptagDescs + type;
255 }
256 
getPtagTypeForName(const char * name)257 extern ptagType getPtagTypeForName (const char *name)
258 {
259 	int i;
260 
261 	Assert (name);
262 	for (i = 0; i < PTAG_COUNT; i++)
263 		if (strcmp (ptagDescs [i].name, name) == 0)
264 			return i;
265 	return PTAG_UNKNOWN;
266 }
267 
isPtagCommonInParsers(ptagType type)268 extern bool isPtagCommonInParsers  (ptagType type)
269 {
270 	ptagDesc* pdesc = getPtagDesc (type);
271 	return pdesc->flags & PTAGF_COMMON;
272 }
273 
isPtagParserSpecific(ptagType type)274 extern bool isPtagParserSpecific (ptagType type)
275 {
276 	ptagDesc* pdesc = getPtagDesc (type);
277 	return pdesc->flags & PTAGF_PARSER;
278 }
279 
ptagCompare(struct colprintLine * a,struct colprintLine * b)280 static int ptagCompare (struct colprintLine *a, struct colprintLine *b)
281 {
282 	const char *a_name = colprintLineGetColumn (a, 0);
283 	const char *b_name = colprintLineGetColumn (b, 0);
284 	return strcmp(a_name, b_name);
285 }
286 
printPtags(bool withListHeader,bool machinable,FILE * fp)287 extern void printPtags (bool withListHeader, bool machinable, FILE *fp)
288 {
289 	struct colprintTable *table = colprintTableNew ("L:NAME",
290 													"L:ENABLED",
291 													"L:DESCRIPTION",
292 													NULL);
293 	for (unsigned int i = 0; i < PTAG_COUNT; i++)
294 	{
295 		struct colprintLine *line = colprintTableGetNewLine (table);
296 		colprintLineAppendColumnCString (line, ptagDescs[i].name);
297 		colprintLineAppendColumnCString (line, ptagDescs[i].enabled
298 										 ? "on"
299 										 : "off");
300 		colprintLineAppendColumnCString (line, ptagDescs[i].description);
301 	}
302 
303 	colprintTableSort (table, ptagCompare);
304 	colprintTablePrint (table, 0, withListHeader, machinable, fp);
305 	colprintTableDelete (table);
306 }
307