1dc3daa67SMasatake YAMATO /*
2dc3daa67SMasatake YAMATO *
3dc3daa67SMasatake YAMATO * Copyright (c) 2000-2001, Darren Hiebert
4dc3daa67SMasatake YAMATO *
5dc3daa67SMasatake YAMATO * This source code is released for free distribution under the terms of the
6dc3daa67SMasatake YAMATO * GNU General Public License version 2 or (at your option) any later version.
7dc3daa67SMasatake YAMATO *
8dc3daa67SMasatake YAMATO * This module contains functions for generating tags for ini/config files.
9dc3daa67SMasatake YAMATO */
10dc3daa67SMasatake YAMATO
11dc3daa67SMasatake YAMATO /*
12dc3daa67SMasatake YAMATO * This is based on geany's conf.c:
13dc3daa67SMasatake YAMATO * --------------------------------
14dc3daa67SMasatake YAMATO * commit 3af538fa65f8b17897259080db8144b1edc43470
15dc3daa67SMasatake YAMATO * Author: Enrico Tröger <enrico.troeger@uvena.de>
16dc3daa67SMasatake YAMATO * Date: Sun Nov 27 20:39:57 2005 +0000
17dc3daa67SMasatake YAMATO *
18dc3daa67SMasatake YAMATO * added tag support for filetype Conf
19dc3daa67SMasatake YAMATO *
20dc3daa67SMasatake YAMATO *
21dc3daa67SMasatake YAMATO * git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@15 ea778897-0a13-0410-b9d1-a72fbfd435f5
22dc3daa67SMasatake YAMATO *
23dc3daa67SMasatake YAMATO */
24dc3daa67SMasatake YAMATO
25dc3daa67SMasatake YAMATO #include "general.h" /* must always come first */
26dc3daa67SMasatake YAMATO
2714781660SMasatake YAMATO #include "entry.h"
28dc3daa67SMasatake YAMATO #include "htable.h"
2987214e15SMasatake YAMATO #include "iniconf.h"
30dc3daa67SMasatake YAMATO #include "parse.h"
31dc3daa67SMasatake YAMATO #include "read.h"
32ed9b023fSMasatake YAMATO #include "subparser.h"
33dc3daa67SMasatake YAMATO #include "vstring.h"
34dc3daa67SMasatake YAMATO
isIdentifier(int c)35ce990805SThomas Braun static bool isIdentifier (int c)
36dc3daa67SMasatake YAMATO {
37dc3daa67SMasatake YAMATO /* allow whitespace within keys and sections */
38ce990805SThomas Braun return (bool)(isalnum (c) || isspace (c) || c == '_');
39dc3daa67SMasatake YAMATO }
40dc3daa67SMasatake YAMATO
isValue(int c)41ce990805SThomas Braun static bool isValue (int c)
42dc3daa67SMasatake YAMATO {
43dc3daa67SMasatake YAMATO return (c != '\0');
44dc3daa67SMasatake YAMATO }
45dc3daa67SMasatake YAMATO
maySwitchLanguage(const char * section,const char * key,const char * value)46ed9b023fSMasatake YAMATO static iniconfSubparser *maySwitchLanguage (const char *section, const char *key, const char *value)
47dc3daa67SMasatake YAMATO {
48ed9b023fSMasatake YAMATO iniconfSubparser *iniconf_subparser = NULL;
49ed9b023fSMasatake YAMATO subparser *sub;
50ed9b023fSMasatake YAMATO
5111358a9dSMasatake YAMATO foreachSubparser (sub, false)
52ed9b023fSMasatake YAMATO {
53ed9b023fSMasatake YAMATO iniconfSubparser *s = (iniconfSubparser *)sub;
54ed9b023fSMasatake YAMATO if ((sub->direction & SUBPARSER_BASE_RUNS_SUB)
55ed9b023fSMasatake YAMATO && s->probeLanguage)
56ed9b023fSMasatake YAMATO {
57ed9b023fSMasatake YAMATO bool r;
58ed9b023fSMasatake YAMATO
593abcac5dSMasatake YAMATO enterSubparser ((subparser *)s);
60ed9b023fSMasatake YAMATO r = s->probeLanguage(section, key, value);
61ed9b023fSMasatake YAMATO leaveSubparser ();
62ed9b023fSMasatake YAMATO if (r)
63ed9b023fSMasatake YAMATO {
64ed9b023fSMasatake YAMATO iniconf_subparser = s;
65ed9b023fSMasatake YAMATO chooseExclusiveSubparser (sub, NULL);
66ed9b023fSMasatake YAMATO break;
67ed9b023fSMasatake YAMATO }
68ed9b023fSMasatake YAMATO }
69dc3daa67SMasatake YAMATO }
70dc3daa67SMasatake YAMATO
71ed9b023fSMasatake YAMATO return iniconf_subparser;
72ed9b023fSMasatake YAMATO }
73dc3daa67SMasatake YAMATO
74ed9b023fSMasatake YAMATO typedef enum {
75ed9b023fSMasatake YAMATO K_SECTION,
76ed9b023fSMasatake YAMATO K_KEY,
77ed9b023fSMasatake YAMATO } makeKind;
78dc3daa67SMasatake YAMATO
79e112e8abSMasatake YAMATO static kindDefinition IniconfKinds [] = {
80ed9b023fSMasatake YAMATO { true, 's', "section", "sections"},
81ed9b023fSMasatake YAMATO { true, 'k', "key", "keys"},
82dc3daa67SMasatake YAMATO };
83dc3daa67SMasatake YAMATO
makeIniconfTagMaybe(const char * section,const char * key,const char * value CTAGS_ATTR_UNUSED,int * index)84e4d16241SMasatake YAMATO static void makeIniconfTagMaybe (const char *section, const char *key, const char *value CTAGS_ATTR_UNUSED, int *index)
85dc3daa67SMasatake YAMATO {
86ed9b023fSMasatake YAMATO tagEntryInfo e;
87dc3daa67SMasatake YAMATO
88ed9b023fSMasatake YAMATO if (!isLanguageEnabled (getInputLanguage ()))
89dc3daa67SMasatake YAMATO return;
90dc3daa67SMasatake YAMATO
91ed9b023fSMasatake YAMATO if (key)
92ed9b023fSMasatake YAMATO {
9316a2541cSMasatake YAMATO initTagEntry (&e, key, K_KEY);
94ed9b023fSMasatake YAMATO e.extensionFields.scopeIndex = *index;
95ed9b023fSMasatake YAMATO makeTagEntry (&e);
96ed9b023fSMasatake YAMATO }
97ed9b023fSMasatake YAMATO else
98ed9b023fSMasatake YAMATO {
99*3671ad72SMasatake YAMATO tagEntryInfo *last = getEntryInCorkQueue (*index);
100ed9b023fSMasatake YAMATO if (last)
101ed9b023fSMasatake YAMATO last->extensionFields.endLine = getInputLineNumber ();
102dc3daa67SMasatake YAMATO
10316a2541cSMasatake YAMATO initTagEntry (&e, section, K_SECTION);
104ed9b023fSMasatake YAMATO *index = makeTagEntry (&e);
105dc3daa67SMasatake YAMATO }
106dc3daa67SMasatake YAMATO }
107dc3daa67SMasatake YAMATO
findIniconfTags(void)108ed9b023fSMasatake YAMATO static void findIniconfTags (void)
109dc3daa67SMasatake YAMATO {
110ed9b023fSMasatake YAMATO const unsigned char *line;
111dc3daa67SMasatake YAMATO vString *val = vStringNew ();
112dc3daa67SMasatake YAMATO vString *name = vStringNew ();
113dc3daa67SMasatake YAMATO vString *scope = vStringNew ();
114ed9b023fSMasatake YAMATO iniconfSubparser *sub;
115ed9b023fSMasatake YAMATO int sectionCorkIndex = CORK_NIL;
116dc3daa67SMasatake YAMATO
117dc3daa67SMasatake YAMATO
118ed9b023fSMasatake YAMATO sub = (iniconfSubparser *)getSubparserRunningBaseparser();
119ed9b023fSMasatake YAMATO if (sub)
120ed9b023fSMasatake YAMATO chooseExclusiveSubparser ((subparser *)sub, NULL);
121dc3daa67SMasatake YAMATO
122dc3daa67SMasatake YAMATO while ((line = readLineFromInputFile ()) != NULL)
123dc3daa67SMasatake YAMATO {
124dc3daa67SMasatake YAMATO const unsigned char* cp = line;
125ce990805SThomas Braun bool possible = true;
126dc3daa67SMasatake YAMATO
127c1faa6e5SMasatake YAMATO if (isspace ((int) *cp) || *cp == '#' || *cp == ';' || *cp == '\0'
128c1faa6e5SMasatake YAMATO || (*cp == '/' && *(cp+1) == '/'))
129dc3daa67SMasatake YAMATO continue;
130dc3daa67SMasatake YAMATO
131dc3daa67SMasatake YAMATO /* look for a section */
132c1faa6e5SMasatake YAMATO if (*cp == '[')
133dc3daa67SMasatake YAMATO {
134dc3daa67SMasatake YAMATO ++cp;
135dc3daa67SMasatake YAMATO while (*cp != '\0' && *cp != ']')
136dc3daa67SMasatake YAMATO {
137dc3daa67SMasatake YAMATO vStringPut (name, (int) *cp);
138dc3daa67SMasatake YAMATO ++cp;
139dc3daa67SMasatake YAMATO }
140dc3daa67SMasatake YAMATO
141ed9b023fSMasatake YAMATO makeIniconfTagMaybe (vStringValue (name), NULL, NULL,
142dc3daa67SMasatake YAMATO §ionCorkIndex);
143dc3daa67SMasatake YAMATO
144ed9b023fSMasatake YAMATO
145ed9b023fSMasatake YAMATO if (!sub)
146ed9b023fSMasatake YAMATO sub = maySwitchLanguage (vStringValue (name), NULL, NULL);
147ed9b023fSMasatake YAMATO
148ed9b023fSMasatake YAMATO if (sub)
149dc3daa67SMasatake YAMATO {
1503abcac5dSMasatake YAMATO enterSubparser((subparser *)sub);
151ed9b023fSMasatake YAMATO sub->newDataNotify (sub, vStringValue (name), NULL, NULL);
152ed9b023fSMasatake YAMATO leaveSubparser ();
153dc3daa67SMasatake YAMATO }
154dc3daa67SMasatake YAMATO
155dc3daa67SMasatake YAMATO vStringCopy (scope, name);
156dc3daa67SMasatake YAMATO vStringClear (name);
157dc3daa67SMasatake YAMATO continue;
158dc3daa67SMasatake YAMATO }
159dc3daa67SMasatake YAMATO
160dc3daa67SMasatake YAMATO while (*cp != '\0')
161dc3daa67SMasatake YAMATO {
162dc3daa67SMasatake YAMATO /* We look for any sequence of identifier characters following a white space */
163dc3daa67SMasatake YAMATO if (possible && isIdentifier ((int) *cp))
164dc3daa67SMasatake YAMATO {
165dc3daa67SMasatake YAMATO while (isIdentifier ((int) *cp))
166dc3daa67SMasatake YAMATO {
167dc3daa67SMasatake YAMATO vStringPut (name, (int) *cp);
168dc3daa67SMasatake YAMATO ++cp;
169dc3daa67SMasatake YAMATO }
170dc3daa67SMasatake YAMATO vStringStripTrailing (name);
171dc3daa67SMasatake YAMATO while (isspace ((int) *cp))
172dc3daa67SMasatake YAMATO ++cp;
173dc3daa67SMasatake YAMATO if (*cp == '=' || *cp == ':')
174dc3daa67SMasatake YAMATO {
175dc3daa67SMasatake YAMATO
176dc3daa67SMasatake YAMATO cp++;
177dc3daa67SMasatake YAMATO while (isspace ((int) *cp))
178dc3daa67SMasatake YAMATO ++cp;
179dc3daa67SMasatake YAMATO while (isValue ((int) *cp))
180dc3daa67SMasatake YAMATO {
181dc3daa67SMasatake YAMATO vStringPut (val, (int) *cp);
182dc3daa67SMasatake YAMATO ++cp;
183dc3daa67SMasatake YAMATO }
184dc3daa67SMasatake YAMATO vStringStripTrailing (val);
185dc3daa67SMasatake YAMATO
186ed9b023fSMasatake YAMATO makeIniconfTagMaybe ((vStringLength (scope) > 0)
187dc3daa67SMasatake YAMATO ? vStringValue (scope)
188dc3daa67SMasatake YAMATO : NULL,
189dc3daa67SMasatake YAMATO vStringValue (name),
190dc3daa67SMasatake YAMATO vStringValue (val),
191dc3daa67SMasatake YAMATO §ionCorkIndex);
192ed9b023fSMasatake YAMATO if (!sub)
193ed9b023fSMasatake YAMATO sub = maySwitchLanguage ((vStringLength (scope) > 0)
194dc3daa67SMasatake YAMATO ? vStringValue (scope)
195dc3daa67SMasatake YAMATO : NULL,
196dc3daa67SMasatake YAMATO vStringValue (name),
197dc3daa67SMasatake YAMATO vStringValue (val));
198ed9b023fSMasatake YAMATO if (sub)
199dc3daa67SMasatake YAMATO {
2003abcac5dSMasatake YAMATO enterSubparser ((subparser *)sub);
201ed9b023fSMasatake YAMATO sub->newDataNotify (sub,
202ed9b023fSMasatake YAMATO (vStringLength (scope) > 0)
203dc3daa67SMasatake YAMATO ? vStringValue (scope)
204dc3daa67SMasatake YAMATO : NULL,
205dc3daa67SMasatake YAMATO vStringValue (name),
206ed9b023fSMasatake YAMATO vStringValue (val));
207ed9b023fSMasatake YAMATO leaveSubparser ();
208ed9b023fSMasatake YAMATO }
209dc3daa67SMasatake YAMATO vStringClear (val);
210dc3daa67SMasatake YAMATO }
211dc3daa67SMasatake YAMATO vStringClear (name);
212dc3daa67SMasatake YAMATO }
213dc3daa67SMasatake YAMATO else
214dc3daa67SMasatake YAMATO possible = !!(isspace ((int) *cp));
215dc3daa67SMasatake YAMATO
216dc3daa67SMasatake YAMATO if (*cp != '\0')
217dc3daa67SMasatake YAMATO ++cp;
218dc3daa67SMasatake YAMATO }
219dc3daa67SMasatake YAMATO }
220dc3daa67SMasatake YAMATO
221dc3daa67SMasatake YAMATO vStringDelete (name);
222dc3daa67SMasatake YAMATO vStringDelete (scope);
223dc3daa67SMasatake YAMATO vStringDelete (val);
224dc3daa67SMasatake YAMATO }
225dc3daa67SMasatake YAMATO
IniconfParser(void)226dc3daa67SMasatake YAMATO extern parserDefinition* IniconfParser (void)
227dc3daa67SMasatake YAMATO {
228dc3daa67SMasatake YAMATO static const char *const extensions [] = { "ini", "conf", NULL };
229dc3daa67SMasatake YAMATO parserDefinition* const def = parserNew ("Iniconf");
230dc3daa67SMasatake YAMATO
23109ae690fSMasatake YAMATO def->kindTable = IniconfKinds;
232dc3daa67SMasatake YAMATO def->kindCount = ARRAY_SIZE (IniconfKinds);
233dc3daa67SMasatake YAMATO def->extensions = extensions;
234dc3daa67SMasatake YAMATO def->parser = findIniconfTags;
2356b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
236dc3daa67SMasatake YAMATO
237dc3daa67SMasatake YAMATO return def;
238dc3daa67SMasatake YAMATO }
239