xref: /Universal-ctags/main/promise.c (revision 5066e2feadfa1f2d1826125a60095f6246895369)
14fa68e36SMasatake YAMATO /*
24fa68e36SMasatake YAMATO  *
34fa68e36SMasatake YAMATO  *  Copyright (c) 2016, Red Hat, Inc.
44fa68e36SMasatake YAMATO  *  Copyright (c) 2016, Masatake YAMATO
54fa68e36SMasatake YAMATO  *
64fa68e36SMasatake YAMATO  *  Author: Masatake YAMATO <yamato@redhat.com>
74fa68e36SMasatake YAMATO  *
84fa68e36SMasatake YAMATO  *   This source code is released for free distribution under the terms of the
94fa68e36SMasatake YAMATO  *   GNU General Public License version 2 or (at your option) any later version.
104fa68e36SMasatake YAMATO  *
114fa68e36SMasatake YAMATO  */
124fa68e36SMasatake YAMATO 
134fa68e36SMasatake YAMATO #include "general.h"
140d502ef0SMasatake YAMATO #include "parse_p.h"
154fa68e36SMasatake YAMATO #include "promise.h"
166014fe81SColomban Wendling #include "promise_p.h"
1711e58e48SMasatake YAMATO #include "ptrarray.h"
184fa68e36SMasatake YAMATO #include "debug.h"
19b5df137eSMasatake YAMATO #include "read_p.h"
20be62b73fSMasatake YAMATO #include "trashbox.h"
21090d5581SMasatake YAMATO #include "xtag.h"
22db20bea4SMasatake YAMATO #include "numarray.h"
2329e40fb6SMasatake YAMATO #include "routines.h"
24*5066e2feSMasatake YAMATO #include "options.h"
254fa68e36SMasatake YAMATO 
26db20bea4SMasatake YAMATO #include <string.h>
274fa68e36SMasatake YAMATO 
284fa68e36SMasatake YAMATO struct promise {
294fa68e36SMasatake YAMATO 	langType lang;
304fa68e36SMasatake YAMATO 	unsigned long startLine;
31ef722b09SMasatake YAMATO 	long startCharOffset;
324fa68e36SMasatake YAMATO 	unsigned long endLine;
33ef722b09SMasatake YAMATO 	long endCharOffset;
344fa68e36SMasatake YAMATO 	unsigned long sourceLineOffset;
35631d6aa6SMasatake YAMATO 	int parent_promise;
3611e58e48SMasatake YAMATO 	ptrArray *modifiers;
3711e58e48SMasatake YAMATO };
3811e58e48SMasatake YAMATO 
3911e58e48SMasatake YAMATO typedef void ( *promiseInputModifier) (unsigned char * input,
4011e58e48SMasatake YAMATO 									   size_t size,
4111e58e48SMasatake YAMATO 									   unsigned long startLine, long startCharOffset,
4211e58e48SMasatake YAMATO 									   unsigned long endLine, long endCharOffset,
4311e58e48SMasatake YAMATO 									   void *data);
4411e58e48SMasatake YAMATO typedef void ( *promiseDestroyAttachedData) (void *data);
4511e58e48SMasatake YAMATO 
4611e58e48SMasatake YAMATO struct modifier {
4711e58e48SMasatake YAMATO 	promiseInputModifier modifier;
4811e58e48SMasatake YAMATO 	promiseDestroyAttachedData destroyData;
4911e58e48SMasatake YAMATO 	void *data;
504fa68e36SMasatake YAMATO };
514fa68e36SMasatake YAMATO 
524fa68e36SMasatake YAMATO static struct promise *promises;
534fa68e36SMasatake YAMATO static int promise_count;
544fa68e36SMasatake YAMATO static int promise_allocated;
554fa68e36SMasatake YAMATO 
56631d6aa6SMasatake YAMATO #define NO_PROMISE -1
57631d6aa6SMasatake YAMATO static int current_promise = NO_PROMISE;
58631d6aa6SMasatake YAMATO 
5911e58e48SMasatake YAMATO static void attachPromiseModifier (int promise,
6011e58e48SMasatake YAMATO 								   promiseInputModifier modifier,
6111e58e48SMasatake YAMATO 								   promiseDestroyAttachedData destroyData,
6211e58e48SMasatake YAMATO 								   void *data);
6311e58e48SMasatake YAMATO 
6411e58e48SMasatake YAMATO 
makePromise(const char * parser,unsigned long startLine,long startCharOffset,unsigned long endLine,long endCharOffset,unsigned long sourceLineOffset)654fa68e36SMasatake YAMATO int  makePromise   (const char *parser,
66ef722b09SMasatake YAMATO 		    unsigned long startLine, long startCharOffset,
67ef722b09SMasatake YAMATO 		    unsigned long endLine, long endCharOffset,
684fa68e36SMasatake YAMATO 		    unsigned long sourceLineOffset)
694fa68e36SMasatake YAMATO {
704fa68e36SMasatake YAMATO 	struct promise *p;
714fa68e36SMasatake YAMATO 	int r;
7289a71f3bSMasatake YAMATO 	langType lang = LANG_IGNORE;
734fa68e36SMasatake YAMATO 
74*5066e2feSMasatake YAMATO 	verbose("makePromise: %s start(line: %lu, offset: %lu, srcline: %lu), end(line: %lu, offset: %lu)\n",
75*5066e2feSMasatake YAMATO 			parser? parser: "*", startLine, startCharOffset, sourceLineOffset,
76*5066e2feSMasatake YAMATO 			endLine, endCharOffset);
77*5066e2feSMasatake YAMATO 
782fa69c1bSMasatake YAMATO 	if ((!isThinStreamSpec(startLine,
792fa69c1bSMasatake YAMATO 						   startCharOffset,
802fa69c1bSMasatake YAMATO 						   endLine,
812fa69c1bSMasatake YAMATO 						   endCharOffset,
822fa69c1bSMasatake YAMATO 						   sourceLineOffset))
8346a698ceSMasatake YAMATO 		&& ( !isXtagEnabled (XTAG_GUEST)))
84090d5581SMasatake YAMATO 		return -1;
85090d5581SMasatake YAMATO 
8689a71f3bSMasatake YAMATO 	if (parser)
8789a71f3bSMasatake YAMATO 	{
884fa68e36SMasatake YAMATO 		lang = getNamedLanguage (parser, 0);
894fa68e36SMasatake YAMATO 		if (lang == LANG_IGNORE)
904fa68e36SMasatake YAMATO 			return -1;
9189a71f3bSMasatake YAMATO 	}
924fa68e36SMasatake YAMATO 
934fa68e36SMasatake YAMATO 	if ( promise_count == promise_allocated)
944fa68e36SMasatake YAMATO 	{
954fa68e36SMasatake YAMATO 		size_t c = promise_allocated? (promise_allocated * 2): 8;
96be62b73fSMasatake YAMATO 		if (promises)
97be62b73fSMasatake YAMATO 			DEFAULT_TRASH_BOX_TAKE_BACK(promises);
984fa68e36SMasatake YAMATO 		promises = xRealloc (promises, c, struct promise);
99be62b73fSMasatake YAMATO 		DEFAULT_TRASH_BOX(promises, eFree);
1004fa68e36SMasatake YAMATO 		promise_allocated = c;
1014fa68e36SMasatake YAMATO 	}
1024fa68e36SMasatake YAMATO 
1034fa68e36SMasatake YAMATO 	p = promises + promise_count;
104631d6aa6SMasatake YAMATO 	p->parent_promise = current_promise;
1054fa68e36SMasatake YAMATO 	p->lang = lang;
1064fa68e36SMasatake YAMATO 	p->startLine = startLine;
1074fa68e36SMasatake YAMATO 	p->startCharOffset = startCharOffset;
1084fa68e36SMasatake YAMATO 	p->endLine = endLine;
1094fa68e36SMasatake YAMATO 	p->endCharOffset = endCharOffset;
1104fa68e36SMasatake YAMATO 	p->sourceLineOffset = sourceLineOffset;
11111e58e48SMasatake YAMATO 	p->modifiers = NULL;
1124fa68e36SMasatake YAMATO 
1134fa68e36SMasatake YAMATO 	r = promise_count;
1144fa68e36SMasatake YAMATO 	promise_count++;
1154fa68e36SMasatake YAMATO 	return r;
1164fa68e36SMasatake YAMATO }
1174fa68e36SMasatake YAMATO 
freeModifier(void * data)11811e58e48SMasatake YAMATO static void freeModifier (void *data)
11911e58e48SMasatake YAMATO {
12011e58e48SMasatake YAMATO 	struct modifier *m = data;
12111e58e48SMasatake YAMATO 	m->destroyData(m->data);
12211e58e48SMasatake YAMATO 	eFree (m);
12311e58e48SMasatake YAMATO }
12411e58e48SMasatake YAMATO 
attachPromiseModifier(int promise,promiseInputModifier modifier,promiseDestroyAttachedData destroyData,void * data)12511e58e48SMasatake YAMATO static void attachPromiseModifier (int promise,
12611e58e48SMasatake YAMATO 								   promiseInputModifier modifier,
12711e58e48SMasatake YAMATO 								   promiseDestroyAttachedData destroyData,
12811e58e48SMasatake YAMATO 								   void *data)
12911e58e48SMasatake YAMATO {
13011e58e48SMasatake YAMATO 	struct modifier *m = xMalloc (1, struct modifier);
13111e58e48SMasatake YAMATO 
13211e58e48SMasatake YAMATO 	m->modifier = modifier;
13311e58e48SMasatake YAMATO 	m->destroyData = destroyData;
13411e58e48SMasatake YAMATO 	m->data = data;
13511e58e48SMasatake YAMATO 
13611e58e48SMasatake YAMATO 	struct promise *p = promises + promise;
13711e58e48SMasatake YAMATO 	if (!p->modifiers)
13811e58e48SMasatake YAMATO 		p->modifiers = ptrArrayNew(freeModifier);
13911e58e48SMasatake YAMATO 
14011e58e48SMasatake YAMATO 	ptrArrayAdd (p->modifiers, m);
14111e58e48SMasatake YAMATO }
14211e58e48SMasatake YAMATO 
freeModifiers(int promise)14311e58e48SMasatake YAMATO static void freeModifiers(int promise)
14411e58e48SMasatake YAMATO {
14511e58e48SMasatake YAMATO 	for (int i = promise; i < promise_count; i++)
14611e58e48SMasatake YAMATO 	{
14711e58e48SMasatake YAMATO 		struct promise *p = promises + promise;
14811e58e48SMasatake YAMATO 		if (p->modifiers)
14911e58e48SMasatake YAMATO 		{
15011e58e48SMasatake YAMATO 			ptrArrayDelete (p->modifiers);
15111e58e48SMasatake YAMATO 			p->modifiers = NULL;
15211e58e48SMasatake YAMATO 		}
15311e58e48SMasatake YAMATO 	}
15411e58e48SMasatake YAMATO }
15511e58e48SMasatake YAMATO 
breakPromisesAfter(int promise)1564fa68e36SMasatake YAMATO void breakPromisesAfter (int promise)
1574fa68e36SMasatake YAMATO {
1584fa68e36SMasatake YAMATO 	Assert (promise_count >= promise);
15911e58e48SMasatake YAMATO 	if (promise == NO_PROMISE)
16011e58e48SMasatake YAMATO 		promise = 0;
1614fa68e36SMasatake YAMATO 
16211e58e48SMasatake YAMATO 	freeModifiers(promise);
1634fa68e36SMasatake YAMATO 	promise_count = promise;
1644fa68e36SMasatake YAMATO }
1654fa68e36SMasatake YAMATO 
forcePromises(void)166ce990805SThomas Braun bool forcePromises (void)
1674fa68e36SMasatake YAMATO {
1684fa68e36SMasatake YAMATO 	int i;
169ce990805SThomas Braun 	bool tagFileResized = false;
170090d5581SMasatake YAMATO 
1714fa68e36SMasatake YAMATO 	for (i = 0; i < promise_count; ++i)
1724fa68e36SMasatake YAMATO 	{
173631d6aa6SMasatake YAMATO 		current_promise = i;
1744fa68e36SMasatake YAMATO 		struct promise *p = promises + i;
17589a71f3bSMasatake YAMATO 
17689a71f3bSMasatake YAMATO 		if (p->lang != LANG_IGNORE && isLanguageEnabled (p->lang))
1774fa68e36SMasatake YAMATO 			tagFileResized = runParserInNarrowedInputStream (p->lang,
1784fa68e36SMasatake YAMATO 															 p->startLine,
1794fa68e36SMasatake YAMATO 															 p->startCharOffset,
1804fa68e36SMasatake YAMATO 															 p->endLine,
1814fa68e36SMasatake YAMATO 															 p->endCharOffset,
18211e58e48SMasatake YAMATO 															 p->sourceLineOffset,
18311e58e48SMasatake YAMATO 															 i)
184ce990805SThomas Braun 				? true
1854fa68e36SMasatake YAMATO 				: tagFileResized;
1864fa68e36SMasatake YAMATO 	}
1874fa68e36SMasatake YAMATO 
18811e58e48SMasatake YAMATO 	freeModifiers (0);
189631d6aa6SMasatake YAMATO 	current_promise  = NO_PROMISE;
1904fa68e36SMasatake YAMATO 	promise_count = 0;
1914fa68e36SMasatake YAMATO 	return tagFileResized;
1924fa68e36SMasatake YAMATO }
1934fa68e36SMasatake YAMATO 
1944fa68e36SMasatake YAMATO 
getLastPromise(void)1954fa68e36SMasatake YAMATO int getLastPromise (void)
1964fa68e36SMasatake YAMATO {
1974fa68e36SMasatake YAMATO 	return promise_count - 1;
1984fa68e36SMasatake YAMATO }
19911e58e48SMasatake YAMATO 
fill_or_skip(unsigned char * input,unsigned char * input_end,bool filling)200db20bea4SMasatake YAMATO static unsigned char* fill_or_skip (unsigned char *input, unsigned char *input_end, bool filling)
201db20bea4SMasatake YAMATO {
202db20bea4SMasatake YAMATO 	if ( !(input < input_end))
203db20bea4SMasatake YAMATO 		return NULL;
204db20bea4SMasatake YAMATO 
205db20bea4SMasatake YAMATO 	unsigned char *next = memchr(input, '\n', input_end - input);
206db20bea4SMasatake YAMATO 	if (next)
207db20bea4SMasatake YAMATO 	{
208db20bea4SMasatake YAMATO 		if (filling)
209db20bea4SMasatake YAMATO 			memset(input, ' ', next - input);
210db20bea4SMasatake YAMATO 		input = next + 1;
211db20bea4SMasatake YAMATO 		if (input == input_end)
212db20bea4SMasatake YAMATO 			return NULL;
213db20bea4SMasatake YAMATO 		else
214db20bea4SMasatake YAMATO 			return input;
215db20bea4SMasatake YAMATO 	}
216db20bea4SMasatake YAMATO 	else
217db20bea4SMasatake YAMATO 	{
218db20bea4SMasatake YAMATO 		if (filling)
219db20bea4SMasatake YAMATO 			memset(input, ' ', input_end - input);
220db20bea4SMasatake YAMATO 		return NULL;
221db20bea4SMasatake YAMATO 	}
222db20bea4SMasatake YAMATO }
223db20bea4SMasatake YAMATO 
line_filler(unsigned char * input,size_t size,unsigned long startLine,long startCharOffset,unsigned long endLine,long endCharOffset,void * data)224db20bea4SMasatake YAMATO static void line_filler (unsigned char *input, size_t size,
225db20bea4SMasatake YAMATO 						 unsigned long startLine, long startCharOffset,
226db20bea4SMasatake YAMATO 						 unsigned long endLine, long endCharOffset,
227db20bea4SMasatake YAMATO 						 void *data)
228db20bea4SMasatake YAMATO {
229db20bea4SMasatake YAMATO 	ulongArray *lines = data;
230db20bea4SMasatake YAMATO 	unsigned int start_index, end_index;
2314c64e833SMasatake YAMATO 	unsigned int i;
232db20bea4SMasatake YAMATO 
233db20bea4SMasatake YAMATO 	for (i = 0; i < ulongArrayCount (lines); i++)
234db20bea4SMasatake YAMATO 	{
235db20bea4SMasatake YAMATO 		unsigned long line = ulongArrayItem (lines, i);
236db20bea4SMasatake YAMATO 		if (line >= startLine)
237db20bea4SMasatake YAMATO 			break;
238db20bea4SMasatake YAMATO 	}
239db20bea4SMasatake YAMATO 	if (i == ulongArrayCount (lines))
240db20bea4SMasatake YAMATO 		return;
241db20bea4SMasatake YAMATO 	if (i > endLine)
242db20bea4SMasatake YAMATO 		return;
243db20bea4SMasatake YAMATO 	start_index = i;
244db20bea4SMasatake YAMATO 
245db20bea4SMasatake YAMATO 	for (; i < ulongArrayCount (lines); i++)
246db20bea4SMasatake YAMATO 	{
247db20bea4SMasatake YAMATO 		unsigned long line = ulongArrayItem (lines, i);
248db20bea4SMasatake YAMATO 		if (line > endLine)
249db20bea4SMasatake YAMATO 			break;
250db20bea4SMasatake YAMATO 	}
251db20bea4SMasatake YAMATO 	end_index = i;
252db20bea4SMasatake YAMATO 
253db20bea4SMasatake YAMATO 	unsigned long input_line = startLine;
254db20bea4SMasatake YAMATO 	for (i = start_index; i < end_index; i++)
255db20bea4SMasatake YAMATO 	{
256db20bea4SMasatake YAMATO 		unsigned long line = ulongArrayItem (lines, i);
257db20bea4SMasatake YAMATO 
258db20bea4SMasatake YAMATO 		while (1)
259db20bea4SMasatake YAMATO 		{
260db20bea4SMasatake YAMATO 			if (input_line == line)
261db20bea4SMasatake YAMATO 			{
262db20bea4SMasatake YAMATO 				input = fill_or_skip (input, input + size, true);
263db20bea4SMasatake YAMATO 				input_line++;
264db20bea4SMasatake YAMATO 				break;
265db20bea4SMasatake YAMATO 			}
266db20bea4SMasatake YAMATO 			else
267db20bea4SMasatake YAMATO 			{
268db20bea4SMasatake YAMATO 				input = fill_or_skip (input, input + size, false);
269db20bea4SMasatake YAMATO 				input_line++;
270db20bea4SMasatake YAMATO 			}
271db20bea4SMasatake YAMATO 		}
272db20bea4SMasatake YAMATO 	}
273db20bea4SMasatake YAMATO }
274db20bea4SMasatake YAMATO 
promiseAttachLineFiller(int promise,ulongArray * lines)275db20bea4SMasatake YAMATO void promiseAttachLineFiller (int promise, ulongArray *lines)
276db20bea4SMasatake YAMATO {
277db20bea4SMasatake YAMATO 	attachPromiseModifier (promise, line_filler,
278db20bea4SMasatake YAMATO 						   (promiseDestroyAttachedData)ulongArrayDelete,
279db20bea4SMasatake YAMATO 						   lines);
280db20bea4SMasatake YAMATO }
281db20bea4SMasatake YAMATO 
282db20bea4SMasatake YAMATO 
collectModifiers(int promise,ptrArray * modifiers)28311e58e48SMasatake YAMATO static void collectModifiers(int promise, ptrArray *modifiers)
28411e58e48SMasatake YAMATO {
28511e58e48SMasatake YAMATO 	while (promise != NO_PROMISE)
28611e58e48SMasatake YAMATO 	{
28711e58e48SMasatake YAMATO 		struct promise *p = promises + promise;
28811e58e48SMasatake YAMATO 		if (p->modifiers)
28911e58e48SMasatake YAMATO 		{
29011e58e48SMasatake YAMATO 			for (int i = ptrArrayCount(p->modifiers); i > 0; i--)
29111e58e48SMasatake YAMATO 			{
29211e58e48SMasatake YAMATO 				struct modifier *m = ptrArrayItem(p->modifiers, i - 1);
29311e58e48SMasatake YAMATO 				ptrArrayAdd (modifiers, m);
29411e58e48SMasatake YAMATO 			}
29511e58e48SMasatake YAMATO 		}
29611e58e48SMasatake YAMATO 		promise = p->parent_promise;
29711e58e48SMasatake YAMATO 	}
29811e58e48SMasatake YAMATO }
29911e58e48SMasatake YAMATO 
runModifiers(int promise,unsigned long startLine,long startCharOffset,unsigned long endLine,long endCharOffset,unsigned char * input,size_t size)30011e58e48SMasatake YAMATO void runModifiers (int promise,
30111e58e48SMasatake YAMATO 				   unsigned long startLine, long startCharOffset,
30211e58e48SMasatake YAMATO 				   unsigned long endLine, long endCharOffset,
30311e58e48SMasatake YAMATO 				   unsigned char *input,
30411e58e48SMasatake YAMATO 				   size_t size)
30511e58e48SMasatake YAMATO {
30611e58e48SMasatake YAMATO 	ptrArray *modifiers = ptrArrayNew (NULL);
30711e58e48SMasatake YAMATO 
30811e58e48SMasatake YAMATO 	collectModifiers (promise, modifiers);
30911e58e48SMasatake YAMATO 	for (int i = ptrArrayCount (modifiers); i > 0 ; i--)
31011e58e48SMasatake YAMATO 	{
31111e58e48SMasatake YAMATO 		struct modifier *m = ptrArrayItem (modifiers, i - 1);
31211e58e48SMasatake YAMATO 		m->modifier (input, size,
31311e58e48SMasatake YAMATO 					 startLine, startCharOffset,
31411e58e48SMasatake YAMATO 					 endLine, endCharOffset,
31511e58e48SMasatake YAMATO 					 m->data);
31611e58e48SMasatake YAMATO 	}
31711e58e48SMasatake YAMATO 	ptrArrayDelete (modifiers);
31811e58e48SMasatake YAMATO }
31989a71f3bSMasatake YAMATO 
promiseUpdateLanguage(int promise,langType lang)32089a71f3bSMasatake YAMATO void promiseUpdateLanguage  (int promise, langType lang)
32189a71f3bSMasatake YAMATO {
32289a71f3bSMasatake YAMATO 	Assert (promise >= 0);
32389a71f3bSMasatake YAMATO 
32489a71f3bSMasatake YAMATO 	struct promise *p = promises + promise;
32589a71f3bSMasatake YAMATO 
32689a71f3bSMasatake YAMATO 	p->lang = lang;
32789a71f3bSMasatake YAMATO }
328