1 /*
2 * Copyright (c) 2011, Colomban Wendling <colomban@geany.org>
3 *
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
6 *
7 * This module contains functions for generating tags for Autoconf files.
8 */
9
10 #include "general.h" /* must always come first */
11
12 #include <string.h>
13
14 #include "autoconf.h"
15 #include "m4.h"
16
17 #include "debug.h"
18 #include "entry.h"
19 #include "read.h"
20 #include "keyword.h"
21 #include "kind.h"
22 #include "parse.h"
23
24
25 static roleDefinition AutoconfOptwithRoles [] = {
26 { true, "cmdline", "specified in a configure command line" },
27 };
28
29 static roleDefinition AutoconfOptenableRoles [] = {
30 { true, "cmdline", "specified in a configure command line" },
31 };
32
33 static kindDefinition AutoconfKinds[] = {
34 { true, 'p', "package", "packages" },
35 { true, 't', "template", "templates" },
36 { true, 'm', "macro", "autoconf macros" },
37 { true, 'w', "optwith", "options specified with --with-...",
38 .referenceOnly = false, ATTACH_ROLES(AutoconfOptwithRoles)},
39 { true, 'e', "optenable", "options specified with --enable-...",
40 .referenceOnly = false, ATTACH_ROLES(AutoconfOptenableRoles)},
41 { true, 's', "subst", "substitution keys"},
42 { true, 'c', "condition", "automake conditions" },
43 { true, 'd', "definition", "definitions" },
44 };
45
46 typedef enum {
47 KEYWORD_init,
48 KEYWORD_template,
49 KEYWORD_defun,
50 KEYWORD_argwith,
51 KEYWORD_argenable,
52 KEYWORD_subst,
53 KEYWORD_conditional,
54 KEYWORD_define,
55 } autoconfKeywordId;
56
57 static const keywordTable autoconfKeywordTable[] = {
58 { "AC_INIT", KEYWORD_init, },
59 { "AH_TEMPLATE", KEYWORD_template, },
60 { "AC_DEFUN", KEYWORD_defun, },
61 { "AC_DEFUN_ONCE", KEYWORD_defun, },
62 { "AC_ARG_WITH", KEYWORD_argwith, },
63 { "AC_ARG_ENABLE", KEYWORD_argenable, },
64 { "AC_SUBST", KEYWORD_subst, },
65 { "AM_CONDITIONAL", KEYWORD_conditional, },
66 { "AC_DEFINE", KEYWORD_define, },
67 { "AC_DEFINE_UNQUOTED", KEYWORD_define, },
68 };
69
doesLineCommentStart(m4Subparser * m4 CTAGS_ATTR_UNUSED,int c,const char * token CTAGS_ATTR_UNUSED)70 static bool doesLineCommentStart (m4Subparser *m4 CTAGS_ATTR_UNUSED, int c, const char* token CTAGS_ATTR_UNUSED)
71 {
72 return (c == '#');
73 }
74
doesStringLiteralStart(m4Subparser * m4 CTAGS_ATTR_UNUSED,int c CTAGS_ATTR_UNUSED)75 static bool doesStringLiteralStart (m4Subparser *m4 CTAGS_ATTR_UNUSED, int c CTAGS_ATTR_UNUSED)
76 {
77 // return (c == '"') || (c == '\'') || (c == '`');
78 return false;
79 }
80
probeLanguage(m4Subparser * m4 CTAGS_ATTR_UNUSED,const char * token)81 static bool probeLanguage (m4Subparser *m4 CTAGS_ATTR_UNUSED, const char* token)
82 {
83 return strncmp (token, "m4_", 3) == 0
84 || strncmp (token, "AC_", 3) == 0
85 || strncmp (token, "AM_", 3) == 0
86 || strncmp (token, "AS_", 3) == 0
87 || strncmp (token, "AH_", 3) == 0
88 ;
89 }
90
makeAutoconfTag(int kind)91 static int makeAutoconfTag (int kind)
92 {
93 int index = CORK_NIL;
94 vString * name;
95
96 name = vStringNew();
97 readM4MacroArgument(name);
98 if (vStringLength (name) > 0)
99 {
100 tagEntryInfo e;
101 initTagEntry (&e, vStringValue(name), kind);
102 index = makeTagEntry(&e);
103 }
104 vStringDelete (name);
105
106 return index;
107 }
108
newMacroCallback(m4Subparser * m4 CTAGS_ATTR_UNUSED,const char * token)109 static int newMacroCallback (m4Subparser *m4 CTAGS_ATTR_UNUSED, const char* token)
110 {
111 int keyword;
112 int index = CORK_NIL;
113
114 keyword = lookupKeyword (token, getInputLanguage ());
115
116 /* TODO:
117 AH_VERBATIM
118 */
119 switch (keyword)
120 {
121 case KEYWORD_NONE:
122 break;
123 case KEYWORD_init:
124 index = makeAutoconfTag (AUTOCONF_PACKAGE_KIND);
125 break;
126 case KEYWORD_template:
127 index = makeAutoconfTag (AUTOCONF_TEMPLATE_KIND);
128 break;
129 case KEYWORD_defun:
130 index = makeAutoconfTag (AUTOCONF_MACRO_KIND);
131 break;
132 case KEYWORD_argwith:
133 index = makeAutoconfTag (AUTOCONF_OPTWITH_KIND);
134 break;
135 case KEYWORD_argenable:
136 index = makeAutoconfTag (AUTOCONF_OPTENABLE_KIND);
137 break;
138 case KEYWORD_subst:
139 index = makeAutoconfTag (AUTOCONF_SUBST_KIND);
140 break;
141 case KEYWORD_conditional:
142 index = makeAutoconfTag (AUTOCONF_CONDITION_KIND);
143 break;
144 case KEYWORD_define:
145 index = makeAutoconfTag (AUTOCONF_DEFINITION_KIND);
146 break;
147 default:
148 AssertNotReached ();
149 }
150 return index;
151 }
152
exclusiveSubparserChosenCallback(subparser * s CTAGS_ATTR_UNUSED,void * data CTAGS_ATTR_UNUSED)153 static void exclusiveSubparserChosenCallback (subparser *s CTAGS_ATTR_UNUSED, void *data CTAGS_ATTR_UNUSED)
154 {
155 setM4Quotes ('[', ']');
156 }
157
findAutoconfTags(void)158 static void findAutoconfTags(void)
159 {
160 scheduleRunningBaseparser (0);
161 }
162
AutoconfParser(void)163 extern parserDefinition* AutoconfParser (void)
164 {
165 static const char *const patterns [] = { "configure.in", NULL };
166 static const char *const extensions [] = { "ac", NULL };
167 parserDefinition* const def = parserNew("Autoconf");
168
169 static m4Subparser autoconfSubparser = {
170 .subparser = {
171 .direction = SUBPARSER_BI_DIRECTION,
172 .exclusiveSubparserChosenNotify = exclusiveSubparserChosenCallback,
173 },
174 .probeLanguage = probeLanguage,
175 .newMacroNotify = newMacroCallback,
176 .doesLineCommentStart = doesLineCommentStart,
177 .doesStringLiteralStart = doesStringLiteralStart,
178 };
179 static parserDependency dependencies [] = {
180 [0] = { DEPTYPE_SUBPARSER, "M4", &autoconfSubparser },
181 };
182
183 def->dependencies = dependencies;
184 def->dependencyCount = ARRAY_SIZE (dependencies);
185
186 def->kindTable = AutoconfKinds;
187 def->kindCount = ARRAY_SIZE(AutoconfKinds);
188 def->patterns = patterns;
189 def->extensions = extensions;
190 def->parser = findAutoconfTags;
191 def->useCork = CORK_QUEUE;
192
193 def->keywordTable = autoconfKeywordTable;
194 def->keywordCount = ARRAY_SIZE (autoconfKeywordTable);
195
196 return def;
197 }
198