Making "inline" behave like an attribute. Fixes #1
[arduino-ctags.git] / beta.c
blobda195a1a4b876b5b9760f8121d769ae0f1ced7d9
1 /*
2 * $Id: beta.c 536 2007-06-02 06:09:00Z elliotth $
4 * Copyright (c) 1999-2000, MjĂžlner Informatics
6 * Written by Erik Corry <corry@mjolner.dk>
8 * This source code is released for free distribution under the terms of the
9 * GNU General Public License.
11 * This module contains functions for generating tags for BETA language
12 * files.
16 * INCLUDE FILES
18 #include "general.h" /* must always come first */
20 #include <string.h>
22 #include "entry.h"
23 #include "parse.h"
24 #include "read.h"
25 #include "routines.h"
26 #include "vstring.h"
29 * MACROS
31 #define isbident(c) (identarray [(unsigned char) (c)])
34 * DATA DEFINITIONS
36 typedef enum {
37 K_FRAGMENT, K_PATTERN, K_SLOT, K_VIRTUAL
38 } betaKind;
40 static kindOption BetaKinds [] = {
41 { TRUE, 'f', "fragment", "fragment definitions"},
42 { FALSE, 'p', "pattern", "all patterns"},
43 { TRUE, 's', "slot", "slots (fragment uses)"},
44 { TRUE, 'v', "virtual", "patterns (virtual or rebound)"}
47 /* [A-Z_a-z0-9] */
48 static const char identarray [256] = {
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-15 */
50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-31 */
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32-47 !"#$%&'()*+'-./ */
52 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 48-63 0123456789:;<=>? */
53 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-79 @ABCDEFGHIJKLMNO */
54 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 80-95 PQRSTUVWXYZ [\]^_ */
55 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96-111 `abcdefghijklmno */
56 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 112-127 pqrstuvwxyz{|}~ */
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128- */
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* -255 */
67 * FUNCTION DEFINITIONS
70 static void makeBetaTag (const char* const name, const betaKind kind)
72 if (BetaKinds [kind].enabled)
74 tagEntryInfo e;
75 initTagEntry (&e, name);
76 e.kindName = BetaKinds [kind].name;
77 e.kind = BetaKinds [kind].letter;
78 makeTagEntry (&e);
82 static void findBetaTags (void)
84 vString *line = vStringNew ();
85 boolean incomment = FALSE;
86 boolean inquote = FALSE;
87 boolean dovirtuals = BetaKinds [K_VIRTUAL].enabled;
88 boolean dopatterns = BetaKinds [K_PATTERN].enabled;
92 boolean foundfragmenthere = FALSE;
93 /* find fragment definition (line that starts and ends with --) */
94 int last;
95 int first;
96 int c;
98 vStringClear (line);
100 while ((c = fileGetc ()) != EOF && c != '\n' && c != '\r')
101 vStringPut (line, c);
103 vStringTerminate (line);
105 last = vStringLength (line) - 1;
106 first = 0;
107 /* skip white space at start and end of line */
108 while (last && isspace ((int) vStringChar (line, last))) last--;
109 while (first < last && isspace ((int) vStringChar (line, first))) first++;
110 /* if line still has a reasonable length and ... */
111 if (last - first > 4 &&
112 (vStringChar (line, first) == '-' &&
113 vStringChar (line, first + 1) == '-' &&
114 vStringChar (line, last) == '-' &&
115 vStringChar (line, last - 1) == '-'))
117 if (!incomment && !inquote)
119 foundfragmenthere = TRUE;
120 /* skip past -- and whitespace. Also skip back past 'dopart'
121 or 'attributes' to the :. We have to do this because there
122 is no sensible way to include whitespace in a ctags token
123 so the conventional space after the ':' would mess us up */
124 last -= 2;
125 first += 2;
126 while (last && vStringChar (line, last) != ':') last--;
127 while (last && (isspace ((int) vStringChar (line, last-1)))) last--;
128 while (first < last &&
129 (isspace ((int) vStringChar (line, first)) ||
130 vStringChar (line, first) == '-'))
131 first++;
132 /* If there's anything left it is a fragment title */
133 if (first < last - 1)
135 vStringChar (line, last) = 0;
136 if (strcasecmp ("LIB", vStringValue (line) + first) &&
137 strcasecmp ("PROGRAM", vStringValue (line) + first))
139 makeBetaTag (vStringValue (line) + first, K_FRAGMENT);
143 } else {
144 int pos = 0;
145 int len = vStringLength (line);
146 if (inquote) goto stringtext;
147 if (incomment) goto commenttext;
148 programtext:
149 for ( ; pos < len; pos++)
151 if (vStringChar (line, pos) == '\'')
153 pos++;
154 inquote = TRUE;
155 goto stringtext;
157 if (vStringChar (line, pos) == '{')
159 pos++;
160 incomment = TRUE;
161 goto commenttext;
163 if (vStringChar (line, pos) == '(' && pos < len - 1 &&
164 vStringChar (line, pos+1) == '*')
166 pos +=2;
167 incomment = TRUE;
168 goto commenttext;
171 * SLOT definition looks like this:
172 * <<SLOT nameofslot: dopart>>
173 * or
174 * <<SLOT nameofslot: descriptor>>
176 if (!foundfragmenthere &&
177 vStringChar (line, pos) == '<' &&
178 pos+1 < len &&
179 vStringChar (line, pos+1) == '<' &&
180 strstr (vStringValue (line) + pos, ">>"))
182 /* Found slot name, get start and end */
183 int eoname;
184 char c2;
185 pos += 2; /* skip past << */
186 /* skip past space before SLOT */
187 while (pos < len && isspace ((int) vStringChar (line, pos)))
188 pos++;
189 /* skip past SLOT */
190 if (pos+4 <= len &&
191 !strncasecmp (vStringValue(line) + pos, "SLOT", (size_t)4))
192 pos += 4;
193 /* skip past space after SLOT */
194 while (pos < len && isspace ((int) vStringChar (line, pos)))
195 pos++;
196 eoname = pos;
197 /* skip to end of name */
198 while (eoname < len &&
199 (c2 = vStringChar (line, eoname)) != '>' &&
200 c2 != ':' &&
201 !isspace ((int) c2))
202 eoname++;
203 if (eoname < len)
205 vStringChar (line, eoname) = 0;
206 if (strcasecmp ("LIB", vStringValue (line) + pos) &&
207 strcasecmp ("PROGRAM", vStringValue (line) + pos) &&
208 strcasecmp ("SLOT", vStringValue (line) + pos))
210 makeBetaTag (vStringValue (line) + pos, K_SLOT);
213 if (eoname+1 < len) {
214 pos = eoname + 1;
215 } else {
216 pos = len;
217 continue;
220 /* Only patterns that are virtual, extensions of virtuals or
221 * final bindings are normally included so as not to overload
222 * totally.
223 * That means one of the forms name:: name:< or name::<
225 if (!foundfragmenthere &&
226 vStringChar (line, pos) == ':' &&
227 (dopatterns ||
228 (dovirtuals &&
229 (vStringChar (line, pos+1) == ':' ||
230 vStringChar (line, pos+1) == '<')
235 /* Found pattern name, get start and end */
236 int eoname = pos;
237 int soname;
238 while (eoname && isspace ((int) vStringChar (line, eoname-1)))
239 eoname--;
240 foundanothername:
241 /* terminate right after name */
242 vStringChar (line, eoname) = 0;
243 soname = eoname;
244 while (soname &&
245 isbident (vStringChar (line, soname-1)))
247 soname--;
249 if (soname != eoname)
251 makeBetaTag (vStringValue (line) + soname, K_PATTERN);
252 /* scan back past white space */
253 while (soname &&
254 isspace ((int) vStringChar (line, soname-1)))
255 soname--;
256 if (soname && vStringChar (line, soname-1) == ',')
258 /* we found a new pattern name before comma */
259 eoname = soname;
260 goto foundanothername;
265 goto endofline;
266 commenttext:
267 for ( ; pos < len; pos++)
269 if (vStringChar (line, pos) == '*' && pos < len - 1 &&
270 vStringChar (line, pos+1) == ')')
272 pos += 2;
273 incomment = FALSE;
274 goto programtext;
276 if (vStringChar (line, pos) == '}')
278 pos++;
279 incomment = FALSE;
280 goto programtext;
283 goto endofline;
284 stringtext:
285 for ( ; pos < len; pos++)
287 if (vStringChar (line, pos) == '\\')
289 if (pos < len - 1) pos++;
291 else if (vStringChar (line, pos) == '\'')
293 pos++;
294 /* support obsolete '' syntax */
295 if (pos < len && vStringChar (line, pos) == '\'')
297 continue;
299 inquote = FALSE;
300 goto programtext;
304 endofline:
305 inquote = FALSE; /* This shouldn't really make a difference */
306 } while (!feof (File.fp));
307 vStringDelete (line);
310 extern parserDefinition* BetaParser (void)
312 static const char *const extensions [] = { "bet", NULL };
313 parserDefinition* def = parserNew ("BETA");
314 def->kinds = BetaKinds;
315 def->kindCount = KIND_COUNT (BetaKinds);
316 def->extensions = extensions;
317 def->parser = findBetaTags;
318 return def;
321 /* vi:set tabstop=4 shiftwidth=4: */