xref: /Universal-ctags/main/writer-etags.c (revision d5406d79490b3ee2dfcbe86d9609fdbe60175ceb)
15176f023SMasatake YAMATO /*
25176f023SMasatake YAMATO *   Copyright (c) 1998-2002, Darren Hiebert
35176f023SMasatake YAMATO *
45176f023SMasatake YAMATO *   This source code is released for free distribution under the terms of the
55176f023SMasatake YAMATO *   GNU General Public License version 2 or (at your option) any later version.
65176f023SMasatake YAMATO *
75176f023SMasatake YAMATO *   External interface to entry.c
85176f023SMasatake YAMATO */
95176f023SMasatake YAMATO 
105176f023SMasatake YAMATO #include "general.h"  /* must always come first */
115176f023SMasatake YAMATO 
125176f023SMasatake YAMATO #include <string.h>
135176f023SMasatake YAMATO 
145176f023SMasatake YAMATO #include "debug.h"
158cbf052bSMasatake YAMATO #include "entry_p.h"
165176f023SMasatake YAMATO #include "mio.h"
1721996d92SMasatake YAMATO #include "options_p.h"
18*d5406d79SMasatake YAMATO #include "parse.h"
19*d5406d79SMasatake YAMATO #include "parse_p.h"
205176f023SMasatake YAMATO #include "read.h"
21934a26beSMasatake YAMATO #include "routines.h"
2229e40fb6SMasatake YAMATO #include "routines_p.h"
235176f023SMasatake YAMATO #include "vstring.h"
24285b4dfeSMasatake YAMATO #include "writer_p.h"
255176f023SMasatake YAMATO 
265176f023SMasatake YAMATO 
274b7a1543SMasatake YAMATO #define ETAGS_FILE  "TAGS"
284b7a1543SMasatake YAMATO 
294b7a1543SMasatake YAMATO 
305053d6adSMasatake YAMATO static int writeEtagsEntry  (tagWriter *writer, MIO * mio, const tagEntryInfo *const tag,
315053d6adSMasatake YAMATO 							 void *clientData CTAGS_ATTR_UNUSED);
325053d6adSMasatake YAMATO static void *beginEtagsFile (tagWriter *writer, MIO * mio,
335053d6adSMasatake YAMATO 							 void *clientData CTAGS_ATTR_UNUSED);
345053d6adSMasatake YAMATO static bool  endEtagsFile   (tagWriter *writer, MIO * mio, const char* filename,
355053d6adSMasatake YAMATO 							 void *clientData CTAGS_ATTR_UNUSED);
365176f023SMasatake YAMATO 
375176f023SMasatake YAMATO tagWriter etagsWriter = {
385176f023SMasatake YAMATO 	.writeEntry = writeEtagsEntry,
395176f023SMasatake YAMATO 	.writePtagEntry = NULL,
405176f023SMasatake YAMATO 	.preWriteEntry = beginEtagsFile,
415176f023SMasatake YAMATO 	.postWriteEntry = endEtagsFile,
4267d1f12fSJiří Techet 	.rescanFailedEntry = NULL,
438182f840SMasatake YAMATO 	.treatFieldAsFixed = NULL,
444b7a1543SMasatake YAMATO 	.defaultFileName = ETAGS_FILE,
455176f023SMasatake YAMATO };
465176f023SMasatake YAMATO 
475176f023SMasatake YAMATO struct sEtags {
485176f023SMasatake YAMATO 	char *name;
495176f023SMasatake YAMATO 	MIO *mio;
505176f023SMasatake YAMATO 	size_t byteCount;
515176f023SMasatake YAMATO 	vString *vLine;
525176f023SMasatake YAMATO };
535176f023SMasatake YAMATO 
545176f023SMasatake YAMATO 
555176f023SMasatake YAMATO 
beginEtagsFile(tagWriter * writer CTAGS_ATTR_UNUSED,MIO * mio CTAGS_ATTR_UNUSED,void * clientData CTAGS_ATTR_UNUSED)565053d6adSMasatake YAMATO static void *beginEtagsFile (tagWriter *writer CTAGS_ATTR_UNUSED, MIO *mio CTAGS_ATTR_UNUSED,
575053d6adSMasatake YAMATO 							 void *clientData CTAGS_ATTR_UNUSED)
585176f023SMasatake YAMATO {
595176f023SMasatake YAMATO 	static struct sEtags etags = { NULL, NULL, 0, NULL };
605176f023SMasatake YAMATO 
615176f023SMasatake YAMATO 	etags.mio = tempFile ("w+b", &etags.name);
625176f023SMasatake YAMATO 	etags.byteCount = 0;
635176f023SMasatake YAMATO 	etags.vLine = vStringNew ();
645176f023SMasatake YAMATO 	return &etags;
655176f023SMasatake YAMATO }
665176f023SMasatake YAMATO 
endEtagsFile(tagWriter * writer,MIO * mainfp,const char * filename,void * clientData CTAGS_ATTR_UNUSED)67975c73faSMasatake YAMATO static bool endEtagsFile (tagWriter *writer,
685053d6adSMasatake YAMATO 						  MIO *mainfp, const char *filename,
695053d6adSMasatake YAMATO 						  void *clientData CTAGS_ATTR_UNUSED)
705176f023SMasatake YAMATO {
715176f023SMasatake YAMATO 	const char *line;
720479e0a2SMasatake YAMATO 	struct sEtags *etags = writer->private;
735176f023SMasatake YAMATO 
745176f023SMasatake YAMATO 	mio_printf (mainfp, "\f\n%s,%ld\n", filename, (long) etags->byteCount);
753d71bd5fSMasatake YAMATO 	setNumTagsAdded (numTagsAdded () + 1);
765176f023SMasatake YAMATO 	abort_if_ferror (mainfp);
775176f023SMasatake YAMATO 
785176f023SMasatake YAMATO 	if (etags->mio != NULL)
795176f023SMasatake YAMATO 	{
805176f023SMasatake YAMATO 		mio_rewind (etags->mio);
815176f023SMasatake YAMATO 
825176f023SMasatake YAMATO 		while ((line = readLineRaw (etags->vLine, etags->mio)) != NULL)
835176f023SMasatake YAMATO 			mio_puts (mainfp, line);
845176f023SMasatake YAMATO 
855176f023SMasatake YAMATO 		vStringDelete (etags->vLine);
86b978efd6SMasatake YAMATO 		mio_unref (etags->mio);
875176f023SMasatake YAMATO 		remove (etags->name);
885176f023SMasatake YAMATO 		eFree (etags->name);
895176f023SMasatake YAMATO 		etags->vLine = NULL;
905176f023SMasatake YAMATO 		etags->mio = NULL;
915176f023SMasatake YAMATO 		etags->name = NULL;
925176f023SMasatake YAMATO 	}
93975c73faSMasatake YAMATO 	return false;
945176f023SMasatake YAMATO }
955176f023SMasatake YAMATO 
ada_suffix(const tagEntryInfo * const tag,const char * const line)96*d5406d79SMasatake YAMATO static const char* ada_suffix (const tagEntryInfo *const tag, const char *const line)
97*d5406d79SMasatake YAMATO {
98*d5406d79SMasatake YAMATO 	kindDefinition *kdef = getLanguageKind(tag->langType, tag->kindIndex);
99*d5406d79SMasatake YAMATO 
100*d5406d79SMasatake YAMATO 	Assert (kdef);
101*d5406d79SMasatake YAMATO 
102*d5406d79SMasatake YAMATO 	/* Mapping from ctags' kind letter to etags's suffix string.
103*d5406d79SMasatake YAMATO 	 * See https://www.gnu.org/software/emacs/manual/html_node/emacs/Tag-Syntax.html */
104*d5406d79SMasatake YAMATO 	switch (kdef->letter)
105*d5406d79SMasatake YAMATO 	{
106*d5406d79SMasatake YAMATO 	case 'p':
107*d5406d79SMasatake YAMATO 	case 'k':
108*d5406d79SMasatake YAMATO 		return "/b";
109*d5406d79SMasatake YAMATO 	case 'K':
110*d5406d79SMasatake YAMATO 		return "/k";
111*d5406d79SMasatake YAMATO 	case 'P':
112*d5406d79SMasatake YAMATO 		return "/s";
113*d5406d79SMasatake YAMATO 	case 't':
114*d5406d79SMasatake YAMATO 		return "/t";
115*d5406d79SMasatake YAMATO 	case 'R':
116*d5406d79SMasatake YAMATO 	case 'r':
117*d5406d79SMasatake YAMATO 	{
118*d5406d79SMasatake YAMATO 		/* Unlike etags, ctags uses the procedure kind for both
119*d5406d79SMasatake YAMATO 		 * procedures and functions. So in the level, emitting a tag,
120*d5406d79SMasatake YAMATO 		 * we cannot distinguish whether a tag is for a procedureor a
121*d5406d79SMasatake YAMATO 		 * function.
122*d5406d79SMasatake YAMATO 		 *
123*d5406d79SMasatake YAMATO 		 * If the typeref field of the tag is filled, we can say the tag
124*d5406d79SMasatake YAMATO 		 * is for a function. However, Ada parser doesn't implement the
125*d5406d79SMasatake YAMATO 		 * typeref field yet, and implementing it is not so easy.
126*d5406d79SMasatake YAMATO 		 *
127*d5406d79SMasatake YAMATO 		 * So we have to take an unclean way here: scanning the input
128*d5406d79SMasatake YAMATO 		 * line again.
129*d5406d79SMasatake YAMATO 		 * FIXME: remove the scanning code and implement the typeref field
130*d5406d79SMasatake YAMATO 		 * in Ada.
131*d5406d79SMasatake YAMATO 		 */
132*d5406d79SMasatake YAMATO 		const char *r = strstr (line, "return");
133*d5406d79SMasatake YAMATO 		const char *f = strstr (line, "function");
134*d5406d79SMasatake YAMATO 		const char *p = strstr (line, "procedure");
135*d5406d79SMasatake YAMATO 		if (r && f)
136*d5406d79SMasatake YAMATO 			return "/f";
137*d5406d79SMasatake YAMATO 		else if (p && !r)
138*d5406d79SMasatake YAMATO 			return "/p";
139*d5406d79SMasatake YAMATO 		return "";				/* Unknown */
140*d5406d79SMasatake YAMATO 	}
141*d5406d79SMasatake YAMATO 	default:
142*d5406d79SMasatake YAMATO 		return "";
143*d5406d79SMasatake YAMATO 	}
144*d5406d79SMasatake YAMATO }
145*d5406d79SMasatake YAMATO 
writeEtagsEntry(tagWriter * writer,MIO * mio,const tagEntryInfo * const tag,void * clientData CTAGS_ATTR_UNUSED)1460479e0a2SMasatake YAMATO static int writeEtagsEntry (tagWriter *writer,
1475053d6adSMasatake YAMATO 							MIO * mio, const tagEntryInfo *const tag,
1485053d6adSMasatake YAMATO 							void *clientData CTAGS_ATTR_UNUSED)
1495176f023SMasatake YAMATO {
150*d5406d79SMasatake YAMATO 	langType adaLangType = getNamedLanguage ("Ada", 0);
151*d5406d79SMasatake YAMATO 	Assert (adaLangType != LANG_IGNORE);
152*d5406d79SMasatake YAMATO 
1535176f023SMasatake YAMATO 	int length;
1540479e0a2SMasatake YAMATO 	struct sEtags *etags = writer->private;
1555176f023SMasatake YAMATO 
1565176f023SMasatake YAMATO 	mio = etags->mio;
1575176f023SMasatake YAMATO 
1585176f023SMasatake YAMATO 	if (tag->isFileEntry)
1595176f023SMasatake YAMATO 		length = mio_printf (mio, "\177%s\001%lu,0\n",
1605176f023SMasatake YAMATO 				tag->name, tag->lineNumber);
1615176f023SMasatake YAMATO 	else
1625176f023SMasatake YAMATO 	{
16307087623SMasatake YAMATO 		size_t len;
1645176f023SMasatake YAMATO 		long seekValue;
1655176f023SMasatake YAMATO 		char *const line =
166c8c97f1cSMasatake YAMATO 				readLineFromBypassForTag (etags->vLine, tag, &seekValue);
1675d73ebeeSColomban Wendling 		if (line == NULL || line [0] == '\0')
1685176f023SMasatake YAMATO 			return 0;
1695176f023SMasatake YAMATO 
17007087623SMasatake YAMATO 		len = strlen (line);
17107087623SMasatake YAMATO 
1720e70b227SMasatake YAMATO 		if (tag->truncateLineAfterTag)
1730e70b227SMasatake YAMATO 			truncateTagLineAfterTag (line, tag->name, true);
1745d73ebeeSColomban Wendling 		else if (line [len - 1] == '\n')
1755d73ebeeSColomban Wendling 			line [--len] = '\0';
17607087623SMasatake YAMATO 
177b4d9e03fSColomban Wendling 		if (Option.patternLengthLimit > 0 && Option.patternLengthLimit < len)
1784f39a655SColomban Wendling 		{
1794f39a655SColomban Wendling 			unsigned int truncationLength = Option.patternLengthLimit;
1804f39a655SColomban Wendling 
1814f39a655SColomban Wendling 			/* don't cut in the middle of a UTF-8 character, but don't allow
1824f39a655SColomban Wendling 			 * for more than one extra character in case it actually wasn't
1834f39a655SColomban Wendling 			 * UTF-8.  See also entry.c:appendInputLine() */
1845d73ebeeSColomban Wendling 			while (truncationLength < len &&
1854f39a655SColomban Wendling 			       truncationLength < Option.patternLengthLimit + 3 &&
1864f39a655SColomban Wendling 			       (((unsigned char) line[truncationLength]) & 0xc0) == 0x80)
1874f39a655SColomban Wendling 				truncationLength++;
1884f39a655SColomban Wendling 
1894f39a655SColomban Wendling 			line [truncationLength] = '\0';
1904f39a655SColomban Wendling 		}
1915176f023SMasatake YAMATO 
192*d5406d79SMasatake YAMATO 		length = mio_printf (mio, "%s\177%s%s\001%lu,%ld\n", line,
193*d5406d79SMasatake YAMATO 							 tag->name,
194*d5406d79SMasatake YAMATO 							 (tag->langType == adaLangType)
195*d5406d79SMasatake YAMATO 							 ? ada_suffix (tag, line)
196*d5406d79SMasatake YAMATO 							 : "",
197*d5406d79SMasatake YAMATO 							 tag->lineNumber, seekValue);
1985176f023SMasatake YAMATO 	}
1995176f023SMasatake YAMATO 	etags->byteCount += length;
2005176f023SMasatake YAMATO 
2015176f023SMasatake YAMATO 	return length;
2025176f023SMasatake YAMATO }
203