Update HACKING for changed doc generation instructions
[geany-mirror.git] / tagmanager / ctags / basic.c
blobe3dd4580c46366909d47025dff2596eb3ecd4ea4
1 /*
2 * Copyright (c) 2000-2006, Darren Hiebert, Elias Pschernig
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License.
7 * This module contains functions for generating tags for BlitzBasic
8 * (BlitzMax), PureBasic and FreeBasic language files. For now, this is kept
9 * quite simple - but feel free to ask for more things added any time -
10 * patches are of course most welcome.
14 * INCLUDE FILES
16 #include "general.h" /* must always come first */
18 #include <string.h>
20 #include "parse.h"
21 #include "read.h"
22 #include "vstring.h"
25 * DATA DEFINITIONS
27 typedef enum {
28 K_CONST,
29 K_FUNCTION,
30 K_LABEL,
31 K_TYPE,
32 K_VARIABLE,
33 K_ENUM
34 } BasicKind;
36 typedef struct {
37 char const *token;
38 BasicKind kind;
39 } KeyWord;
41 static kindOption BasicKinds[] = {
42 {TRUE, 'c', "macro", "constants"},
43 {TRUE, 'f', "function", "functions"},
44 {TRUE, 'l', "namespace", "labels"},
45 {TRUE, 't', "struct", "types"},
46 {TRUE, 'v', "variable", "variables"},
47 {TRUE, 'g', "externvar", "enumerations"}
50 static KeyWord freebasic_keywords[] = {
51 {"dim", K_VARIABLE}, /* must always be the first */
52 {"common", K_VARIABLE}, /* must always be the second */
53 {"const", K_CONST}, /* must always be the third */
54 {"function", K_FUNCTION},
55 {"sub", K_FUNCTION},
56 {"property", K_FUNCTION},
57 {"constructor", K_FUNCTION},
58 {"destructor", K_FUNCTION},
59 {"private sub", K_FUNCTION},
60 {"public sub", K_FUNCTION},
61 {"private function", K_FUNCTION},
62 {"public function", K_FUNCTION},
63 {"type", K_TYPE},
64 {"enum", K_ENUM},
65 {NULL, 0}
69 * FUNCTION DEFINITIONS
72 /* Match the name of a dim or const starting at pos. */
73 static int extract_dim (char const *pos, vString * name, BasicKind kind)
75 const char *old_pos = pos;
76 while (isspace (*pos))
77 pos++;
79 /* create tags only if there is some space between the keyword and the identifier */
80 if (old_pos == pos)
81 return 0;
83 vStringClear (name);
85 if (strncasecmp (pos, "shared", 6) == 0)
86 pos += 6; /* skip keyword "shared" */
88 while (isspace (*pos))
89 pos++;
91 /* capture "dim as String str" */
92 if (strncasecmp (pos, "as", 2) == 0)
94 pos += 2; /* skip keyword "as" */
96 while (isspace (*pos))
97 pos++;
98 while (!isspace (*pos)) /* skip next part which is a type */
99 pos++;
100 while (isspace (*pos))
101 pos++;
102 /* now we are at the name */
104 /* capture "dim as foo ptr bar" */
105 if (strncasecmp (pos, "ptr", 3) == 0 && isspace(*(pos+4)))
107 pos += 3; /* skip keyword "ptr" */
108 while (isspace (*pos))
109 pos++;
111 /* capture "dim as string * 4096 chunk" */
112 if (strncmp (pos, "*", 1) == 0)
114 pos += 1; /* skip "*" */
115 while (isspace (*pos) || isdigit(*pos) || ispunct(*pos))
116 pos++;
119 for (; *pos && !isspace (*pos) && *pos != '(' && *pos != ',' && *pos != '='; pos++)
120 vStringPut (name, *pos);
121 vStringTerminate (name);
122 makeSimpleTag (name, BasicKinds, kind);
124 /* if the line contains a ',', we have multiple declarations */
125 while (*pos && strchr (pos, ','))
127 /* skip all we don't need(e.g. "..., new_array(5), " we skip "(5)") */
128 while (*pos != ',' && *pos != '\'')
129 pos++;
131 if (*pos == '\'')
132 return 0; /* break if we are in a comment */
134 while (isspace (*pos) || *pos == ',')
135 pos++;
137 if (*pos == '\'')
138 return 0; /* break if we are in a comment */
140 vStringClear (name);
141 for (; *pos && !isspace (*pos) && *pos != '(' && *pos != ',' && *pos != '='; pos++)
142 vStringPut (name, *pos);
143 vStringTerminate (name);
144 makeSimpleTag (name, BasicKinds, kind);
147 vStringDelete (name);
148 return 1;
151 /* Match the name of a tag (function, variable, type, ...) starting at pos. */
152 static char const *extract_name (char const *pos, vString * name)
154 while (isspace (*pos))
155 pos++;
156 vStringClear (name);
157 for (; *pos && !isspace (*pos) && *pos != '(' && *pos != ',' && *pos != '='; pos++)
158 vStringPut (name, *pos);
159 vStringTerminate (name);
160 return pos;
163 /* Match a keyword starting at p (case insensitive). */
164 static int match_keyword (const char *p, KeyWord const *kw)
166 vString *name;
167 size_t i;
168 int j;
169 const char *old_p;
170 for (i = 0; i < strlen (kw->token); i++)
172 if (tolower (p[i]) != kw->token[i])
173 return 0;
175 name = vStringNew ();
176 p += i;
177 if (kw == &freebasic_keywords[0] ||
178 kw == &freebasic_keywords[1] ||
179 kw == &freebasic_keywords[2])
180 return extract_dim (p, name, kw->kind); /* extract_dim adds the found tag(s) */
182 old_p = p;
183 while (isspace (*p))
184 p++;
186 /* create tags only if there is some space between the keyword and the identifier */
187 if (old_p == p)
189 vStringDelete (name);
190 return 0;
193 for (j = 0; j < 1; j++)
195 p = extract_name (p, name);
197 makeSimpleTag (name, BasicKinds, kw->kind);
198 vStringDelete (name);
200 return 1;
203 /* Match a "label:" style label. */
204 static void match_colon_label (char const *p)
206 char const *end = p + strlen (p) - 1;
207 while (isspace (*end))
208 end--;
209 if (*end == ':')
211 vString *name = vStringNew ();
212 vStringNCatS (name, p, end - p);
213 makeSimpleTag (name, BasicKinds, K_LABEL);
214 vStringDelete (name);
218 static void findBasicTags (void)
220 const char *line;
221 KeyWord *keywords;
223 keywords = freebasic_keywords;
225 while ((line = (const char *) fileReadLine ()) != NULL)
227 const char *p = line;
228 KeyWord const *kw;
230 while (isspace (*p))
231 p++;
233 /* Empty line or comment? */
234 if (!*p || *p == '\'')
235 continue;
237 /* In Basic, keywords always are at the start of the line. */
238 for (kw = keywords; kw->token; kw++)
239 if (match_keyword (p, kw)) break;
241 /* Is it a label? */
242 match_colon_label (p);
246 parserDefinition *FreeBasicParser (void)
248 static char const *extensions[] = { "bas", "bi", "bb", "pb", NULL };
249 parserDefinition *def = parserNew ("FreeBasic");
250 def->kinds = BasicKinds;
251 def->kindCount = KIND_COUNT (BasicKinds);
252 def->extensions = extensions;
253 def->parser = findBasicTags;
254 return def;
257 /* vi:set tabstop=4 shiftwidth=4: */