Merge pull request #482 from philippwiesemann/fix-typos-po-de
[geany-mirror.git] / tagmanager / ctags / txt2tags.c
blobf3092ab05d166ff59a6a997d501c395e38034901
1 /*
2 * Copyright (c) 2009, Eric Forgeot
3 * Copyright (c) 2014, Colomban Wendling <colomban@geany.org>
5 * Based on work by Jon Strait
7 * This source code is released for free distribution under the terms of the
8 * GNU General Public License.
10 * This module contains functions for generating tags for Txt2tags files.
14 * INCLUDE FILES
16 #include "general.h" /* must always come first */
18 #include <ctype.h>
19 #include <string.h>
21 #include "parse.h"
22 #include "read.h"
23 #include "nestlevel.h"
24 #include "vstring.h"
27 /* as any character may happen in an input, use something highly unlikely */
28 #define SCOPE_SEPARATOR '\x3' /* ASCII ETX */
31 * DATA DEFINITIONS
34 typedef enum {
35 K_SECTION = 0
36 } Txt2tagsKind;
38 static kindOption Txt2tagsKinds[] = {
39 { TRUE, 'm', "member", "sections" }
43 * FUNCTION DEFINITIONS
46 static void makeTxt2tagsTag (const vString* const name,
47 const NestingLevels *const nls,
48 Txt2tagsKind type)
50 tagEntryInfo e;
51 vString *scope = NULL;
52 kindOption *kind = &Txt2tagsKinds[type];
53 initTagEntry (&e, vStringValue(name));
55 e.kindName = kind->name;
56 e.kind = kind->letter;
58 if (nls->n > 0) {
59 int i;
60 kindOption *parentKind;
62 scope = vStringNew();
63 for (i = 0; i < nls->n; i++) {
64 if (vStringLength(scope) > 0)
65 vStringPut(scope, SCOPE_SEPARATOR);
66 vStringCat(scope, nls->levels[i].name);
68 parentKind = &Txt2tagsKinds[nls->levels[nls->n - 1].type];
70 e.extensionFields.scope[0] = parentKind->name;
71 e.extensionFields.scope[1] = vStringValue(scope);
74 makeTagEntry(&e);
76 vStringDelete(scope);
79 /* matches: ^ *[=_-]{20,} *$ */
80 static boolean isTxt2tagsLine (const unsigned char *line)
82 unsigned int len;
84 while (isspace(*line)) line++;
85 for (len = 0; *line == '=' || *line == '-' || *line == '_'; len++)
86 line++;
87 while (isspace(*line)) line++;
89 return len >= 20 && *line == 0;
92 static boolean parseTxt2tagsTitle (const unsigned char *line,
93 vString *const title,
94 int *const depth_)
96 const int MAX_TITLE_DEPTH = 5; /* maximum length of a title delimiter */
97 unsigned char delim;
98 int delim_delta = 0;
99 const unsigned char *end;
101 /* skip leading spaces, but no tabs (probably because they create quotes) */
102 while (*line == ' ') line++;
104 /* normal/numbered titles */
105 if (*line != '=' && *line != '+')
106 return FALSE;
108 delim = *line;
110 /* find the start delimiter length */
111 while (*line == delim && delim_delta < MAX_TITLE_DEPTH+1)
113 line++;
114 delim_delta++;
116 while (isspace(*line))
117 line++;
119 if (delim_delta > MAX_TITLE_DEPTH) /* invalid */
120 return FALSE;
122 *depth_ = delim_delta;
124 /* find the end delimiter */
125 end = line + strlen((const char *) line) - 1;
126 while (end > line && isspace(*end)) end--;
127 /* skip a possible label: \[[A-Za-z0-9_-]+\] */
128 if (*end == ']')
130 end--;
131 while (end > line && (isalnum(*end) || *end == '_' || *end == '-'))
132 end--;
133 if (*end != '[') /* invalid */
134 return FALSE;
135 end--;
137 while (end > line && *end == delim && delim_delta >= 0)
139 delim_delta--;
140 end--;
142 while (end > line && isspace(*end)) end--;
143 end++;
145 /* if start and end delimiters are not identical, or the the name is empty */
146 if (delim_delta != 0 || (end - line) <= 0)
147 return FALSE;
149 vStringNCopyS(title, (const char *) line, end - line);
150 return TRUE;
153 static void findTxt2tagsTags (void)
155 NestingLevels *nls = nestingLevelsNew();
156 vString *name = vStringNew();
157 const unsigned char *line;
159 while ((line = fileReadLine()) != NULL)
161 int depth;
163 if (isTxt2tagsLine(line))
164 ; /* skip not to improperly match titles */
165 else if (parseTxt2tagsTitle(line, name, &depth))
167 NestingLevel *nl = nestingLevelsGetCurrent(nls);
168 while (nl && nl->indentation >= depth)
170 nestingLevelsPop(nls);
171 nl = nestingLevelsGetCurrent(nls);
174 vStringTerminate(name);
175 makeTxt2tagsTag(name, nls, K_SECTION);
176 nestingLevelsPush(nls, name, K_SECTION);
177 nestingLevelsGetCurrent(nls)->indentation = depth;
180 vStringDelete (name);
181 nestingLevelsFree(nls);
184 extern parserDefinition* Txt2tagsParser (void)
186 static const char *const patterns [] = { "*.t2t", NULL };
187 static const char *const extensions [] = { "t2t", NULL };
188 parserDefinition* const def = parserNew ("Txt2tags");
190 def->kinds = Txt2tagsKinds;
191 def->kindCount = KIND_COUNT (Txt2tagsKinds);
192 def->patterns = patterns;
193 def->extensions = extensions;
194 def->parser = findTxt2tagsTags;
195 return def;