2 * Copyright (c) 2000-2005, Darren Hiebert
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.
7 * This module contains functions for generating tags for makefiles.
13 #include "general.h" /* must always come first */
34 static kindDefinition MakeKinds
[] = {
35 { true, 'm', "macro", "macros"},
36 { true, 't', "target", "targets"}
40 * FUNCTION DEFINITIONS
43 static int nextChar (void)
45 int c
= getcFromInputFile ();
48 c
= getcFromInputFile ();
55 static void skipLine (void)
60 while (c
!= EOF
&& c
!= '\n');
62 ungetcToInputFile (c
);
65 static int skipToNonWhite (int c
)
67 while (c
!= '\n' && isspace (c
))
72 static bool isIdentifier (int c
)
74 return (bool)(c
!= '\0' && (isalnum (c
) || strchr (".-_/$(){}%", c
) != NULL
));
77 static bool isSpecialTarget (vString
*const name
)
80 /* All special targets begin with '.'. */
81 if (vStringLength (name
) < 1 || vStringChar (name
, i
++) != '.') {
84 while (i
< vStringLength (name
)) {
85 char ch
= vStringChar (name
, i
++);
86 if (ch
!= '_' && !isupper (ch
))
94 static void newTarget (vString
*const name
)
96 /* Ignore GNU Make's "special targets". */
97 if (isSpecialTarget (name
))
101 makeSimpleTag (name
, K_TARGET
);
104 static void newMacro (vString
*const name
)
106 makeSimpleTag (name
, K_MACRO
);
109 static void readIdentifier (const int first
, vString
*const id
)
114 while (isIdentifier (c
) || (depth
> 0 && c
!= EOF
&& c
!= '\n'))
116 if (c
== '(' || c
== '{')
118 else if (depth
> 0 && (c
== ')' || c
== '}'))
123 ungetcToInputFile (c
);
126 static void findMakeTags (void)
128 stringList
*identifiers
= stringListNew ();
130 bool in_define
= false;
131 bool in_rule
= false;
132 bool variable_possible
= true;
135 while ((c
= nextChar ()) != EOF
)
141 if (c
== '\t' || (c
= skipToNonWhite (c
)) == '#')
143 skipLine (); /* skip rule or comment */
149 stringListClear (identifiers
);
150 variable_possible
= (bool)(!in_rule
);
155 else if (isspace (c
))
159 else if (variable_possible
&& c
== '?')
162 ungetcToInputFile (c
);
163 variable_possible
= (c
== '=');
165 else if (variable_possible
&& c
== ':' &&
166 stringListCount (identifiers
) > 0)
169 ungetcToInputFile (c
);
173 for (i
= 0; i
< stringListCount (identifiers
); i
++)
174 newTarget (stringListItem (identifiers
, i
));
175 stringListClear (identifiers
);
179 else if (variable_possible
&& c
== '=' &&
180 stringListCount (identifiers
) == 1)
182 newMacro (stringListItem (identifiers
, 0));
186 else if (variable_possible
&& isIdentifier (c
))
188 vString
*name
= vStringNew ();
189 readIdentifier (c
, name
);
190 stringListAdd (identifiers
, name
);
192 if (stringListCount (identifiers
) == 1)
194 if (in_define
&& ! strcmp (vStringValue (name
), "endef"))
198 else if (! strcmp (vStringValue (name
), "define"))
201 c
= skipToNonWhite (nextChar ());
203 /* all remaining characters on the line are the name -- even spaces */
204 while (c
!= EOF
&& c
!= '\n')
206 vStringPut (name
, c
);
210 ungetcToInputFile (c
);
211 vStringStripTrailing (name
);
214 else if (! strcmp (vStringValue (name
), "export"))
215 stringListClear (identifiers
);
219 variable_possible
= false;
221 stringListDelete (identifiers
);
224 extern parserDefinition
* MakefileParser (void)
226 static const char *const patterns
[] = { "[Mm]akefile", "GNUmakefile", NULL
};
227 static const char *const extensions
[] = { "mak", "mk", NULL
};
228 parserDefinition
* const def
= parserNew ("Make");
229 def
->kindTable
= MakeKinds
;
230 def
->kindCount
= ARRAY_SIZE (MakeKinds
);
231 def
->patterns
= patterns
;
232 def
->extensions
= extensions
;
233 def
->parser
= findMakeTags
;