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