xref: /Universal-ctags/parsers/vim.c (revision 750ebcec75bfca0d9bf0ddf958a1616cf76779c8)
13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO *   Copyright (c) 2000-2003, Darren Hiebert
33ae02089SMasatake YAMATO *
43ae02089SMasatake YAMATO *   This source code is released for free distribution under the terms of the
50ce38835Sviccuad *   GNU General Public License version 2 or (at your option) any later version.
63ae02089SMasatake YAMATO *
73ae02089SMasatake YAMATO *   Thanks are due to Jay Glanville for significant improvements.
83ae02089SMasatake YAMATO *
93ae02089SMasatake YAMATO *   This module contains functions for generating tags for user-defined
103ae02089SMasatake YAMATO *   functions for the Vim editor.
113ae02089SMasatake YAMATO */
123ae02089SMasatake YAMATO 
133ae02089SMasatake YAMATO /*
143ae02089SMasatake YAMATO  *  INCLUDE FILES
153ae02089SMasatake YAMATO  */
163ae02089SMasatake YAMATO #include "general.h"  /* must always come first */
173ae02089SMasatake YAMATO 
183ae02089SMasatake YAMATO #include <string.h>
193ae02089SMasatake YAMATO #ifdef DEBUG
203ae02089SMasatake YAMATO #include <stdio.h>
213ae02089SMasatake YAMATO #endif
223ae02089SMasatake YAMATO 
23*750ebcecSMasatake YAMATO #include "debug.h"
2446e50c4fSMasatake YAMATO #include "entry.h"
253ae02089SMasatake YAMATO #include "parse.h"
263ae02089SMasatake YAMATO #include "read.h"
273db72c21SMasatake YAMATO #include "routines.h"
283ae02089SMasatake YAMATO #include "vstring.h"
293ae02089SMasatake YAMATO 
303ae02089SMasatake YAMATO #if 0
313ae02089SMasatake YAMATO typedef struct sLineInfo {
323ae02089SMasatake YAMATO 	tokenType type;
333ae02089SMasatake YAMATO 	keywordId keyword;
343ae02089SMasatake YAMATO 	vString *string;
353ae02089SMasatake YAMATO 	vString *scope;
363ae02089SMasatake YAMATO 	unsigned long lineNumber;
37509a47dbSJiří Techet 	MIOPos filePosition;
383ae02089SMasatake YAMATO } lineInfo;
393ae02089SMasatake YAMATO #endif
403ae02089SMasatake YAMATO 
413ae02089SMasatake YAMATO /*
423ae02089SMasatake YAMATO  * DATA DEFINITIONS
433ae02089SMasatake YAMATO  */
443ae02089SMasatake YAMATO typedef enum {
453ae02089SMasatake YAMATO 	K_AUGROUP,
463ae02089SMasatake YAMATO 	K_COMMAND,
473ae02089SMasatake YAMATO 	K_FUNCTION,
483ae02089SMasatake YAMATO 	K_MAP,
493ae02089SMasatake YAMATO 	K_VARIABLE,
50b92362f2Slacygoill 	K_FILENAME,
51b92362f2Slacygoill 	K_CONST,
523ae02089SMasatake YAMATO } vimKind;
533ae02089SMasatake YAMATO 
54e112e8abSMasatake YAMATO static kindDefinition VimKinds [] = {
55ce990805SThomas Braun 	{ true,  'a', "augroup",  "autocommand groups" },
56ce990805SThomas Braun 	{ true,  'c', "command",  "user-defined commands" },
57ce990805SThomas Braun 	{ true,  'f', "function", "function definitions" },
58ce990805SThomas Braun 	{ true,  'm', "map",      "maps" },
59ce990805SThomas Braun 	{ true,  'v', "variable", "variable definitions" },
60ce990805SThomas Braun 	{ true,  'n', "filename", "vimball filename" },
61b92362f2Slacygoill 	{ true,  'C', "constant", "constant definitions" },
623ae02089SMasatake YAMATO };
633ae02089SMasatake YAMATO 
643ae02089SMasatake YAMATO /*
653ae02089SMasatake YAMATO  *  DATA DECLARATIONS
663ae02089SMasatake YAMATO  */
673ae02089SMasatake YAMATO 
683ae02089SMasatake YAMATO #if 0
693ae02089SMasatake YAMATO typedef enum eException {
703ae02089SMasatake YAMATO 	ExceptionNone, ExceptionEOF
713ae02089SMasatake YAMATO } exception_t;
723ae02089SMasatake YAMATO #endif
733ae02089SMasatake YAMATO 
743ae02089SMasatake YAMATO /*
753ae02089SMasatake YAMATO  *  DATA DEFINITIONS
763ae02089SMasatake YAMATO  */
773ae02089SMasatake YAMATO 
783ae02089SMasatake YAMATO #if 0
793ae02089SMasatake YAMATO static jmp_buf Exception;
803ae02089SMasatake YAMATO #endif
813ae02089SMasatake YAMATO 
823ae02089SMasatake YAMATO /*
833ae02089SMasatake YAMATO  *  FUNCTION DEFINITIONS
843ae02089SMasatake YAMATO  */
853ae02089SMasatake YAMATO 
86ce990805SThomas Braun static bool parseVimLine (const unsigned char *line, int infunction);
873ae02089SMasatake YAMATO 
883ae02089SMasatake YAMATO /* This function takes a char pointer, tries to find a scope separator in the
893ae02089SMasatake YAMATO  * string, and if it does, returns a pointer to the character after the colon,
903ae02089SMasatake YAMATO  * and the character defining the scope.
913ae02089SMasatake YAMATO  * If a colon is not found, it returns the original pointer.
923ae02089SMasatake YAMATO  */
skipPrefix(const unsigned char * name,int * scope)933ae02089SMasatake YAMATO static const unsigned char *skipPrefix (const unsigned char *name, int *scope)
943ae02089SMasatake YAMATO {
953ae02089SMasatake YAMATO 	const unsigned char *result = name;
963ae02089SMasatake YAMATO 	int counter;
973ae02089SMasatake YAMATO 	size_t length;
983ae02089SMasatake YAMATO 	length = strlen ((const char *) name);
993ae02089SMasatake YAMATO 	if (scope != NULL)
1003ae02089SMasatake YAMATO 		*scope = '\0';
1013ae02089SMasatake YAMATO 	if (length > 3 && name[1] == ':')
1023ae02089SMasatake YAMATO 	{
1033ae02089SMasatake YAMATO 		if (scope != NULL)
1043ae02089SMasatake YAMATO 			*scope = *name;
1053ae02089SMasatake YAMATO 		result = name + 2;
1063ae02089SMasatake YAMATO 	}
1073ae02089SMasatake YAMATO 	else if (length > 5 && strncasecmp ((const char *) name, "<SID>", (size_t) 5) == 0)
1083ae02089SMasatake YAMATO 	{
1093ae02089SMasatake YAMATO 		if (scope != NULL)
1103ae02089SMasatake YAMATO 			*scope = *name;
1113ae02089SMasatake YAMATO 		result = name + 5;
1123ae02089SMasatake YAMATO 	}
1133ae02089SMasatake YAMATO 	else
1143ae02089SMasatake YAMATO 	{
1153ae02089SMasatake YAMATO 		/*
1163ae02089SMasatake YAMATO 		 * Vim7 check for dictionaries or autoload function names
1173ae02089SMasatake YAMATO 		 */
1183ae02089SMasatake YAMATO 		counter = 0;
1193ae02089SMasatake YAMATO 		do
1203ae02089SMasatake YAMATO 		{
1213ae02089SMasatake YAMATO 			switch (name[counter])
1223ae02089SMasatake YAMATO 			{
1233ae02089SMasatake YAMATO 				case '.':
1243ae02089SMasatake YAMATO 					/* Set the scope to d - Dictionary */
1253ae02089SMasatake YAMATO 					*scope = 'd';
1263ae02089SMasatake YAMATO 					break;
1273ae02089SMasatake YAMATO 				case '#':
1283ae02089SMasatake YAMATO 					/* Set the scope to a - autoload */
1293ae02089SMasatake YAMATO 					*scope = 'a';
1303ae02089SMasatake YAMATO 					break;
1313ae02089SMasatake YAMATO 			}
1323ae02089SMasatake YAMATO 			++counter;
1333ae02089SMasatake YAMATO 		} while (isalnum ((int) name[counter]) ||
1343ae02089SMasatake YAMATO 				name[counter] == '_'           ||
1353ae02089SMasatake YAMATO 				name[counter] == '.'           ||
1363ae02089SMasatake YAMATO 				name[counter] == '#'
1373ae02089SMasatake YAMATO 				);
1383ae02089SMasatake YAMATO 	}
1393ae02089SMasatake YAMATO 	return result;
1403ae02089SMasatake YAMATO }
1413ae02089SMasatake YAMATO 
isWordChar(const unsigned char c)142ce990805SThomas Braun static bool isWordChar (const unsigned char c)
1433ae02089SMasatake YAMATO {
1443ae02089SMasatake YAMATO 	return (isalnum (c) || c == '_');
1453ae02089SMasatake YAMATO }
1463ae02089SMasatake YAMATO 
1473ae02089SMasatake YAMATO /* checks if a word at the start of `p` matches at least `min_len` first
1483ae02089SMasatake YAMATO  * characters from `word` */
wordMatchLen(const unsigned char * p,const char * const word,size_t min_len)149ce990805SThomas Braun static bool wordMatchLen (const unsigned char *p, const char *const word, size_t min_len)
1503ae02089SMasatake YAMATO {
1513ae02089SMasatake YAMATO 	const unsigned char *w = (const unsigned char *) word;
1523ae02089SMasatake YAMATO 	size_t n = 0;
1533ae02089SMasatake YAMATO 
1543ae02089SMasatake YAMATO 	while (*p && *p == *w)
1553ae02089SMasatake YAMATO 	{
1563ae02089SMasatake YAMATO 		p++;
1573ae02089SMasatake YAMATO 		w++;
1583ae02089SMasatake YAMATO 		n++;
1593ae02089SMasatake YAMATO 	}
1603ae02089SMasatake YAMATO 
1613ae02089SMasatake YAMATO 	if (isWordChar (*p))
162ce990805SThomas Braun 		return false;
1633ae02089SMasatake YAMATO 
1643ae02089SMasatake YAMATO 	return n >= min_len;
1653ae02089SMasatake YAMATO }
1663ae02089SMasatake YAMATO 
skipWord(const unsigned char * p)1673ae02089SMasatake YAMATO static const unsigned char *skipWord (const unsigned char *p)
1683ae02089SMasatake YAMATO {
1693ae02089SMasatake YAMATO 	while (*p && isWordChar (*p))
1703ae02089SMasatake YAMATO 		p++;
1713ae02089SMasatake YAMATO 	return p;
1723ae02089SMasatake YAMATO }
1733ae02089SMasatake YAMATO 
isMap(const unsigned char * line)174ce990805SThomas Braun static bool isMap (const unsigned char *line)
1753ae02089SMasatake YAMATO {
1763ae02089SMasatake YAMATO 	/*
1773ae02089SMasatake YAMATO 	 * There are many different short cuts for specifying a map.
1783ae02089SMasatake YAMATO 	 * This routine should capture all the permutations.
1793ae02089SMasatake YAMATO 	 */
1803ae02089SMasatake YAMATO 	return (wordMatchLen (line, "map", 3) ||
1813ae02089SMasatake YAMATO 			wordMatchLen (line, "nmap", 2) ||
1823ae02089SMasatake YAMATO 			wordMatchLen (line, "vmap", 2) ||
1833ae02089SMasatake YAMATO 			wordMatchLen (line, "xmap", 2) ||
1843ae02089SMasatake YAMATO 			wordMatchLen (line, "smap", 4) ||
1853ae02089SMasatake YAMATO 			wordMatchLen (line, "omap", 2) ||
1863ae02089SMasatake YAMATO 			wordMatchLen (line, "imap", 2) ||
1873ae02089SMasatake YAMATO 			wordMatchLen (line, "lmap", 2) ||
1883ae02089SMasatake YAMATO 			wordMatchLen (line, "cmap", 2) ||
1893ae02089SMasatake YAMATO 			wordMatchLen (line, "noremap", 2) ||
1903ae02089SMasatake YAMATO 			wordMatchLen (line, "nnoremap", 2) ||
1913ae02089SMasatake YAMATO 			wordMatchLen (line, "vnoremap", 2) ||
1923ae02089SMasatake YAMATO 			wordMatchLen (line, "xnoremap", 2) ||
1933ae02089SMasatake YAMATO 			wordMatchLen (line, "snoremap", 4) ||
1943ae02089SMasatake YAMATO 			wordMatchLen (line, "onoremap", 3) ||
1953ae02089SMasatake YAMATO 			wordMatchLen (line, "inoremap", 3) ||
1963ae02089SMasatake YAMATO 			wordMatchLen (line, "lnoremap", 2) ||
1973ae02089SMasatake YAMATO 			wordMatchLen (line, "cnoremap", 3));
1983ae02089SMasatake YAMATO }
1993ae02089SMasatake YAMATO 
readVimLine(void)2003ae02089SMasatake YAMATO static const unsigned char *readVimLine (void)
2013ae02089SMasatake YAMATO {
2023ae02089SMasatake YAMATO 	const unsigned char *line;
2033ae02089SMasatake YAMATO 
2041b312fe7SMasatake YAMATO 	while ((line = readLineFromInputFile ()) != NULL)
2053ae02089SMasatake YAMATO 	{
2063ae02089SMasatake YAMATO 		while (isspace ((int) *line))
2073ae02089SMasatake YAMATO 			++line;
2083ae02089SMasatake YAMATO 
2093ae02089SMasatake YAMATO 		if ((int) *line == '"')
2103ae02089SMasatake YAMATO 			continue;  /* skip comment */
2113ae02089SMasatake YAMATO 
2123ae02089SMasatake YAMATO 		break;
2133ae02089SMasatake YAMATO 	}
2143ae02089SMasatake YAMATO 
2153ae02089SMasatake YAMATO 	return line;
2163ae02089SMasatake YAMATO }
2173ae02089SMasatake YAMATO 
readVimballLine(void)2183ae02089SMasatake YAMATO static const unsigned char *readVimballLine (void)
2193ae02089SMasatake YAMATO {
2203ae02089SMasatake YAMATO 	const unsigned char *line;
2213ae02089SMasatake YAMATO 
2221b312fe7SMasatake YAMATO 	while ((line = readLineFromInputFile ()) != NULL)
2233ae02089SMasatake YAMATO 	{
2243ae02089SMasatake YAMATO 		break;
2253ae02089SMasatake YAMATO 	}
2263ae02089SMasatake YAMATO 
2273ae02089SMasatake YAMATO 	return line;
2283ae02089SMasatake YAMATO }
2293ae02089SMasatake YAMATO 
parseSignature(const unsigned char * cp,tagEntryInfo * e,vString * buf)230*750ebcecSMasatake YAMATO static vString *parseSignature (const unsigned char *cp,
231*750ebcecSMasatake YAMATO 								tagEntryInfo *e,
232*750ebcecSMasatake YAMATO 								vString *buf)
233*750ebcecSMasatake YAMATO {
234*750ebcecSMasatake YAMATO 	/* TODO capture parameters */
235*750ebcecSMasatake YAMATO 
236*750ebcecSMasatake YAMATO 	Assert (e);
237*750ebcecSMasatake YAMATO 	Assert (cp);
238*750ebcecSMasatake YAMATO 
239*750ebcecSMasatake YAMATO 	if (!buf)
240*750ebcecSMasatake YAMATO 	{
241*750ebcecSMasatake YAMATO 		buf = vStringNew ();
242*750ebcecSMasatake YAMATO 		vStringPut (buf, *cp);
243*750ebcecSMasatake YAMATO 		++cp;
244*750ebcecSMasatake YAMATO 	}
245*750ebcecSMasatake YAMATO 
246*750ebcecSMasatake YAMATO 	while (*cp != '\0')
247*750ebcecSMasatake YAMATO 	{
248*750ebcecSMasatake YAMATO 		if (isspace ((int) *cp)
249*750ebcecSMasatake YAMATO 			&& vStringLast (buf) == ',')
250*750ebcecSMasatake YAMATO 		{
251*750ebcecSMasatake YAMATO 			++cp;
252*750ebcecSMasatake YAMATO 			continue;
253*750ebcecSMasatake YAMATO 		}
254*750ebcecSMasatake YAMATO 		vStringPut (buf, *cp);
255*750ebcecSMasatake YAMATO 		if (*cp == ')')
256*750ebcecSMasatake YAMATO 			break;
257*750ebcecSMasatake YAMATO 		++cp;
258*750ebcecSMasatake YAMATO 	}
259*750ebcecSMasatake YAMATO 
260*750ebcecSMasatake YAMATO 	if (*cp == ')')
261*750ebcecSMasatake YAMATO 	{
262*750ebcecSMasatake YAMATO 		e->extensionFields.signature = vStringDeleteUnwrap (buf);
263*750ebcecSMasatake YAMATO 		buf = NULL;
264*750ebcecSMasatake YAMATO 	}
265*750ebcecSMasatake YAMATO 
266*750ebcecSMasatake YAMATO 	return buf;
267*750ebcecSMasatake YAMATO }
268*750ebcecSMasatake YAMATO 
parseFunction(const unsigned char * line)2693ae02089SMasatake YAMATO static void parseFunction (const unsigned char *line)
2703ae02089SMasatake YAMATO {
2713ae02089SMasatake YAMATO 	vString *name = vStringNew ();
272*750ebcecSMasatake YAMATO 	vString *signature = NULL;
273ce990805SThomas Braun 	/* bool inFunction = false; */
2743ae02089SMasatake YAMATO 	int scope;
2753ae02089SMasatake YAMATO 	const unsigned char *cp = line;
27646e50c4fSMasatake YAMATO 	int index = CORK_NIL;
277*750ebcecSMasatake YAMATO 	tagEntryInfo *e = NULL;
2783ae02089SMasatake YAMATO 
2797c92e827SDoug Kearns 	if (*cp == '!')
2803ae02089SMasatake YAMATO 		++cp;
2813ae02089SMasatake YAMATO 	if (isspace ((int) *cp))
2823ae02089SMasatake YAMATO 	{
2833ae02089SMasatake YAMATO 		while (*cp && isspace ((int) *cp))
2843ae02089SMasatake YAMATO 			++cp;
2853ae02089SMasatake YAMATO 
2863ae02089SMasatake YAMATO 		if (*cp)
2873ae02089SMasatake YAMATO 		{
2883ae02089SMasatake YAMATO 			cp = skipPrefix (cp, &scope);
2893ae02089SMasatake YAMATO 			if (isupper ((int) *cp)  ||
2903ae02089SMasatake YAMATO 					scope == 's'  ||  /* script scope */
2913ae02089SMasatake YAMATO 					scope == '<'  ||  /* script scope */
2921e2c63fbSDaniel Hahler 					scope == 'g'  ||  /* global scope */
2933ae02089SMasatake YAMATO 					scope == 'd'  ||  /* dictionary */
2943ae02089SMasatake YAMATO 					scope == 'a')     /* autoload */
2953ae02089SMasatake YAMATO 			{
29609ca50a9SMasatake YAMATO 				char prefix[3] = { [0] = (char)scope, [1] = ':', [2] = '\0' };
29709ca50a9SMasatake YAMATO 				if (scope == 's')
29809ca50a9SMasatake YAMATO 					vStringCatS (name, prefix);
29909ca50a9SMasatake YAMATO 
3003ae02089SMasatake YAMATO 				do
3013ae02089SMasatake YAMATO 				{
3023ae02089SMasatake YAMATO 					vStringPut (name, (int) *cp);
3033ae02089SMasatake YAMATO 					++cp;
3043ae02089SMasatake YAMATO 				} while (isalnum ((int) *cp) || *cp == '_' || *cp == '.' || *cp == '#');
30516a2541cSMasatake YAMATO 				index = makeSimpleTag (name, K_FUNCTION);
3063ae02089SMasatake YAMATO 				vStringClear (name);
307*750ebcecSMasatake YAMATO 
308*750ebcecSMasatake YAMATO 				e = getEntryInCorkQueue (index);
309*750ebcecSMasatake YAMATO 				if (e && isFieldEnabled (FIELD_SIGNATURE))
310*750ebcecSMasatake YAMATO 				{
311*750ebcecSMasatake YAMATO 					while (*cp && isspace ((int) *cp))
312*750ebcecSMasatake YAMATO 						++cp;
313*750ebcecSMasatake YAMATO 					if (*cp == '(')
314*750ebcecSMasatake YAMATO 						signature = parseSignature (cp, e, NULL);
315*750ebcecSMasatake YAMATO 				}
3163ae02089SMasatake YAMATO 			}
3173ae02089SMasatake YAMATO 		}
3183ae02089SMasatake YAMATO 	}
3193ae02089SMasatake YAMATO 
3203ae02089SMasatake YAMATO 	/* TODO - update struct to indicate inside function */
3213ae02089SMasatake YAMATO 	while ((line = readVimLine ()) != NULL)
3223ae02089SMasatake YAMATO 	{
323*750ebcecSMasatake YAMATO 		if (signature)
324*750ebcecSMasatake YAMATO 		{
325*750ebcecSMasatake YAMATO 			cp = line;
326*750ebcecSMasatake YAMATO 			while (*cp && isspace ((int) *cp))
327*750ebcecSMasatake YAMATO 				++cp;
328*750ebcecSMasatake YAMATO 			/* A backslash at the start of a line stands for a line continuation.
329*750ebcecSMasatake YAMATO 			 * https://vimhelp.org/repeat.txt.html#line-continuation */
330*750ebcecSMasatake YAMATO 			if (*cp == '\\')
331*750ebcecSMasatake YAMATO 				signature = parseSignature (++cp, e, signature);
332*750ebcecSMasatake YAMATO 		}
333*750ebcecSMasatake YAMATO 
33481a89990Slacygoill 		if (wordMatchLen (line, "endfunction", 4) || wordMatchLen (line, "enddef", 6))
33546e50c4fSMasatake YAMATO 		{
3363671ad72SMasatake YAMATO 			if (e)
337d82a3cd2SMasatake YAMATO 				e->extensionFields.endLine = getInputLineNumber ();
3383ae02089SMasatake YAMATO 			break;
33946e50c4fSMasatake YAMATO 		}
3403ae02089SMasatake YAMATO 
341ce990805SThomas Braun 		parseVimLine (line, true);
3423ae02089SMasatake YAMATO 	}
343*750ebcecSMasatake YAMATO 	if (signature)
344*750ebcecSMasatake YAMATO 		vStringDelete (signature);
3453ae02089SMasatake YAMATO 	vStringDelete (name);
3463ae02089SMasatake YAMATO }
3473ae02089SMasatake YAMATO 
parseAutogroup(const unsigned char * line)3483ae02089SMasatake YAMATO static void parseAutogroup (const unsigned char *line)
3493ae02089SMasatake YAMATO {
3503ae02089SMasatake YAMATO 	vString *name = vStringNew ();
3513ae02089SMasatake YAMATO 
3523ae02089SMasatake YAMATO 	/* Found Autocommand Group (augroup) */
3533ae02089SMasatake YAMATO 	const unsigned char *cp = line;
3543ae02089SMasatake YAMATO 	if (isspace ((int) *cp))
3553ae02089SMasatake YAMATO 	{
3563ae02089SMasatake YAMATO 		while (*cp && isspace ((int) *cp))
3573ae02089SMasatake YAMATO 			++cp;
3583ae02089SMasatake YAMATO 
3593ae02089SMasatake YAMATO 		if (*cp)
3603ae02089SMasatake YAMATO 		{
3613ae02089SMasatake YAMATO 			const unsigned char *end = skipWord (cp);
3623ae02089SMasatake YAMATO 
3633ae02089SMasatake YAMATO 			/* "end" (caseless) has a special meaning and should not generate a tag */
3643ae02089SMasatake YAMATO 			if (end > cp && strncasecmp ((const char *) cp, "end", end - cp) != 0)
3653ae02089SMasatake YAMATO 			{
3663ae02089SMasatake YAMATO 				vStringNCatS (name, (const char *) cp, end - cp);
36716a2541cSMasatake YAMATO 				makeSimpleTag (name, K_AUGROUP);
3683ae02089SMasatake YAMATO 				vStringClear (name);
3693ae02089SMasatake YAMATO 			}
3703ae02089SMasatake YAMATO 		}
3713ae02089SMasatake YAMATO 	}
3723ae02089SMasatake YAMATO 	vStringDelete (name);
3733ae02089SMasatake YAMATO }
3743ae02089SMasatake YAMATO 
parseCommand(const unsigned char * line)375ce990805SThomas Braun static bool parseCommand (const unsigned char *line)
3763ae02089SMasatake YAMATO {
3773ae02089SMasatake YAMATO 	vString *name = vStringNew ();
378ce990805SThomas Braun 	bool cmdProcessed = true;
3793ae02089SMasatake YAMATO 
3803ae02089SMasatake YAMATO 	/*
3813ae02089SMasatake YAMATO 	 * Found a user-defined command
3823ae02089SMasatake YAMATO 	 *
38346204f78SBen Wiederhake 	 * They can have many options preceded by a dash
3843ae02089SMasatake YAMATO 	 * command! -nargs=+ -complete Select  :call s:DB_execSql("select " . <q-args>)
38546204f78SBen Wiederhake 	 * The name of the command should be the first word not preceded by a dash
3863ae02089SMasatake YAMATO 	 *
3873ae02089SMasatake YAMATO 	 */
3883ae02089SMasatake YAMATO 	const unsigned char *cp = line;
3893ae02089SMasatake YAMATO 
3907c92e827SDoug Kearns 	if (cp && (*cp == '\\'))
3913ae02089SMasatake YAMATO 	{
3923ae02089SMasatake YAMATO 		/*
3933ae02089SMasatake YAMATO 		 * We are recursively calling this function is the command
3943ae02089SMasatake YAMATO 		 * has been continued on to the next line
3953ae02089SMasatake YAMATO 		 *
3963ae02089SMasatake YAMATO 		 * Vim statements can be continued onto a newline using a \
3973ae02089SMasatake YAMATO 		 * to indicate the previous line is continuing.
3983ae02089SMasatake YAMATO 		 *
3993ae02089SMasatake YAMATO 		 * com -nargs=1 -bang -complete=customlist,EditFileComplete
4003ae02089SMasatake YAMATO 		 *          \ EditFile edit<bang> <args>
4013ae02089SMasatake YAMATO 		 *
4023ae02089SMasatake YAMATO 		 * If the following lines do not have a line continuation
4033ae02089SMasatake YAMATO 		 * the command must not be spanning multiple lines and should
404759d281dSK.Takata 		 * be syntactically incorrect.
4053ae02089SMasatake YAMATO 		 */
4067c92e827SDoug Kearns 		if (*cp == '\\')
4073ae02089SMasatake YAMATO 			++cp;
4083ae02089SMasatake YAMATO 
4093ae02089SMasatake YAMATO 		while (*cp && isspace ((int) *cp))
4103ae02089SMasatake YAMATO 			++cp;
4113ae02089SMasatake YAMATO 	}
4123ae02089SMasatake YAMATO 	else if (line && wordMatchLen (cp, "command", 3))
4133ae02089SMasatake YAMATO 	{
4143ae02089SMasatake YAMATO 		cp = skipWord (cp);
4153ae02089SMasatake YAMATO 
4167c92e827SDoug Kearns 		if (*cp == '!')
4173ae02089SMasatake YAMATO 			++cp;
4183ae02089SMasatake YAMATO 
4197c92e827SDoug Kearns 		if (*cp != ' ')
4203ae02089SMasatake YAMATO 		{
4213ae02089SMasatake YAMATO 			/*
4223ae02089SMasatake YAMATO 			 * :command must be followed by a space.  If it is not, it is
4233ae02089SMasatake YAMATO 			 * not a valid command.
4243ae02089SMasatake YAMATO 			 * Treat the line as processed and continue.
4253ae02089SMasatake YAMATO 			 */
426ce990805SThomas Braun 			cmdProcessed = true;
4273ae02089SMasatake YAMATO 			goto cleanUp;
4283ae02089SMasatake YAMATO 		}
4293ae02089SMasatake YAMATO 
4303ae02089SMasatake YAMATO 		while (*cp && isspace ((int) *cp))
4313ae02089SMasatake YAMATO 			++cp;
4323ae02089SMasatake YAMATO 	}
4333ae02089SMasatake YAMATO 	else
4343ae02089SMasatake YAMATO 	{
4353ae02089SMasatake YAMATO 		/*
4363ae02089SMasatake YAMATO 		 * We are recursively calling this function.  If it does not start
4373ae02089SMasatake YAMATO 		 * with "com" or a line continuation character, we have moved off
4383ae02089SMasatake YAMATO 		 * the command line and should let the other routines parse this file.
4393ae02089SMasatake YAMATO 		 */
440ce990805SThomas Braun 		cmdProcessed = false;
4413ae02089SMasatake YAMATO 		goto cleanUp;
4423ae02089SMasatake YAMATO 	}
4433ae02089SMasatake YAMATO 
4443ae02089SMasatake YAMATO 	/*
4453ae02089SMasatake YAMATO 	 * Strip off any spaces and options which are part of the command.
44646204f78SBen Wiederhake 	 * These should precede the command name.
4473ae02089SMasatake YAMATO 	 */
4483ae02089SMasatake YAMATO 	do
4493ae02089SMasatake YAMATO 	{
4503ae02089SMasatake YAMATO 		if (isspace ((int) *cp))
4513ae02089SMasatake YAMATO 		{
4523ae02089SMasatake YAMATO 			++cp;
4533ae02089SMasatake YAMATO 		}
4543ae02089SMasatake YAMATO 		else if (*cp == '-')
4553ae02089SMasatake YAMATO 		{
4563ae02089SMasatake YAMATO 			/*
4573ae02089SMasatake YAMATO 			 * Read until the next space which separates options or the name
4583ae02089SMasatake YAMATO 			 */
4593ae02089SMasatake YAMATO 			while (*cp && !isspace ((int) *cp))
4603ae02089SMasatake YAMATO 				++cp;
4613ae02089SMasatake YAMATO 		}
4623ae02089SMasatake YAMATO 		else if (!isalnum ((int) *cp))
4633ae02089SMasatake YAMATO 		{
4643ae02089SMasatake YAMATO 			/*
4653ae02089SMasatake YAMATO 			 * Broken syntax: throw away this line
4663ae02089SMasatake YAMATO 			 */
467ce990805SThomas Braun 			cmdProcessed = true;
4683ae02089SMasatake YAMATO 			goto cleanUp;
4693ae02089SMasatake YAMATO 		}
4703ae02089SMasatake YAMATO 	} while (*cp &&  !isalnum ((int) *cp));
4713ae02089SMasatake YAMATO 
4723ae02089SMasatake YAMATO 	if (!*cp)
4733ae02089SMasatake YAMATO 	{
4743ae02089SMasatake YAMATO 		/*
4753ae02089SMasatake YAMATO 		 * We have reached the end of the line without finding the command name.
4763ae02089SMasatake YAMATO 		 * Read the next line and continue processing it as a command.
4773ae02089SMasatake YAMATO 		 */
4783ae02089SMasatake YAMATO 		if ((line = readVimLine ()) != NULL)
4793ae02089SMasatake YAMATO 			cmdProcessed = parseCommand (line);
4803ae02089SMasatake YAMATO 		else
481ce990805SThomas Braun 			cmdProcessed = false;
4823ae02089SMasatake YAMATO 		goto cleanUp;
4833ae02089SMasatake YAMATO 	}
4843ae02089SMasatake YAMATO 
4853ae02089SMasatake YAMATO 	do
4863ae02089SMasatake YAMATO 	{
4873ae02089SMasatake YAMATO 		vStringPut (name, (int) *cp);
4883ae02089SMasatake YAMATO 		++cp;
4893ae02089SMasatake YAMATO 	} while (isalnum ((int) *cp) || *cp == '_');
4903ae02089SMasatake YAMATO 
49116a2541cSMasatake YAMATO 	makeSimpleTag (name, K_COMMAND);
4923ae02089SMasatake YAMATO 	vStringClear (name);
4933ae02089SMasatake YAMATO 
4943ae02089SMasatake YAMATO cleanUp:
4953ae02089SMasatake YAMATO 	vStringDelete (name);
4963ae02089SMasatake YAMATO 
4973ae02089SMasatake YAMATO 	return cmdProcessed;
4983ae02089SMasatake YAMATO }
4993ae02089SMasatake YAMATO 
parseVariableOrConstant(const unsigned char * line,int infunction,int kindIndex)500b92362f2Slacygoill static void parseVariableOrConstant (const unsigned char *line, int infunction, int kindIndex)
5013ae02089SMasatake YAMATO {
5023ae02089SMasatake YAMATO 	vString *name = vStringNew ();
5033ae02089SMasatake YAMATO 
5043ae02089SMasatake YAMATO 	const unsigned char *cp = line;
5053ae02089SMasatake YAMATO 	const unsigned char *np = line;
5063ae02089SMasatake YAMATO 	/* get the name */
5073ae02089SMasatake YAMATO 	if (isspace ((int) *cp))
5083ae02089SMasatake YAMATO 	{
5093ae02089SMasatake YAMATO 		while (*cp && isspace ((int) *cp))
5103ae02089SMasatake YAMATO 			++cp;
5113ae02089SMasatake YAMATO 
5123ae02089SMasatake YAMATO 		/*
5133ae02089SMasatake YAMATO 		 * Ignore lets which set:
5143ae02089SMasatake YAMATO 		 *    &  - local buffer vim settings
5153ae02089SMasatake YAMATO 		 *    @  - registers
5163ae02089SMasatake YAMATO 		 *    [  - Lists or Dictionaries
5173ae02089SMasatake YAMATO 		 */
5183ae02089SMasatake YAMATO 		if (!*cp || *cp == '&' || *cp == '@' || *cp == '[')
5193ae02089SMasatake YAMATO 			goto cleanUp;
5203ae02089SMasatake YAMATO 
5213ae02089SMasatake YAMATO 		/*
5223ae02089SMasatake YAMATO 		 * Ignore vim variables which are read only
5233ae02089SMasatake YAMATO 		 *    v: - Vim variables.
5243ae02089SMasatake YAMATO 		 */
5253ae02089SMasatake YAMATO 		np = cp;
5263ae02089SMasatake YAMATO 		++np;
5277c92e827SDoug Kearns 		if (*cp == 'v' && *np == ':')
5283ae02089SMasatake YAMATO 			goto cleanUp;
5293ae02089SMasatake YAMATO 
5303ae02089SMasatake YAMATO 		/* Skip non-global vars in functions */
5317c92e827SDoug Kearns 		if (infunction && (*np != ':' || *cp != 'g'))
5323ae02089SMasatake YAMATO 			goto cleanUp;
5333ae02089SMasatake YAMATO 
5343ae02089SMasatake YAMATO 		/* deal with spaces, $, @ and & */
5353ae02089SMasatake YAMATO 		while (*cp && *cp != '$' && !isalnum ((int) *cp))
5363ae02089SMasatake YAMATO 			++cp;
5373ae02089SMasatake YAMATO 
5383ae02089SMasatake YAMATO 		if (!*cp)
5393ae02089SMasatake YAMATO 			goto cleanUp;
5403ae02089SMasatake YAMATO 
5413ae02089SMasatake YAMATO 		/* cp = skipPrefix (cp, &scope); */
5423ae02089SMasatake YAMATO 		do
5433ae02089SMasatake YAMATO 		{
5443ae02089SMasatake YAMATO 			if (!*cp)
5453ae02089SMasatake YAMATO 				break;
5463ae02089SMasatake YAMATO 
5473ae02089SMasatake YAMATO 			vStringPut (name, (int) *cp);
5483ae02089SMasatake YAMATO 			++cp;
5493ae02089SMasatake YAMATO 		} while (isalnum ((int) *cp) || *cp == '_' || *cp == '#' || *cp == ':' || *cp == '$');
550b92362f2Slacygoill 		makeSimpleTag (name, kindIndex);
5513ae02089SMasatake YAMATO 		vStringClear (name);
5523ae02089SMasatake YAMATO 	}
5533ae02089SMasatake YAMATO 
5543ae02089SMasatake YAMATO cleanUp:
5553ae02089SMasatake YAMATO 	vStringDelete (name);
5563ae02089SMasatake YAMATO }
5573ae02089SMasatake YAMATO 
parseMap(const unsigned char * line)558ce990805SThomas Braun static bool parseMap (const unsigned char *line)
5593ae02089SMasatake YAMATO {
5603ae02089SMasatake YAMATO 	vString *name = vStringNew ();
5613ae02089SMasatake YAMATO 	const unsigned char *cp = line;
5623ae02089SMasatake YAMATO 
5637c92e827SDoug Kearns 	if (*cp == '!')
5643ae02089SMasatake YAMATO 		++cp;
5653ae02089SMasatake YAMATO 
5663ae02089SMasatake YAMATO 	/*
5673ae02089SMasatake YAMATO 	 * Maps follow this basic format
5683ae02089SMasatake YAMATO 	 *    map
5693ae02089SMasatake YAMATO 	 *    nnoremap <silent> <F8> :Tlist<CR>
5703ae02089SMasatake YAMATO 	 *    map <unique> <Leader>scdt <Plug>GetColumnDataType
5713ae02089SMasatake YAMATO 	 *    inoremap ,,, <esc>diwi<<esc>pa><cr></<esc>pa><esc>kA
5723ae02089SMasatake YAMATO 	 *    inoremap <buffer> ( <C-R>=PreviewFunctionSignature()<LF>
5733ae02089SMasatake YAMATO 	 *
5743ae02089SMasatake YAMATO 	 * The Vim help shows the various special arguments available to a map:
5753ae02089SMasatake YAMATO 	 * 1.2 SPECIAL ARGUMENTS                    *:map-arguments*
5763ae02089SMasatake YAMATO 	 *    <buffer>
5772ef063e6SDoug Kearns 	 *    <nowait>
5783ae02089SMasatake YAMATO 	 *    <silent>
5793ae02089SMasatake YAMATO 	 *    <script>
5803ae02089SMasatake YAMATO 	 *    <unique>
5813ae02089SMasatake YAMATO 	 *    <special>
5823ae02089SMasatake YAMATO 	 *    <expr>
5833ae02089SMasatake YAMATO 	 *
5843ae02089SMasatake YAMATO 	 * Strip the special arguments from the map command, this should leave
5853ae02089SMasatake YAMATO 	 * the map name which we will use as the "name".
5863ae02089SMasatake YAMATO 	 */
5873ae02089SMasatake YAMATO 
5883ae02089SMasatake YAMATO 	do
5893ae02089SMasatake YAMATO 	{
5903ae02089SMasatake YAMATO 		while (*cp && isspace ((int) *cp))
5913ae02089SMasatake YAMATO 			++cp;
5923ae02089SMasatake YAMATO 
5933ae02089SMasatake YAMATO 		if (strncmp ((const char *) cp, "<Leader>", (size_t) 8) == 0)
5943ae02089SMasatake YAMATO 			break;
5953ae02089SMasatake YAMATO 
5963ae02089SMasatake YAMATO 		if (
5973ae02089SMasatake YAMATO 				strncmp ((const char *) cp, "<buffer>", (size_t) 8) == 0 ||
5982ef063e6SDoug Kearns 				strncmp ((const char *) cp, "<nowait>", (size_t) 8) == 0 ||
5993ae02089SMasatake YAMATO 				strncmp ((const char *) cp, "<silent>", (size_t) 8) == 0 ||
6003ae02089SMasatake YAMATO 				strncmp ((const char *) cp, "<script>", (size_t) 8) == 0 ||
6013ae02089SMasatake YAMATO 				strncmp ((const char *) cp, "<unique>", (size_t) 8) == 0
6023ae02089SMasatake YAMATO 		   )
6033ae02089SMasatake YAMATO 		{
6043ae02089SMasatake YAMATO 			cp += 8;
6053ae02089SMasatake YAMATO 			continue;
6063ae02089SMasatake YAMATO 		}
6073ae02089SMasatake YAMATO 
6083ae02089SMasatake YAMATO 		if (strncmp ((const char *) cp, "<expr>", (size_t) 6) == 0)
6093ae02089SMasatake YAMATO 		{
6103ae02089SMasatake YAMATO 			cp += 6;
6113ae02089SMasatake YAMATO 			continue;
6123ae02089SMasatake YAMATO 		}
6133ae02089SMasatake YAMATO 
6143ae02089SMasatake YAMATO 		if (strncmp ((const char *) cp, "<special>", (size_t) 9) == 0)
6153ae02089SMasatake YAMATO 		{
6163ae02089SMasatake YAMATO 			cp += 9;
6173ae02089SMasatake YAMATO 			continue;
6183ae02089SMasatake YAMATO 		}
6193ae02089SMasatake YAMATO 
6203ae02089SMasatake YAMATO 		break;
6213ae02089SMasatake YAMATO 	} while (*cp);
6223ae02089SMasatake YAMATO 
6233ae02089SMasatake YAMATO 	do
6243ae02089SMasatake YAMATO 	{
6253ae02089SMasatake YAMATO 		vStringPut (name, (int) *cp);
6263ae02089SMasatake YAMATO 		++cp;
6273ae02089SMasatake YAMATO 	} while (*cp && *cp != ' ');
6283ae02089SMasatake YAMATO 
62916a2541cSMasatake YAMATO 	makeSimpleTag (name, K_MAP);
6303ae02089SMasatake YAMATO 	vStringClear (name);
6313ae02089SMasatake YAMATO 
6323ae02089SMasatake YAMATO 	vStringDelete (name);
6333ae02089SMasatake YAMATO 
634ce990805SThomas Braun 	return true;
6353ae02089SMasatake YAMATO }
6363ae02089SMasatake YAMATO 
parseVimLine(const unsigned char * line,int infunction)637ce990805SThomas Braun static bool parseVimLine (const unsigned char *line, int infunction)
6383ae02089SMasatake YAMATO {
639ce990805SThomas Braun 	bool readNextLine = true;
6403ae02089SMasatake YAMATO 
6413ae02089SMasatake YAMATO 	if (wordMatchLen (line, "command", 3))
6423ae02089SMasatake YAMATO 	{
6433ae02089SMasatake YAMATO 		readNextLine = parseCommand (line);
644ce990805SThomas Braun 		/* TODO - Handle parseCommand returning false */
6453ae02089SMasatake YAMATO 	}
6463ae02089SMasatake YAMATO 
6473ae02089SMasatake YAMATO 	else if (isMap (line))
6483ae02089SMasatake YAMATO 	{
6493ae02089SMasatake YAMATO 		parseMap (skipWord (line));
6503ae02089SMasatake YAMATO 	}
6513ae02089SMasatake YAMATO 
65281a89990Slacygoill 	else if (wordMatchLen (line, "function", 2) || wordMatchLen (line, "def", 3))
6533ae02089SMasatake YAMATO 	{
6543ae02089SMasatake YAMATO 		parseFunction (skipWord (line));
6553ae02089SMasatake YAMATO 	}
6563ae02089SMasatake YAMATO 
6573ae02089SMasatake YAMATO 	else if (wordMatchLen (line, "augroup", 3))
6583ae02089SMasatake YAMATO 	{
6593ae02089SMasatake YAMATO 		parseAutogroup (skipWord (line));
6603ae02089SMasatake YAMATO 	}
6613ae02089SMasatake YAMATO 
6623ae02089SMasatake YAMATO 	else if (wordMatchLen (line, "let", 3))
6633ae02089SMasatake YAMATO 	{
664b92362f2Slacygoill 		parseVariableOrConstant (skipWord (line), infunction, K_VARIABLE);
665b92362f2Slacygoill 	}
666b92362f2Slacygoill 	else if (wordMatchLen (line, "const", 4))
667b92362f2Slacygoill 	{
668b92362f2Slacygoill 		parseVariableOrConstant (skipWord (line), infunction, K_CONST);
6693ae02089SMasatake YAMATO 	}
6703ae02089SMasatake YAMATO 
6713ae02089SMasatake YAMATO 	return readNextLine;
6723ae02089SMasatake YAMATO }
6733ae02089SMasatake YAMATO 
parseVimFile(const unsigned char * line)6743ae02089SMasatake YAMATO static void parseVimFile (const unsigned char *line)
6753ae02089SMasatake YAMATO {
676ce990805SThomas Braun 	bool readNextLine = true;
6773ae02089SMasatake YAMATO 
6783ae02089SMasatake YAMATO 	while (line != NULL)
6793ae02089SMasatake YAMATO 	{
680ce990805SThomas Braun 		readNextLine = parseVimLine (line, false);
6813ae02089SMasatake YAMATO 
6823ae02089SMasatake YAMATO 		if (readNextLine)
6833ae02089SMasatake YAMATO 			line = readVimLine ();
6843ae02089SMasatake YAMATO 
6853ae02089SMasatake YAMATO 	}
6863ae02089SMasatake YAMATO }
6873ae02089SMasatake YAMATO 
parseVimBallFile(const unsigned char * line)6883ae02089SMasatake YAMATO static void parseVimBallFile (const unsigned char *line)
6893ae02089SMasatake YAMATO {
6903ae02089SMasatake YAMATO 	vString *fname = vStringNew ();
6913ae02089SMasatake YAMATO 	const unsigned char *cp;
6923ae02089SMasatake YAMATO 	int file_line_count;
6933ae02089SMasatake YAMATO 	int i;
6943ae02089SMasatake YAMATO 
6953ae02089SMasatake YAMATO 	/*
6963ae02089SMasatake YAMATO 	 * Vimball Archives follow this format
6973ae02089SMasatake YAMATO 	 *    " Vimball Archiver comment
6983ae02089SMasatake YAMATO 	 *    UseVimball
6993ae02089SMasatake YAMATO 	 *    finish
7003ae02089SMasatake YAMATO 	 *    filename
7013ae02089SMasatake YAMATO 	 *    line count (n) for filename
7023ae02089SMasatake YAMATO 	 *    (n) lines
7033ae02089SMasatake YAMATO 	 *    filename
7043ae02089SMasatake YAMATO 	 *    line count (n) for filename
7053ae02089SMasatake YAMATO 	 *    (n) lines
7063ae02089SMasatake YAMATO 	 *    ...
7073ae02089SMasatake YAMATO 	 */
7083ae02089SMasatake YAMATO 
7093ae02089SMasatake YAMATO 	/* Next line should be "finish" */
7103ae02089SMasatake YAMATO 	line = readVimLine ();
711faa66a6fSDoug Kearns 
7123ae02089SMasatake YAMATO 	while (line != NULL)
7133ae02089SMasatake YAMATO 	{
7143ae02089SMasatake YAMATO 		/* Next line should be a filename */
7153ae02089SMasatake YAMATO 		line = readVimLine ();
7163ae02089SMasatake YAMATO 		if (line == NULL)
7173ae02089SMasatake YAMATO 		{
718faa66a6fSDoug Kearns 			goto cleanUp;
7193ae02089SMasatake YAMATO 		}
7203ae02089SMasatake YAMATO 		else
7213ae02089SMasatake YAMATO 		{
7223ae02089SMasatake YAMATO 			cp = line;
7233ae02089SMasatake YAMATO 			do
7243ae02089SMasatake YAMATO 			{
7253ae02089SMasatake YAMATO 				vStringPut (fname, (int) *cp);
7263ae02089SMasatake YAMATO 				++cp;
7273ae02089SMasatake YAMATO 			} while (isalnum ((int) *cp) || *cp == '.' || *cp == '/' || *cp == '\\');
72816a2541cSMasatake YAMATO 			makeSimpleTag (fname, K_FILENAME);
7293ae02089SMasatake YAMATO 			vStringClear (fname);
7303ae02089SMasatake YAMATO 		}
7313ae02089SMasatake YAMATO 
7323ae02089SMasatake YAMATO 		file_line_count = 0;
7333ae02089SMasatake YAMATO 		/* Next line should be the line count of the file */
7343ae02089SMasatake YAMATO 		line = readVimLine ();
7353ae02089SMasatake YAMATO 		if (line == NULL)
7363ae02089SMasatake YAMATO 		{
737faa66a6fSDoug Kearns 			goto cleanUp;
7383ae02089SMasatake YAMATO 		}
7393ae02089SMasatake YAMATO 		else
7403ae02089SMasatake YAMATO 		{
7413ae02089SMasatake YAMATO 			file_line_count = atoi ((const char *) line);
7423ae02089SMasatake YAMATO 		}
7433ae02089SMasatake YAMATO 
7443ae02089SMasatake YAMATO 		/* Read all lines of the file */
7453ae02089SMasatake YAMATO 		for (i = 0; i < file_line_count; i++)
7463ae02089SMasatake YAMATO 		{
7473ae02089SMasatake YAMATO 			line = readVimballLine ();
7483ae02089SMasatake YAMATO 			if (line == NULL)
7493ae02089SMasatake YAMATO 			{
750faa66a6fSDoug Kearns 				goto cleanUp;
7513ae02089SMasatake YAMATO 			}
7523ae02089SMasatake YAMATO 		}
7533ae02089SMasatake YAMATO 	}
7543ae02089SMasatake YAMATO 
755faa66a6fSDoug Kearns cleanUp:
7563ae02089SMasatake YAMATO 	vStringDelete (fname);
7573ae02089SMasatake YAMATO }
7583ae02089SMasatake YAMATO 
findVimTags(void)7593ae02089SMasatake YAMATO static void findVimTags (void)
7603ae02089SMasatake YAMATO {
7613ae02089SMasatake YAMATO 	const unsigned char *line;
7623ae02089SMasatake YAMATO 	/* TODO - change this into a structure */
7633ae02089SMasatake YAMATO 
7643ae02089SMasatake YAMATO 	line = readVimLine ();
7653ae02089SMasatake YAMATO 
7663ae02089SMasatake YAMATO 	if (line == NULL)
7673ae02089SMasatake YAMATO 	{
7683ae02089SMasatake YAMATO 			return;
7693ae02089SMasatake YAMATO 	}
7703ae02089SMasatake YAMATO 
7713ae02089SMasatake YAMATO 	if (strncmp ((const char *) line, "UseVimball", (size_t) 10) == 0)
7723ae02089SMasatake YAMATO 	{
7733ae02089SMasatake YAMATO 		parseVimBallFile (line);
7743ae02089SMasatake YAMATO 	}
7753ae02089SMasatake YAMATO 	else
7763ae02089SMasatake YAMATO 	{
7773ae02089SMasatake YAMATO 		parseVimFile (line);
7783ae02089SMasatake YAMATO 	}
7793ae02089SMasatake YAMATO }
7803ae02089SMasatake YAMATO 
VimParser(void)7813ae02089SMasatake YAMATO extern parserDefinition *VimParser (void)
7823ae02089SMasatake YAMATO {
7833ae02089SMasatake YAMATO 	static const char *const extensions [] = { "vim", "vba", NULL };
7843ae02089SMasatake YAMATO 	static const char *const patterns [] = { "vimrc", "[._]vimrc", "gvimrc",
7853ae02089SMasatake YAMATO 		"[._]gvimrc", NULL };
7863ae02089SMasatake YAMATO 	parserDefinition *def = parserNew ("Vim");
78709ae690fSMasatake YAMATO 	def->kindTable      = VimKinds;
7883db72c21SMasatake YAMATO 	def->kindCount  = ARRAY_SIZE (VimKinds);
7893ae02089SMasatake YAMATO 	def->extensions = extensions;
7903ae02089SMasatake YAMATO 	def->patterns   = patterns;
7913ae02089SMasatake YAMATO 	def->parser     = findVimTags;
7926b1a862eSMasatake YAMATO 	def->useCork    = CORK_QUEUE;
7933ae02089SMasatake YAMATO 	return def;
7943ae02089SMasatake YAMATO }
795