Rename tagEntryInfo.extensionFields.scope
[geany-mirror.git] / ctags / parsers / rest.c
blob51617c28b93166fcab2bce95e385b1d68dfd7d3e
1 /*
3 * Copyright (c) 2007-2011, Nick Treleaven
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License.
8 * This module contains functions for generating tags for reStructuredText (reST) files.
9 */
12 * INCLUDE FILES
14 #include "general.h" /* must always come first */
16 #include <ctype.h>
17 #include <string.h>
19 #include "parse.h"
20 #include "read.h"
21 #include "vstring.h"
22 #include "nestlevel.h"
23 #include "routines.h"
26 * DATA DEFINITIONS
28 typedef enum {
29 K_CHAPTER = 0,
30 K_SECTION,
31 K_SUBSECTION,
32 K_SUBSUBSECTION,
33 SECTION_COUNT
34 } restKind;
36 static kindOption RestKinds[] = {
37 { TRUE, 'n', "namespace", "chapters"},
38 { TRUE, 'm', "member", "sections" },
39 { TRUE, 'd', "macro", "subsections" },
40 { TRUE, 'v', "variable", "subsubsections" }
43 static char kindchars[SECTION_COUNT];
45 static NestingLevels *nestingLevels = NULL;
48 * FUNCTION DEFINITIONS
51 static NestingLevel *getNestingLevel(const int kind)
53 NestingLevel *nl;
55 while (1)
57 nl = nestingLevelsGetCurrent(nestingLevels);
58 if (nl && nl->type >= kind)
59 nestingLevelsPop(nestingLevels);
60 else
61 break;
63 return nl;
66 static void makeRestTag (const vString* const name, const int kind)
68 const NestingLevel *const nl = getNestingLevel(kind);
70 if (vStringLength (name) > 0)
72 tagEntryInfo e;
73 initTagEntry (&e, vStringValue (name));
75 e.lineNumber--; /* we want the line before the '---' underline chars */
76 e.kindName = RestKinds [kind].name;
77 e.kind = RestKinds [kind].letter;
79 if (nl && nl->type < kind)
81 e.extensionFields.scopeKind = &(RestKinds [nl->type]);
82 e.extensionFields.scopeName = vStringValue (nl->name);
84 makeTagEntry (&e);
86 nestingLevelsPush(nestingLevels, name, kind);
90 /* checks if str is all the same character */
91 static boolean issame(const char *str)
93 char first = *str;
95 while (*str)
97 char c;
99 str++;
100 c = *str;
101 if (c && c != first)
102 return FALSE;
104 return TRUE;
108 static int get_kind(char c)
110 int i;
112 for (i = 0; i < SECTION_COUNT; i++)
114 if (kindchars[i] == c)
115 return i;
117 if (kindchars[i] == 0)
119 kindchars[i] = c;
120 return i;
123 return -1;
127 /* computes the length of an UTF-8 string
128 * if the string doesn't look like UTF-8, return -1 */
129 static int utf8_strlen(const char *buf, int buf_len)
131 int len = 0;
132 const char *end = buf + buf_len;
134 for (len = 0; buf < end; len ++)
136 /* perform quick and naive validation (no sub-byte checking) */
137 if (! (*buf & 0x80))
138 buf ++;
139 else if ((*buf & 0xe0) == 0xc0)
140 buf += 2;
141 else if ((*buf & 0xf0) == 0xe0)
142 buf += 3;
143 else if ((*buf & 0xf8) == 0xf0)
144 buf += 4;
145 else /* not a valid leading UTF-8 byte, abort */
146 return -1;
148 if (buf > end) /* incomplete last byte */
149 return -1;
152 return len;
156 /* TODO: parse overlining & underlining as distinct sections. */
157 static void findRestTags (void)
159 vString *name = vStringNew ();
160 const unsigned char *line;
162 memset(kindchars, 0, sizeof kindchars);
163 nestingLevels = nestingLevelsNew();
165 while ((line = readLineFromInputFile ()) != NULL)
167 int line_len = strlen((const char*) line);
168 int name_len_bytes = vStringLength(name);
169 int name_len = utf8_strlen(vStringValue(name), name_len_bytes);
171 /* if the name doesn't look like UTF-8, assume one-byte charset */
172 if (name_len < 0)
173 name_len = name_len_bytes;
175 /* underlines must be the same length or more */
176 if (line_len >= name_len && name_len > 0 &&
177 ispunct(line[0]) && issame((const char*) line))
179 char c = line[0];
180 int kind = get_kind(c);
182 if (kind >= 0)
184 makeRestTag(name, kind);
185 continue;
188 vStringClear (name);
189 if (! isspace(*line))
190 vStringCatS(name, (const char*) line);
191 vStringTerminate(name);
193 vStringDelete (name);
194 nestingLevelsFree(nestingLevels);
197 extern parserDefinition* RestParser (void)
199 static const char *const patterns [] = { "*.rest", "*.reST", NULL };
200 static const char *const extensions [] = { "rest", NULL };
201 parserDefinition* const def = parserNew ("reStructuredText");
203 def->kinds = RestKinds;
204 def->kindCount = ARRAY_SIZE (RestKinds);
205 def->patterns = patterns;
206 def->extensions = extensions;
207 def->parser = findRestTags;
208 return def;
211 /* vi:set tabstop=4 shiftwidth=4: */