2 * Copyright (c) 2017, Alexey Olenich
3 * Copyright (c) 2018, Colomban Wendling <colomban@geany.org>
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License version 2 or (at your option) any later version.
8 * This module contains functions for generating tags for AutoIt functions.
9 * Homepage https://www.autoitscript.com/site/autoit/
10 * Online Documentation https://www.autoitscript.com/autoit3/docs/
16 #include "general.h" /* must always come first */
22 #include "nestlevel.h"
47 static roleDefinition AutoItIncludeRoles
[] = {
48 { true, "system", "system include" },
49 { true, "local", "local include" },
52 static kindDefinition AutoItKinds
[] = {
53 { true, 'f', "func", "functions" },
54 { true, 'r', "region", "regions" },
55 { true, 'g', "global", "global variables" },
56 { true, 'l', "local", "local variables" },
57 { true, 'S', "script", "included scripts",
58 .referenceOnly
= true, ATTACH_ROLES (AutoItIncludeRoles
) },
61 static fieldDefinition AutoItFields
[] = {
64 .description
= "properties (static, volatile, ...)",
70 * FUNCTION DEFINITIONS
73 /* it's unclear what *is* an identifier character, so maybe we're too strict */
74 static bool isIdentChar (int c
)
76 return isalnum (c
) || c
== '_';
79 static bool match (const unsigned char *line
, const char *word
,
80 const unsigned char **positionAfter
)
82 size_t len
= strlen (word
);
83 bool matched
= (strncasecmp ((const char*) line
, word
, len
) == 0 &&
84 ! isIdentChar (line
[len
]));
86 if (matched
&& positionAfter
)
87 *positionAfter
= line
+ len
;
92 static int makeAutoItTag (const NestingLevels
*const nls
,
93 const vString
* const name
,
95 const vString
*const signature
)
99 if (isInputLanguageKindEnabled(kindIndex
) && name
!= NULL
&& vStringLength (name
) > 0)
101 NestingLevel
*nl
= nestingLevelsGetCurrent (nls
);
104 initTagEntry (&e
, vStringValue (name
), kindIndex
);
107 e
.extensionFields
.scopeIndex
= nl
->corkIndex
;
109 e
.extensionFields
.signature
= vStringValue (signature
);
111 r
= makeTagEntry (&e
);
117 static int makeSimpleAutoItTag (const NestingLevels
*const nls
,
118 const vString
* const name
,
121 return makeAutoItTag (nls
, name
, kindIndex
, NULL
);
124 static void setEndLine (const NestingLevels
*const nls
)
126 NestingLevel
*nl
= nestingLevelsGetCurrent (nls
);
129 setTagEndLineToCorkEntry (nl
->corkIndex
,
130 getInputLineNumber ());
133 static void skipSpaces (const unsigned char **p
)
135 while (isspace (**p
))
139 /* parses after a "func" keyword */
140 static int parseFunc (const unsigned char *p
, NestingLevels
*nls
)
143 vString
*name
= vStringNew ();
146 while (isIdentChar (*p
))
148 vStringPut (name
, *p
);
152 if (*p
== '(' && (vStringLength (name
) > 0))
154 vString
*signature
= vStringNew ();
157 vStringPut (signature
, *p
);
158 while (*p
!= ')' && *p
++);
160 k
= makeAutoItTag (nls
, name
, K_FUNCTION
, signature
);
161 nestingLevelsPush (nls
, k
);
162 vStringDelete (signature
);
165 vStringDelete (name
);
170 static void findAutoItTags (void)
172 vString
*name
= vStringNew ();
173 const unsigned char *line
;
174 NestingLevels
*nls
= nestingLevelsNew (0);
175 unsigned int commentDepth
= 0;
177 while ((line
= readLineFromInputFile ()) != NULL
)
179 const unsigned char* p
= line
;
183 if (match (p
, "cs", NULL
) || match (p
, "comments-start", NULL
))
185 else if (commentDepth
> 0)
187 if (match (p
, "ce", NULL
) || match (p
, "comments-end", NULL
))
190 else if (match (p
, "region", &p
))
198 vStringCatS (name
, (const char *) p
);
199 k
= makeSimpleAutoItTag (nls
, name
, K_REGION
);
200 nestingLevelsPush (nls
, k
);
204 else if (nls
->n
> 0 && match (p
, "endregion", NULL
))
207 nestingLevelsPop (nls
);
209 else if (match (p
, "include", &p
))
212 if (*p
== '<' || *p
== '"')
214 const AutoItIncludeRole role
= (*p
== '<')
219 while (*p
!= '\0' && *p
!= '>' && *p
!= '"')
221 vStringPut (name
, *p
);
224 if (vStringLength(name
) > 0)
226 makeSimpleRefTag (name
, K_SCRIPT
, role
);
232 else if (commentDepth
== 0)
234 bool isGlobal
= false;
235 bool isStatic
= false;
237 /* skip white space */
240 /* ignore single-line comments */;
241 else if (match (p
, "volatile", &p
))
244 if (match (p
, "func", &p
))
246 int k
= parseFunc (p
, nls
);
248 attachParserFieldToCorkEntry (k
, AutoItFields
[F_PROPERTIES
].ftype
, "volatile");
251 else if (match (p
, "func", &p
))
253 else if (nls
->n
> 0 && match (p
, "endfunc", NULL
))
256 nestingLevelsPop (nls
);
258 else if ((isStatic
= match (p
, "static", &p
)) ||
259 (isGlobal
= match (p
, "global", &p
)) ||
260 match (p
, "local", &p
))
263 * variable-identifier ::= "$[a-zA-Z_0-9]+"
264 * scope-modifier ::= "Local" | "Global"
265 * variable-declaration ::= "Static" [scope-modifier] variable-identifier
266 * scope-modifier ["Static" | "Const"] variable-identifier
271 /* skip optional modifiers */
272 if ((isGlobal
= match (p
, "global", &p
)) ||
273 match (p
, "local", &p
))
278 else if ((isStatic
= match (p
, "static", &p
)))
280 else if (match (p
, "const", &p
))
285 while (isIdentChar (*p
))
287 vStringPut (name
, *p
);
290 if (vStringLength(name
) > 0)
292 int k
= makeSimpleAutoItTag (nls
, name
, isGlobal
? K_GLOBALVAR
: K_LOCALVAR
);
293 if (k
!= CORK_NIL
&& isStatic
)
294 attachParserFieldToCorkEntry (k
, AutoItFields
[F_PROPERTIES
].ftype
, "static");
301 vStringDelete (name
);
302 nestingLevelsFree (nls
);
305 parserDefinition
*AutoItParser (void)
307 static char const *extensions
[] = { "au3", "AU3", "aU3", "Au3", NULL
};
308 parserDefinition
* def
= parserNew ("AutoIt");
309 def
->kindTable
= AutoItKinds
;
310 def
->kindCount
= ARRAY_SIZE (AutoItKinds
);
311 def
->fieldTable
= AutoItFields
;
312 def
->fieldCount
= ARRAY_SIZE (AutoItFields
);
313 def
->extensions
= extensions
;
314 def
->parser
= findAutoItTags
;
315 def
->useCork
= CORK_QUEUE
;
316 def
->versionCurrent
= 1;