xref: /Universal-ctags/parsers/autoconf.c (revision 6b1a862e526d5017f9f212a321f59d67c859d521)
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