Update all parsers and related files to ctags p6.1.20240421.0
[geany-mirror.git] / ctags / parsers / autoit.c
blobc6f06184703f79188a84091a3572abf904310397
1 /*
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/
14 * INCLUDE FILES
16 #include "general.h" /* must always come first */
18 #include <string.h>
20 #include "parse.h"
21 #include "entry.h"
22 #include "nestlevel.h"
23 #include "read.h"
24 #include "routines.h"
25 #include "vstring.h"
28 * DATA DEFINITIONS
30 typedef enum {
31 K_FUNCTION,
32 K_REGION,
33 K_GLOBALVAR,
34 K_LOCALVAR,
35 K_SCRIPT,
36 } AutoItKind;
38 typedef enum {
39 R_INCLUDE_SYSTEM,
40 R_INCLUDE_LOCAL,
41 } AutoItIncludeRole;
43 typedef enum {
44 F_PROPERTIES,
45 } AutoItField;
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 [] = {
63 .name = "properties",
64 .description = "properties (static, volatile, ...)",
65 .enabled = false,
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;
89 return matched;
92 static int makeAutoItTag (const NestingLevels *const nls,
93 const vString* const name,
94 const int kindIndex,
95 const vString *const signature)
97 int r = CORK_NIL;
99 if (isInputLanguageKindEnabled(kindIndex) && name != NULL && vStringLength (name) > 0)
101 NestingLevel *nl = nestingLevelsGetCurrent (nls);
102 tagEntryInfo e;
104 initTagEntry (&e, vStringValue (name), kindIndex);
106 if (nl)
107 e.extensionFields.scopeIndex = nl->corkIndex;
108 if (signature)
109 e.extensionFields.signature = vStringValue (signature);
111 r = makeTagEntry (&e);
114 return r;
117 static int makeSimpleAutoItTag (const NestingLevels *const nls,
118 const vString* const name,
119 const int kindIndex)
121 return makeAutoItTag (nls, name, kindIndex, NULL);
124 static void setEndLine (const NestingLevels *const nls)
126 NestingLevel *nl = nestingLevelsGetCurrent (nls);
128 if (nl)
129 setTagEndLineToCorkEntry (nl->corkIndex,
130 getInputLineNumber ());
133 static void skipSpaces (const unsigned char **p)
135 while (isspace (**p))
136 ++(*p);
139 /* parses after a "func" keyword */
140 static int parseFunc (const unsigned char *p, NestingLevels *nls)
142 int k = CORK_NIL;
143 vString *name = vStringNew ();
145 skipSpaces (&p);
146 while (isIdentChar (*p))
148 vStringPut (name, *p);
149 ++p;
151 skipSpaces (&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);
167 return k;
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;
180 if (p [0] == '#')
182 p++;
183 if (match (p, "cs", NULL) || match (p, "comments-start", NULL))
184 commentDepth++;
185 else if (commentDepth > 0)
187 if (match (p, "ce", NULL) || match (p, "comments-end", NULL))
188 commentDepth--;
190 else if (match (p, "region", &p))
192 skipSpaces (&p);
194 if (*p != '\0')
196 int k;
198 vStringCatS (name, (const char *) p);
199 k = makeSimpleAutoItTag (nls, name, K_REGION);
200 nestingLevelsPush (nls, k);
201 vStringClear (name);
204 else if (nls->n > 0 && match (p, "endregion", NULL))
206 setEndLine (nls);
207 nestingLevelsPop (nls);
209 else if (match (p, "include", &p))
211 skipSpaces (&p);
212 if (*p == '<' || *p == '"')
214 const AutoItIncludeRole role = (*p == '<')
215 ? R_INCLUDE_SYSTEM
216 : R_INCLUDE_LOCAL;
218 ++p;
219 while (*p != '\0' && *p != '>' && *p != '"')
221 vStringPut (name, *p);
222 ++p;
224 if (vStringLength(name) > 0)
226 makeSimpleRefTag (name, K_SCRIPT, role);
227 vStringClear (name);
232 else if (commentDepth == 0)
234 bool isGlobal = false;
235 bool isStatic = false;
237 /* skip white space */
238 skipSpaces (&p);
239 if (*p == ';')
240 /* ignore single-line comments */;
241 else if (match (p, "volatile", &p))
243 skipSpaces (&p);
244 if (match (p, "func", &p))
246 int k = parseFunc (p, nls);
247 if (k != CORK_NIL)
248 attachParserFieldToCorkEntry (k, AutoItFields[F_PROPERTIES].ftype, "volatile");
251 else if (match (p, "func", &p))
252 parseFunc (p, nls);
253 else if (nls->n > 0 && match (p, "endfunc", NULL))
255 setEndLine (nls);
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
268 skipSpaces (&p);
269 if (isStatic)
271 /* skip optional modifiers */
272 if ((isGlobal = match (p, "global", &p)) ||
273 match (p, "local", &p))
275 skipSpaces (&p);
278 else if ((isStatic = match (p, "static", &p)))
279 skipSpaces (&p);
280 else if (match (p, "const", &p))
281 skipSpaces (&p);
282 if (*p == '$')
284 p++;
285 while (isIdentChar (*p))
287 vStringPut (name, *p);
288 ++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");
296 vStringClear (name);
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;
317 def->versionAge = 0;
318 return def;