13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO * Copyright (c) 2000-2003, Darren Hiebert
323da13bdSMasatake YAMATO * Copyright (c) 2017, Masatake YAMATO
423da13bdSMasatake YAMATO * Copyright (c) 2017, Red Hat, Inc.
53ae02089SMasatake YAMATO *
63ae02089SMasatake YAMATO * This source code is released for free distribution under the terms of the
70ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
83ae02089SMasatake YAMATO *
93ae02089SMasatake YAMATO * This module contains functions for generating tags for TCL scripts.
103ae02089SMasatake YAMATO */
113ae02089SMasatake YAMATO
123ae02089SMasatake YAMATO /*
133ae02089SMasatake YAMATO * INCLUDE FILES
143ae02089SMasatake YAMATO */
153ae02089SMasatake YAMATO #include "general.h" /* must always come first */
1623da13bdSMasatake YAMATO #include "tokeninfo.h"
1723da13bdSMasatake YAMATO #include "parse.h"
1823da13bdSMasatake YAMATO #include "read.h"
1923da13bdSMasatake YAMATO #include "vstring.h"
2023da13bdSMasatake YAMATO #include "keyword.h"
2123da13bdSMasatake YAMATO #include "entry.h"
2223da13bdSMasatake YAMATO #include "routines.h"
2323da13bdSMasatake YAMATO #include "ptrarray.h"
246ae73029SMasatake YAMATO #include "tcl.h"
253ae02089SMasatake YAMATO
263ae02089SMasatake YAMATO #include <string.h>
273ae02089SMasatake YAMATO
2823da13bdSMasatake YAMATO
293ae02089SMasatake YAMATO
303ae02089SMasatake YAMATO /*
313ae02089SMasatake YAMATO * DATA DEFINITIONS
323ae02089SMasatake YAMATO */
333ae02089SMasatake YAMATO typedef enum {
3471f9a680SMasatake YAMATO K_PROCEDURE, K_NAMESPACE, K_PARAMETER,
353ae02089SMasatake YAMATO } tclKind;
363ae02089SMasatake YAMATO
3771f9a680SMasatake YAMATO static scopeSeparator TclParameterSeparators [] = {
3871f9a680SMasatake YAMATO { K_PROCEDURE , "{" },
3971f9a680SMasatake YAMATO };
4071f9a680SMasatake YAMATO
41e112e8abSMasatake YAMATO static kindDefinition TclKinds [] = {
425535211dSMasatake YAMATO { true, 'p', "procedure", "procedures", },
435535211dSMasatake YAMATO { true, 'n', "namespace", "namespaces", },
4471f9a680SMasatake YAMATO { false, 'z', "parameter", "procedure parameters",
4571f9a680SMasatake YAMATO ATTACH_SEPARATORS(TclParameterSeparators)},
4623da13bdSMasatake YAMATO };
4723da13bdSMasatake YAMATO
4823da13bdSMasatake YAMATO enum {
4923da13bdSMasatake YAMATO KEYWORD_PROC,
5023da13bdSMasatake YAMATO KEYWORD_NAMESPACE,
5123da13bdSMasatake YAMATO KEYWORD_EVAL,
52c499a4edSMasatake YAMATO KEYWORD_PACKAGE,
5323da13bdSMasatake YAMATO };
5423da13bdSMasatake YAMATO
5523da13bdSMasatake YAMATO typedef int keywordId; /* to allow KEYWORD_NONE */
5623da13bdSMasatake YAMATO
5723da13bdSMasatake YAMATO
5823da13bdSMasatake YAMATO static const keywordTable TclKeywordTable[] = {
5923da13bdSMasatake YAMATO /* keyword keyword ID */
6023da13bdSMasatake YAMATO { "proc", KEYWORD_PROC },
6123da13bdSMasatake YAMATO { "namespace", KEYWORD_NAMESPACE },
6223da13bdSMasatake YAMATO { "eval", KEYWORD_EVAL },
63c499a4edSMasatake YAMATO { "package", KEYWORD_PACKAGE },
6423da13bdSMasatake YAMATO };
6523da13bdSMasatake YAMATO
6671f9a680SMasatake YAMATO typedef struct sCollector collector;
6771f9a680SMasatake YAMATO struct sCollector {
6871f9a680SMasatake YAMATO void (* proc) (const tokenInfo *const, collector *);
6971f9a680SMasatake YAMATO vString *str;
7071f9a680SMasatake YAMATO int depth;
7171f9a680SMasatake YAMATO int scopeIndex;
72*50e0c3e8SMasatake YAMATO int nth;
7371f9a680SMasatake YAMATO };
7471f9a680SMasatake YAMATO
753ae02089SMasatake YAMATO /*
763ae02089SMasatake YAMATO * FUNCTION DEFINITIONS
773ae02089SMasatake YAMATO */
783ae02089SMasatake YAMATO
7971f9a680SMasatake YAMATO static bool tokenIsEOL (const tokenInfo *const token);
8023da13bdSMasatake YAMATO
815d9d66cfSMasatake YAMATO static void initToken (tokenInfo *token, void *data);
825d9d66cfSMasatake YAMATO static void readToken (tokenInfo *const token, void *data);
8323da13bdSMasatake YAMATO static void clearToken (tokenInfo *token);
8423da13bdSMasatake YAMATO static void copyToken (tokenInfo *dest, tokenInfo *src, void *data CTAGS_ATTR_UNUSED);
8523da13bdSMasatake YAMATO
865d9d66cfSMasatake YAMATO struct sTclParserState {
875d9d66cfSMasatake YAMATO enum TclTokenType lastTokenType;
885d9d66cfSMasatake YAMATO };
895d9d66cfSMasatake YAMATO
90002dd246SMasatake YAMATO typedef struct sTclToken {
91002dd246SMasatake YAMATO tokenInfo base;
9223da13bdSMasatake YAMATO int scopeIndex;
935d9d66cfSMasatake YAMATO struct sTclParserState *pstate;
94002dd246SMasatake YAMATO } tclToken;
95002dd246SMasatake YAMATO
96002dd246SMasatake YAMATO #define TCL(TOKEN) ((tclToken *)TOKEN)
97002dd246SMasatake YAMATO #define TCL_PSTATE(TOKEN) (TCL(TOKEN)->pstate)
9823da13bdSMasatake YAMATO
991082869bSMasatake YAMATO static struct tokenTypePair typePairs [] = {
10023da13bdSMasatake YAMATO { '{', '}' },
10123da13bdSMasatake YAMATO { '[', ']' },
10223da13bdSMasatake YAMATO };
10323da13bdSMasatake YAMATO
10423da13bdSMasatake YAMATO
10523da13bdSMasatake YAMATO static struct tokenInfoClass tclTokenInfoClass = {
10623da13bdSMasatake YAMATO .nPreAlloc = 4,
1076ae73029SMasatake YAMATO .typeForUndefined = TOKEN_TCL_UNDEFINED,
10823da13bdSMasatake YAMATO .keywordNone = KEYWORD_NONE,
1096ae73029SMasatake YAMATO .typeForKeyword = TOKEN_TCL_KEYWORD,
1106ae73029SMasatake YAMATO .typeForEOF = TOKEN_TCL_EOF,
111002dd246SMasatake YAMATO .extraSpace = sizeof (tclToken) - sizeof (tokenInfo),
11223da13bdSMasatake YAMATO .pairs = typePairs,
11323da13bdSMasatake YAMATO .pairCount = ARRAY_SIZE (typePairs),
1145d9d66cfSMasatake YAMATO .init = initToken,
11523da13bdSMasatake YAMATO .read = readToken,
11623da13bdSMasatake YAMATO .clear = clearToken,
11723da13bdSMasatake YAMATO .copy = copyToken,
11823da13bdSMasatake YAMATO };
11923da13bdSMasatake YAMATO
newTclToken(void * pstate)1205d9d66cfSMasatake YAMATO extern tokenInfo *newTclToken (void *pstate)
1213ae02089SMasatake YAMATO {
1225d9d66cfSMasatake YAMATO return newTokenFull (&tclTokenInfoClass, pstate);
1233ae02089SMasatake YAMATO }
1243ae02089SMasatake YAMATO
clearToken(tokenInfo * token)12523da13bdSMasatake YAMATO static void clearToken (tokenInfo *token)
1263ae02089SMasatake YAMATO {
127002dd246SMasatake YAMATO TCL (token)->scopeIndex = CORK_NIL;
128002dd246SMasatake YAMATO TCL (token)->pstate = NULL;
12923da13bdSMasatake YAMATO }
13023da13bdSMasatake YAMATO
copyToken(tokenInfo * dest,tokenInfo * src,void * data CTAGS_ATTR_UNUSED)13123da13bdSMasatake YAMATO static void copyToken (tokenInfo *dest, tokenInfo *src, void *data CTAGS_ATTR_UNUSED)
13223da13bdSMasatake YAMATO {
133002dd246SMasatake YAMATO TCL (dest)->scopeIndex =
134002dd246SMasatake YAMATO TCL (src)->scopeIndex;
135002dd246SMasatake YAMATO TCL (dest)->pstate =
136002dd246SMasatake YAMATO TCL (src)->pstate;
13723da13bdSMasatake YAMATO }
13823da13bdSMasatake YAMATO
readString(vString * string)13923da13bdSMasatake YAMATO static void readString (vString *string)
14023da13bdSMasatake YAMATO {
14123da13bdSMasatake YAMATO int c;
14223da13bdSMasatake YAMATO bool escaped = false;
14323da13bdSMasatake YAMATO
14423da13bdSMasatake YAMATO while (1)
14523da13bdSMasatake YAMATO {
14623da13bdSMasatake YAMATO c = getcFromInputFile ();
14723da13bdSMasatake YAMATO switch (c)
14823da13bdSMasatake YAMATO {
14923da13bdSMasatake YAMATO case EOF:
1504a31d2a5SMasatake YAMATO return;
15123da13bdSMasatake YAMATO case '\\':
152964a762cSMasatake YAMATO if (escaped)
153964a762cSMasatake YAMATO {
15423da13bdSMasatake YAMATO vStringPut (string, c);
155964a762cSMasatake YAMATO escaped = false;
156964a762cSMasatake YAMATO }
157964a762cSMasatake YAMATO else
15823da13bdSMasatake YAMATO escaped = true;
1594a31d2a5SMasatake YAMATO break;
16023da13bdSMasatake YAMATO case '"':
16123da13bdSMasatake YAMATO vStringPut (string, c);
16223da13bdSMasatake YAMATO if (escaped)
16323da13bdSMasatake YAMATO escaped = false;
16423da13bdSMasatake YAMATO else
16523da13bdSMasatake YAMATO return;
16623da13bdSMasatake YAMATO break;
16723da13bdSMasatake YAMATO default:
1684a31d2a5SMasatake YAMATO escaped = false;
16923da13bdSMasatake YAMATO vStringPut (string, c);
17023da13bdSMasatake YAMATO break;
17123da13bdSMasatake YAMATO }
17223da13bdSMasatake YAMATO }
17323da13bdSMasatake YAMATO }
17423da13bdSMasatake YAMATO
readIdentifier(vString * string)17523da13bdSMasatake YAMATO static void readIdentifier (vString *string)
17623da13bdSMasatake YAMATO {
17723da13bdSMasatake YAMATO while (1)
17823da13bdSMasatake YAMATO {
17923da13bdSMasatake YAMATO int c = getcFromInputFile ();
18023da13bdSMasatake YAMATO if (isgraph (c) && (!strchr ("{}[]", c)))
18123da13bdSMasatake YAMATO vStringPut (string, c);
18223da13bdSMasatake YAMATO else
18323da13bdSMasatake YAMATO {
18423da13bdSMasatake YAMATO ungetcToInputFile (c);
18523da13bdSMasatake YAMATO break;
18623da13bdSMasatake YAMATO }
18723da13bdSMasatake YAMATO }
18823da13bdSMasatake YAMATO }
18923da13bdSMasatake YAMATO
resolveKeyword(vString * string)19023da13bdSMasatake YAMATO static keywordId resolveKeyword (vString *string)
19123da13bdSMasatake YAMATO {
19223da13bdSMasatake YAMATO char *s = vStringValue (string);
19323da13bdSMasatake YAMATO static langType lang = LANG_AUTO;
19423da13bdSMasatake YAMATO
19523da13bdSMasatake YAMATO if (lang == LANG_AUTO)
19623da13bdSMasatake YAMATO lang = getInputLanguage ();
19723da13bdSMasatake YAMATO
19823da13bdSMasatake YAMATO return lookupKeyword (s, lang);
19923da13bdSMasatake YAMATO }
20023da13bdSMasatake YAMATO
initToken(tokenInfo * token,void * data)2015d9d66cfSMasatake YAMATO static void initToken (tokenInfo *token, void *data)
20223da13bdSMasatake YAMATO {
203002dd246SMasatake YAMATO TCL (token)->pstate = data;
2045d9d66cfSMasatake YAMATO }
20523da13bdSMasatake YAMATO
readToken0(tokenInfo * const token,struct sTclParserState * pstate)2065d9d66cfSMasatake YAMATO static void readToken0 (tokenInfo *const token, struct sTclParserState *pstate)
2075d9d66cfSMasatake YAMATO {
2085d9d66cfSMasatake YAMATO int c = EOF;
2095d9d66cfSMasatake YAMATO bool escaped;
2105d9d66cfSMasatake YAMATO bool bol = (pstate->lastTokenType == TOKEN_TCL_EOL
2115d9d66cfSMasatake YAMATO || pstate->lastTokenType == ';'
2125d9d66cfSMasatake YAMATO || pstate->lastTokenType == TOKEN_TCL_UNDEFINED);
2136ae73029SMasatake YAMATO token->type = TOKEN_TCL_UNDEFINED;
21423da13bdSMasatake YAMATO token->keyword = KEYWORD_NONE;
21523da13bdSMasatake YAMATO vStringClear (token->string);
21623da13bdSMasatake YAMATO
21723da13bdSMasatake YAMATO getNextChar:
21823da13bdSMasatake YAMATO escaped = false;
21923da13bdSMasatake YAMATO
22023da13bdSMasatake YAMATO do {
22123da13bdSMasatake YAMATO c = getcFromInputFile ();
22223da13bdSMasatake YAMATO } while (c == ' ' || c== '\t' || c == '\f');
22323da13bdSMasatake YAMATO
22423da13bdSMasatake YAMATO if (c == '\\')
22523da13bdSMasatake YAMATO {
2265d9d66cfSMasatake YAMATO bol = false;
22723da13bdSMasatake YAMATO int c0 = getcFromInputFile ();
22823da13bdSMasatake YAMATO switch (c0)
22923da13bdSMasatake YAMATO {
23023da13bdSMasatake YAMATO case '\n':
23123da13bdSMasatake YAMATO case '\r':
23223da13bdSMasatake YAMATO goto getNextChar;
23323da13bdSMasatake YAMATO default:
23423da13bdSMasatake YAMATO escaped = true;
23523da13bdSMasatake YAMATO c = c0;
23623da13bdSMasatake YAMATO break;
23723da13bdSMasatake YAMATO }
23823da13bdSMasatake YAMATO }
23923da13bdSMasatake YAMATO
24023da13bdSMasatake YAMATO token->lineNumber = getInputLineNumber ();
24123da13bdSMasatake YAMATO token->filePosition = getInputFilePosition ();
24223da13bdSMasatake YAMATO
24323da13bdSMasatake YAMATO switch (c)
24423da13bdSMasatake YAMATO {
24523da13bdSMasatake YAMATO case EOF:
2466ae73029SMasatake YAMATO token->type = TOKEN_TCL_EOF;
24723da13bdSMasatake YAMATO break;
24823da13bdSMasatake YAMATO case '\n':
24923da13bdSMasatake YAMATO case '\r':
2506ae73029SMasatake YAMATO token->type = TOKEN_TCL_EOL;
25123da13bdSMasatake YAMATO break;
25223da13bdSMasatake YAMATO case '#':
25323da13bdSMasatake YAMATO if (!escaped)
25423da13bdSMasatake YAMATO {
2555d9d66cfSMasatake YAMATO if (bol)
2565d9d66cfSMasatake YAMATO {
25723da13bdSMasatake YAMATO do
25823da13bdSMasatake YAMATO c = getcFromInputFile ();
25923da13bdSMasatake YAMATO while (c != EOF && c != '\r' && c != '\n');
2605d9d66cfSMasatake YAMATO }
26123da13bdSMasatake YAMATO goto getNextChar;
26223da13bdSMasatake YAMATO }
26323da13bdSMasatake YAMATO case '"':
26423da13bdSMasatake YAMATO if (!escaped)
26523da13bdSMasatake YAMATO {
2666ae73029SMasatake YAMATO token->type = TOKEN_TCL_STRING;
2675c2563d5SMasatake YAMATO tokenPutc (token, c);
26823da13bdSMasatake YAMATO readString (token->string);
26923da13bdSMasatake YAMATO break;
27023da13bdSMasatake YAMATO }
271ca83e3bfSMasatake YAMATO case ';':
27223da13bdSMasatake YAMATO case '{':
27323da13bdSMasatake YAMATO case '}':
27423da13bdSMasatake YAMATO case '[':
27523da13bdSMasatake YAMATO case ']':
27623da13bdSMasatake YAMATO if (!escaped)
27723da13bdSMasatake YAMATO {
27871f9a680SMasatake YAMATO tokenPutc (token, c);
27923da13bdSMasatake YAMATO token->type = c;
28023da13bdSMasatake YAMATO break;
28123da13bdSMasatake YAMATO }
28223da13bdSMasatake YAMATO case '$':
28323da13bdSMasatake YAMATO if (!escaped)
28423da13bdSMasatake YAMATO {
2855c2563d5SMasatake YAMATO tokenPutc (token, c);
2866ae73029SMasatake YAMATO token->type = TOKEN_TCL_VARIABLE;
28723da13bdSMasatake YAMATO
28823da13bdSMasatake YAMATO int c0 = getcFromInputFile ();
28923da13bdSMasatake YAMATO if (c0 == EOF)
29023da13bdSMasatake YAMATO break;
29123da13bdSMasatake YAMATO
29223da13bdSMasatake YAMATO if (c0 == '{')
29323da13bdSMasatake YAMATO {
2946d139d9bSMasatake YAMATO tokenPutc (token, c0);
29523da13bdSMasatake YAMATO while ((c0 = getcFromInputFile ()) != EOF)
29623da13bdSMasatake YAMATO {
2975c2563d5SMasatake YAMATO tokenPutc (token, c0);
29823da13bdSMasatake YAMATO if (c0 == '}')
29923da13bdSMasatake YAMATO break;
30023da13bdSMasatake YAMATO }
30123da13bdSMasatake YAMATO }
3026d139d9bSMasatake YAMATO else if (isalnum (c0))
3036d139d9bSMasatake YAMATO {
3046d139d9bSMasatake YAMATO tokenPutc (token, c0);
30523da13bdSMasatake YAMATO readIdentifier (token->string);
3066d139d9bSMasatake YAMATO }
3076d139d9bSMasatake YAMATO else
3086d139d9bSMasatake YAMATO ungetcToInputFile (c0);
30923da13bdSMasatake YAMATO break;
31023da13bdSMasatake YAMATO }
31123da13bdSMasatake YAMATO default:
3125c2563d5SMasatake YAMATO tokenPutc (token, c);
31323da13bdSMasatake YAMATO readIdentifier (token->string);
31423da13bdSMasatake YAMATO
31523da13bdSMasatake YAMATO token->keyword = resolveKeyword (token->string);
31623da13bdSMasatake YAMATO if (token->keyword == KEYWORD_NONE)
3176ae73029SMasatake YAMATO token->type = TOKEN_TCL_IDENTIFIER;
31823da13bdSMasatake YAMATO else
3196ae73029SMasatake YAMATO token->type = TOKEN_TCL_KEYWORD;
32023da13bdSMasatake YAMATO break;
32123da13bdSMasatake YAMATO }
32223da13bdSMasatake YAMATO }
32323da13bdSMasatake YAMATO
readToken(tokenInfo * const token,void * data)32471f9a680SMasatake YAMATO static void readToken (tokenInfo *const token, void *data)
3255d9d66cfSMasatake YAMATO {
326002dd246SMasatake YAMATO struct sTclParserState *pstate = TCL_PSTATE(token);
3275d9d66cfSMasatake YAMATO
3285d9d66cfSMasatake YAMATO readToken0 (token, pstate);
3295d9d66cfSMasatake YAMATO
3305d9d66cfSMasatake YAMATO pstate->lastTokenType = token->type;
33171f9a680SMasatake YAMATO
33271f9a680SMasatake YAMATO if (data)
33371f9a680SMasatake YAMATO {
33471f9a680SMasatake YAMATO collector *col = data;
33571f9a680SMasatake YAMATO col->proc (token, col);
33671f9a680SMasatake YAMATO }
3375d9d66cfSMasatake YAMATO }
33823da13bdSMasatake YAMATO
tokenIsEOL(const tokenInfo * const token)33971f9a680SMasatake YAMATO static bool tokenIsEOL (const tokenInfo *const token)
3402b7fcc1eSMasatake YAMATO {
3412b7fcc1eSMasatake YAMATO if (token->type == ';'
3422b7fcc1eSMasatake YAMATO || tokenIsType (token, TCL_EOL)
3432b7fcc1eSMasatake YAMATO || tokenIsEOF (token))
3442b7fcc1eSMasatake YAMATO return true;
3452b7fcc1eSMasatake YAMATO return false;
3462b7fcc1eSMasatake YAMATO }
34723da13bdSMasatake YAMATO
skipToEndOfCmdline(tokenInfo * const token)34823da13bdSMasatake YAMATO static void skipToEndOfCmdline (tokenInfo *const token)
34923da13bdSMasatake YAMATO {
3502b7fcc1eSMasatake YAMATO while (!tokenIsEOL (token))
3512b7fcc1eSMasatake YAMATO {
3522b7fcc1eSMasatake YAMATO if ((token->type == '{')
35323da13bdSMasatake YAMATO || (token->type == '['))
35423da13bdSMasatake YAMATO tokenSkipOverPair(token);
35523da13bdSMasatake YAMATO tokenRead (token);
3562b7fcc1eSMasatake YAMATO }
35723da13bdSMasatake YAMATO }
35823da13bdSMasatake YAMATO
skipToEndOfTclCmdline(tokenInfo * const token)35994e60171SMasatake YAMATO extern void skipToEndOfTclCmdline (tokenInfo *const token)
36094e60171SMasatake YAMATO {
36194e60171SMasatake YAMATO skipToEndOfCmdline (token);
36294e60171SMasatake YAMATO }
36394e60171SMasatake YAMATO
isAbsoluteIdentifier(tokenInfo * const token)36423da13bdSMasatake YAMATO static bool isAbsoluteIdentifier(tokenInfo *const token)
36523da13bdSMasatake YAMATO {
3665c2563d5SMasatake YAMATO return !strncmp (tokenString (token), "::", 2);
36723da13bdSMasatake YAMATO }
36823da13bdSMasatake YAMATO
getLastComponentInIdentifier(tokenInfo * const token)36923da13bdSMasatake YAMATO static const char* getLastComponentInIdentifier(tokenInfo *const token)
37023da13bdSMasatake YAMATO {
3715c2563d5SMasatake YAMATO const char* s = tokenString (token);
37223da13bdSMasatake YAMATO char *last = strrstr(s, "::");
37323da13bdSMasatake YAMATO
37423da13bdSMasatake YAMATO if (last)
37523da13bdSMasatake YAMATO return last + 2;
37623da13bdSMasatake YAMATO else
37723da13bdSMasatake YAMATO return NULL;
37823da13bdSMasatake YAMATO }
37923da13bdSMasatake YAMATO
380c499a4edSMasatake YAMATO
notifyNamespaceImport(tokenInfo * const token)381bf898f4dSMasatake YAMATO static void notifyNamespaceImport (tokenInfo *const token)
382bf898f4dSMasatake YAMATO {
383bf898f4dSMasatake YAMATO subparser *sub;
384bf898f4dSMasatake YAMATO
385bf898f4dSMasatake YAMATO foreachSubparser (sub, false)
386bf898f4dSMasatake YAMATO {
387bf898f4dSMasatake YAMATO tclSubparser *tclsub = (tclSubparser *)sub;
388bf898f4dSMasatake YAMATO
389bf898f4dSMasatake YAMATO if (tclsub->namespaceImportNotify)
390bf898f4dSMasatake YAMATO {
391bf898f4dSMasatake YAMATO enterSubparser(sub);
3925c2563d5SMasatake YAMATO tclsub->namespaceImportNotify (tclsub, tokenString (token),
393002dd246SMasatake YAMATO TCL_PSTATE(token));
394bf898f4dSMasatake YAMATO leaveSubparser();
395bf898f4dSMasatake YAMATO }
396bf898f4dSMasatake YAMATO }
397bf898f4dSMasatake YAMATO }
398bf898f4dSMasatake YAMATO
notifyCommand(tokenInfo * const token,int parent)3993afb5475SMasatake YAMATO static int notifyCommand (tokenInfo *const token, int parent)
4006ae73029SMasatake YAMATO {
4016ae73029SMasatake YAMATO subparser *sub;
402c2c434adSjannick0 int r = CORK_NIL;
4036ae73029SMasatake YAMATO
4046ae73029SMasatake YAMATO foreachSubparser (sub, false)
4056ae73029SMasatake YAMATO {
4066ae73029SMasatake YAMATO tclSubparser *tclsub = (tclSubparser *)sub;
4074e7f9b4dSMasatake YAMATO
4084e7f9b4dSMasatake YAMATO if (tclsub->commandNotify)
4094e7f9b4dSMasatake YAMATO {
4106ae73029SMasatake YAMATO enterSubparser(sub);
4115c2563d5SMasatake YAMATO r = tclsub->commandNotify (tclsub, tokenString (token), parent,
412002dd246SMasatake YAMATO TCL_PSTATE(token));
4136ae73029SMasatake YAMATO leaveSubparser();
4146ae73029SMasatake YAMATO if (r != CORK_NIL)
4156ae73029SMasatake YAMATO break;
4166ae73029SMasatake YAMATO }
4174e7f9b4dSMasatake YAMATO }
4186ae73029SMasatake YAMATO return r;
4196ae73029SMasatake YAMATO }
4206ae73029SMasatake YAMATO
collectSignature(const tokenInfo * const token,collector * col)42171f9a680SMasatake YAMATO static void collectSignature (const tokenInfo *const token, collector * col)
42271f9a680SMasatake YAMATO {
42371f9a680SMasatake YAMATO if (tokenIsEOL (token))
42471f9a680SMasatake YAMATO return;
42571f9a680SMasatake YAMATO
42671f9a680SMasatake YAMATO if (tokenIsType (token, TCL_IDENTIFIER) &&
42771f9a680SMasatake YAMATO (col->depth == 1
42871f9a680SMasatake YAMATO || (col->depth == 2 && tokenIsType (token, TCL_IDENTIFIER)
42971f9a680SMasatake YAMATO && vStringLast (col->str) == '{')))
43071f9a680SMasatake YAMATO {
43171f9a680SMasatake YAMATO tagEntryInfo e;
43271f9a680SMasatake YAMATO initTagEntry (&e, tokenString (token), K_PARAMETER);
43371f9a680SMasatake YAMATO e.extensionFields.scopeIndex = col->scopeIndex;
434*50e0c3e8SMasatake YAMATO e.extensionFields.nth = col->nth++;
43571f9a680SMasatake YAMATO makeTagEntry (&e);
43671f9a680SMasatake YAMATO }
43771f9a680SMasatake YAMATO else if (tokenIsTypeVal (token, '{'))
43871f9a680SMasatake YAMATO col->depth++;
43971f9a680SMasatake YAMATO else if (tokenIsTypeVal (token, '}'))
44071f9a680SMasatake YAMATO col->depth--;
44171f9a680SMasatake YAMATO
44271f9a680SMasatake YAMATO if ((vStringLength (col->str) > 0
44371f9a680SMasatake YAMATO && vStringLast (col->str) != '{'
44471f9a680SMasatake YAMATO && vStringLast (col->str) != '['
44571f9a680SMasatake YAMATO && vStringLast (col->str) != '(')
44671f9a680SMasatake YAMATO && (!tokenIsTypeVal (token, '}'))
44771f9a680SMasatake YAMATO && (!tokenIsTypeVal (token, ']'))
44871f9a680SMasatake YAMATO && (!tokenIsTypeVal (token, ')')))
44971f9a680SMasatake YAMATO vStringPut (col->str, ' ');
45071f9a680SMasatake YAMATO vStringCat (col->str, token->string);
45171f9a680SMasatake YAMATO }
45271f9a680SMasatake YAMATO
parseProc(tokenInfo * const token,int parent)45323da13bdSMasatake YAMATO static void parseProc (tokenInfo *const token,
4543afb5475SMasatake YAMATO int parent)
45523da13bdSMasatake YAMATO {
45623da13bdSMasatake YAMATO int index = CORK_NIL;
45723da13bdSMasatake YAMATO int index_fq = CORK_NIL;
45823da13bdSMasatake YAMATO
45923da13bdSMasatake YAMATO tokenRead (token);
46023da13bdSMasatake YAMATO
4616ae73029SMasatake YAMATO if (tokenIsType(token, TCL_IDENTIFIER))
46223da13bdSMasatake YAMATO {
46323da13bdSMasatake YAMATO const char *last = getLastComponentInIdentifier (token);
46423da13bdSMasatake YAMATO if (last)
46523da13bdSMasatake YAMATO {
46623da13bdSMasatake YAMATO tagEntryInfo e;
46723da13bdSMasatake YAMATO
46816a2541cSMasatake YAMATO initTagEntry (&e, last, K_PROCEDURE);
46923da13bdSMasatake YAMATO e.lineNumber = token->lineNumber;
47023da13bdSMasatake YAMATO e.filePosition = token->filePosition;
47123da13bdSMasatake YAMATO
4725c2563d5SMasatake YAMATO int len = (last - tokenString (token));
47323da13bdSMasatake YAMATO vString *ns = vStringNew();
4743671ad72SMasatake YAMATO tagEntryInfo *e_parent = getEntryInCorkQueue (parent);
47523da13bdSMasatake YAMATO if (isAbsoluteIdentifier (token))
47623da13bdSMasatake YAMATO {
47723da13bdSMasatake YAMATO if (len > 2)
47823da13bdSMasatake YAMATO vStringNCopy (ns, token->string, len - 2);
47923da13bdSMasatake YAMATO }
4803671ad72SMasatake YAMATO else if (e_parent)
48123da13bdSMasatake YAMATO {
482c22925e9SMasatake YAMATO const char * sep = scopeSeparatorFor (getInputLanguage(),
483c22925e9SMasatake YAMATO K_PROCEDURE,
484c22925e9SMasatake YAMATO e_parent->kindIndex);
48523da13bdSMasatake YAMATO vStringCatS(ns, e_parent->name);
486c22925e9SMasatake YAMATO vStringCatS(ns, sep);
48723da13bdSMasatake YAMATO vStringNCopy(ns, token->string, len - 2);
48823da13bdSMasatake YAMATO }
4893671ad72SMasatake YAMATO else
490ff499819SMasatake YAMATO vStringNCopy (ns, token->string, len - 2);
49123da13bdSMasatake YAMATO
49223da13bdSMasatake YAMATO if (vStringLength(ns) > 0)
49323da13bdSMasatake YAMATO {
494f92e6bf2SMasatake YAMATO e.extensionFields.scopeKindIndex = K_NAMESPACE;
49523da13bdSMasatake YAMATO e.extensionFields.scopeName = vStringValue (ns);
49623da13bdSMasatake YAMATO }
49723da13bdSMasatake YAMATO
4988ee65243SMasatake YAMATO e.skipAutoFQEmission = 1;
49923da13bdSMasatake YAMATO index = makeTagEntry (&e);
50023da13bdSMasatake YAMATO
50123da13bdSMasatake YAMATO if (isXtagEnabled(XTAG_QUALIFIED_TAGS))
50223da13bdSMasatake YAMATO {
503c22925e9SMasatake YAMATO const char * sep = scopeSeparatorFor (getInputLanguage(),
504c22925e9SMasatake YAMATO K_PROCEDURE,
505a3f7eeb8SMasatake YAMATO vStringIsEmpty (ns)
506a3f7eeb8SMasatake YAMATO ? KIND_GHOST_INDEX
507a3f7eeb8SMasatake YAMATO : K_NAMESPACE);
508c22925e9SMasatake YAMATO
509c22925e9SMasatake YAMATO vStringCatS (ns, sep);
51023da13bdSMasatake YAMATO vStringCatS (ns, last);
51123da13bdSMasatake YAMATO
51216a2541cSMasatake YAMATO index_fq = makeSimpleTag (ns, K_PROCEDURE);
51323da13bdSMasatake YAMATO tagEntryInfo *e_fq = getEntryInCorkQueue (index_fq);
5143671ad72SMasatake YAMATO if (e_fq)
51523da13bdSMasatake YAMATO markTagExtraBit (e_fq, XTAG_QUALIFIED_TAGS);
51623da13bdSMasatake YAMATO }
51723da13bdSMasatake YAMATO vStringDelete (ns);
51823da13bdSMasatake YAMATO }
51923da13bdSMasatake YAMATO else
52023da13bdSMasatake YAMATO {
52123da13bdSMasatake YAMATO tagEntryInfo *ep;
52216a2541cSMasatake YAMATO index = makeSimpleTag (token->string, K_PROCEDURE);
52323da13bdSMasatake YAMATO ep = getEntryInCorkQueue (index);
5243671ad72SMasatake YAMATO if (ep)
52523da13bdSMasatake YAMATO ep->extensionFields.scopeIndex = parent;
52623da13bdSMasatake YAMATO }
52723da13bdSMasatake YAMATO }
52823da13bdSMasatake YAMATO
52971f9a680SMasatake YAMATO vString *signature = NULL;
5302b7fcc1eSMasatake YAMATO if (!tokenIsEOL (token))
53123da13bdSMasatake YAMATO {
5322b7fcc1eSMasatake YAMATO tokenRead (token);
53371f9a680SMasatake YAMATO if (tokenIsType (token, TCL_IDENTIFIER))
53471f9a680SMasatake YAMATO {
53571f9a680SMasatake YAMATO tagEntryInfo e;
53671f9a680SMasatake YAMATO initTagEntry (&e, tokenString (token), K_PARAMETER);
53771f9a680SMasatake YAMATO e.extensionFields.scopeIndex = index;
53871f9a680SMasatake YAMATO makeTagEntry (&e);
53971f9a680SMasatake YAMATO signature = vStringNewCopy (token->string);
54071f9a680SMasatake YAMATO }
54171f9a680SMasatake YAMATO else if (token->type == '{')
54271f9a680SMasatake YAMATO {
54371f9a680SMasatake YAMATO signature = vStringNewInit ("{");
54471f9a680SMasatake YAMATO collector col = {
54571f9a680SMasatake YAMATO .proc = collectSignature,
54671f9a680SMasatake YAMATO .str = signature,
54771f9a680SMasatake YAMATO .depth = 1,
54871f9a680SMasatake YAMATO .scopeIndex = index,
549*50e0c3e8SMasatake YAMATO .nth = 0,
55071f9a680SMasatake YAMATO };
55171f9a680SMasatake YAMATO tokenSkipOverPairFull (token, &col);
55271f9a680SMasatake YAMATO }
55371f9a680SMasatake YAMATO
55423da13bdSMasatake YAMATO skipToEndOfCmdline(token);
55523da13bdSMasatake YAMATO }
55623da13bdSMasatake YAMATO
5573671ad72SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (index);
5583671ad72SMasatake YAMATO if (e)
55923da13bdSMasatake YAMATO {
56023da13bdSMasatake YAMATO e->extensionFields.endLine = token->lineNumber;
56123da13bdSMasatake YAMATO
56271f9a680SMasatake YAMATO if (signature)
56371f9a680SMasatake YAMATO {
56471f9a680SMasatake YAMATO e->extensionFields.signature = vStringDeleteUnwrap (signature);
56571f9a680SMasatake YAMATO signature = NULL;
56671f9a680SMasatake YAMATO }
56771f9a680SMasatake YAMATO
5683671ad72SMasatake YAMATO tagEntryInfo *e_fq = getEntryInCorkQueue (index_fq);
5693671ad72SMasatake YAMATO if (e_fq)
57023da13bdSMasatake YAMATO {
57171f9a680SMasatake YAMATO const char *sig = e->extensionFields.signature;
5723671ad72SMasatake YAMATO e_fq->extensionFields.endLine = token->lineNumber;
57371f9a680SMasatake YAMATO if (sig)
5743671ad72SMasatake YAMATO e_fq->extensionFields.signature = eStrdup (sig);
57523da13bdSMasatake YAMATO }
57623da13bdSMasatake YAMATO }
57771f9a680SMasatake YAMATO vStringDelete (signature); /* NULL is acceptable */
57823da13bdSMasatake YAMATO }
57923da13bdSMasatake YAMATO
parseNamespace(tokenInfo * const token,int parent)58023da13bdSMasatake YAMATO static void parseNamespace (tokenInfo *const token,
5813afb5475SMasatake YAMATO int parent)
58223da13bdSMasatake YAMATO {
58323da13bdSMasatake YAMATO tokenRead (token);
58423da13bdSMasatake YAMATO if (tokenIsEOF(token))
58523da13bdSMasatake YAMATO return;
58623da13bdSMasatake YAMATO
587bf898f4dSMasatake YAMATO if (tokenIsType (token, TCL_IDENTIFIER) &&
588bf898f4dSMasatake YAMATO (strcmp(tokenString(token), "import") == 0))
589bf898f4dSMasatake YAMATO {
590bf898f4dSMasatake YAMATO while (1)
591bf898f4dSMasatake YAMATO {
592bf898f4dSMasatake YAMATO tokenRead (token);
593bf898f4dSMasatake YAMATO
594bf898f4dSMasatake YAMATO if (!tokenIsType (token, TCL_IDENTIFIER))
595bf898f4dSMasatake YAMATO break;
596bf898f4dSMasatake YAMATO
5975c2563d5SMasatake YAMATO if (tokenString(token)[0] == '-')
598bf898f4dSMasatake YAMATO continue;
599bf898f4dSMasatake YAMATO
600bf898f4dSMasatake YAMATO notifyNamespaceImport (token);
601bf898f4dSMasatake YAMATO }
602bf898f4dSMasatake YAMATO skipToEndOfCmdline(token);
603bf898f4dSMasatake YAMATO return;
604bf898f4dSMasatake YAMATO }
605bf898f4dSMasatake YAMATO else if (!tokenIsKeyword (token, EVAL))
60623da13bdSMasatake YAMATO return;
60723da13bdSMasatake YAMATO
60823da13bdSMasatake YAMATO tokenRead (token);
6096ae73029SMasatake YAMATO if (!tokenIsType (token, TCL_IDENTIFIER))
61023da13bdSMasatake YAMATO {
61123da13bdSMasatake YAMATO skipToEndOfCmdline(token);
61223da13bdSMasatake YAMATO return;
61323da13bdSMasatake YAMATO }
61423da13bdSMasatake YAMATO
61516a2541cSMasatake YAMATO int index = makeSimpleTag (token->string, K_NAMESPACE);
61623da13bdSMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (index);
6173671ad72SMasatake YAMATO if (e && parent != CORK_NIL && !isAbsoluteIdentifier(token))
61823da13bdSMasatake YAMATO e->extensionFields.scopeIndex = parent;
61923da13bdSMasatake YAMATO
62023da13bdSMasatake YAMATO tokenRead (token);
62123da13bdSMasatake YAMATO if (token->type != '{')
62223da13bdSMasatake YAMATO {
62323da13bdSMasatake YAMATO skipToEndOfCmdline(token);
62423da13bdSMasatake YAMATO return;
62523da13bdSMasatake YAMATO }
62623da13bdSMasatake YAMATO
62723da13bdSMasatake YAMATO do {
62823da13bdSMasatake YAMATO tokenRead (token);
62923da13bdSMasatake YAMATO if (tokenIsKeyword (token, NAMESPACE))
63023da13bdSMasatake YAMATO parseNamespace (token, index);
63123da13bdSMasatake YAMATO else if (tokenIsKeyword (token, PROC))
63223da13bdSMasatake YAMATO parseProc (token, index);
6336ae73029SMasatake YAMATO else if (tokenIsType (token, TCL_IDENTIFIER))
6346ae73029SMasatake YAMATO {
6356ae73029SMasatake YAMATO notifyCommand (token, index);
6366ae73029SMasatake YAMATO skipToEndOfCmdline(token); /* ??? */
6376ae73029SMasatake YAMATO }
63823da13bdSMasatake YAMATO else if (token->type == '}')
63923da13bdSMasatake YAMATO {
6403671ad72SMasatake YAMATO if (e)
64123da13bdSMasatake YAMATO e->extensionFields.endLine = token->lineNumber;
64223da13bdSMasatake YAMATO break;
64323da13bdSMasatake YAMATO }
64423da13bdSMasatake YAMATO else
64523da13bdSMasatake YAMATO skipToEndOfCmdline(token);
64623da13bdSMasatake YAMATO } while (!tokenIsEOF(token));
6473ae02089SMasatake YAMATO }
6483ae02089SMasatake YAMATO
parsePackage(tokenInfo * const token)649c499a4edSMasatake YAMATO static void parsePackage (tokenInfo *const token)
650c499a4edSMasatake YAMATO {
651c499a4edSMasatake YAMATO tokenRead (token);
652c499a4edSMasatake YAMATO if (tokenIsType (token, TCL_IDENTIFIER)
6535c2563d5SMasatake YAMATO && (strcmp (tokenString (token), "require") == 0))
654c499a4edSMasatake YAMATO {
655c499a4edSMasatake YAMATO next:
656c499a4edSMasatake YAMATO tokenRead (token);
657c499a4edSMasatake YAMATO if (tokenIsType (token, TCL_IDENTIFIER)
658c499a4edSMasatake YAMATO && (vStringLength (token->string) > 0))
659c499a4edSMasatake YAMATO {
6605c2563d5SMasatake YAMATO if (tokenString(token)[0] == '-')
661c499a4edSMasatake YAMATO goto next;
662c499a4edSMasatake YAMATO }
663c499a4edSMasatake YAMATO }
664c499a4edSMasatake YAMATO skipToEndOfCmdline(token);
665c499a4edSMasatake YAMATO }
666c499a4edSMasatake YAMATO
667c499a4edSMasatake YAMATO
findTclTags(void)6683ae02089SMasatake YAMATO static void findTclTags (void)
6693ae02089SMasatake YAMATO {
6705d9d66cfSMasatake YAMATO struct sTclParserState pstate = {
6715d9d66cfSMasatake YAMATO .lastTokenType = TOKEN_TCL_UNDEFINED,
6725d9d66cfSMasatake YAMATO };
6735d9d66cfSMasatake YAMATO tokenInfo *const token = newTclToken (&pstate);
6743ae02089SMasatake YAMATO
67523da13bdSMasatake YAMATO do {
67623da13bdSMasatake YAMATO tokenRead (token);
67723da13bdSMasatake YAMATO if (tokenIsKeyword (token, NAMESPACE))
67823da13bdSMasatake YAMATO parseNamespace (token, CORK_NIL);
67923da13bdSMasatake YAMATO else if (tokenIsKeyword (token, PROC))
68023da13bdSMasatake YAMATO parseProc (token, CORK_NIL);
681c499a4edSMasatake YAMATO else if (tokenIsKeyword (token, PACKAGE))
682c499a4edSMasatake YAMATO parsePackage (token);
6836ae73029SMasatake YAMATO else if (tokenIsType (token, TCL_IDENTIFIER))
6846ae73029SMasatake YAMATO {
6856ae73029SMasatake YAMATO notifyCommand (token, CORK_NIL);
6866ae73029SMasatake YAMATO skipToEndOfCmdline(token); /* ??? */
6876ae73029SMasatake YAMATO }
68823da13bdSMasatake YAMATO else
68923da13bdSMasatake YAMATO skipToEndOfCmdline(token);
69023da13bdSMasatake YAMATO } while (!tokenIsEOF(token));
6913ae02089SMasatake YAMATO
692a203ce0eSMasatake YAMATO tokenDelete (token);
69323da13bdSMasatake YAMATO flashTokenBacklog (&tclTokenInfoClass);
6943ae02089SMasatake YAMATO }
6953ae02089SMasatake YAMATO
TclParser(void)6963ae02089SMasatake YAMATO extern parserDefinition* TclParser (void)
6973ae02089SMasatake YAMATO {
698ec223a9aSMasatake YAMATO static const char *const extensions [] = { "tcl", "tk", "wish", "exp", NULL };
699137271eeSMasatake YAMATO static const char *const aliases [] = {"expect", "tclsh", NULL };
70098d31190SMasatake YAMATO
7013ae02089SMasatake YAMATO parserDefinition* def = parserNew ("Tcl");
70209ae690fSMasatake YAMATO def->kindTable = TclKinds;
7033db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (TclKinds);
7043ae02089SMasatake YAMATO def->extensions = extensions;
70598d31190SMasatake YAMATO def->aliases = aliases;
70623da13bdSMasatake YAMATO def->keywordTable = TclKeywordTable;
70723da13bdSMasatake YAMATO def->keywordCount = ARRAY_SIZE (TclKeywordTable);
70823da13bdSMasatake YAMATO
7093ae02089SMasatake YAMATO def->parser = findTclTags;
7106b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
71123da13bdSMasatake YAMATO def->requestAutomaticFQTag = true;
7125535211dSMasatake YAMATO def->defaultScopeSeparator = "::";
7137de1c18bSMasatake YAMATO def->defaultRootScopeSeparator = "::";
7145535211dSMasatake YAMATO
7153ae02089SMasatake YAMATO return def;
7163ae02089SMasatake YAMATO }
717