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.
7 * This module contains functions for generating tags for makefiles.
13 #include "general.h" /* must always come first */
31 static kindOption MakeKinds
[] = {
32 { TRUE
, 'm', "macro", "macros"},
33 { TRUE
, 't', "function", "targets"}
37 * FUNCTION DEFINITIONS
40 static int nextChar (void)
52 static void skipLine (void)
57 while (c
!= EOF
&& c
!= '\n');
62 static int skipToNonWhite (int c
)
64 while (c
!= '\n' && isspace (c
))
69 static boolean
isIdentifier (int c
)
71 return (boolean
)(c
!= '\0' && (isalnum (c
) || strchr (".-_/$(){}%", c
) != NULL
));
74 static boolean
isSpecialTarget (vString
*const name
)
77 /* All special targets begin with '.'. */
78 if (vStringLength (name
) < 1 || vStringChar (name
, i
++) != '.') {
81 while (i
< vStringLength (name
)) {
82 char ch
= vStringChar (name
, i
++);
83 if (ch
!= '_' && !isupper (ch
))
91 static void newTarget (vString
*const name
)
93 /* Ignore GNU Make's "special targets". */
94 if (isSpecialTarget (name
))
98 makeSimpleTag (name
, MakeKinds
, K_TARGET
);
101 static void newMacro (vString
*const name
)
103 makeSimpleTag (name
, MakeKinds
, K_MACRO
);
106 static void readIdentifier (const int first
, vString
*const id
)
111 while (isIdentifier (c
) || (depth
> 0 && c
!= EOF
&& c
!= '\n'))
113 if (c
== '(' || c
== '{')
115 else if (depth
> 0 && (c
== ')' || c
== '}'))
121 vStringTerminate (id
);
124 static void findMakeTags (void)
126 stringList
*identifiers
= stringListNew ();
127 boolean newline
= TRUE
;
128 boolean in_define
= FALSE
;
129 boolean in_rule
= FALSE
;
130 boolean variable_possible
= TRUE
;
133 while ((c
= nextChar ()) != EOF
)
139 if (c
== '\t' || (c
= skipToNonWhite (c
)) == '#')
141 skipLine (); /* skip rule or comment */
147 stringListClear (identifiers
);
148 variable_possible
= (boolean
)(!in_rule
);
153 else if (isspace (c
))
157 else if (variable_possible
&& c
== '?')
161 variable_possible
= (c
== '=');
163 else if (variable_possible
&& c
== ':' &&
164 stringListCount (identifiers
) > 0)
171 for (i
= 0; i
< stringListCount (identifiers
); i
++)
172 newTarget (stringListItem (identifiers
, i
));
173 stringListClear (identifiers
);
177 else if (variable_possible
&& c
== '=' &&
178 stringListCount (identifiers
) == 1)
180 newMacro (stringListItem (identifiers
, 0));
184 else if (variable_possible
&& isIdentifier (c
))
186 vString
*name
= vStringNew ();
187 readIdentifier (c
, name
);
188 stringListAdd (identifiers
, name
);
190 if (stringListCount (identifiers
) == 1)
192 if (in_define
&& ! strcmp (vStringValue (name
), "endef"))
196 else if (! strcmp (vStringValue (name
), "define"))
199 c
= skipToNonWhite (nextChar ());
201 /* all remaining characters on the line are the name -- even spaces */
202 while (c
!= EOF
&& c
!= '\n')
204 vStringPut (name
, c
);
209 vStringTerminate (name
);
210 vStringStripTrailing (name
);
213 else if (! strcmp (vStringValue (name
), "export"))
214 stringListClear (identifiers
);
218 variable_possible
= FALSE
;
220 stringListDelete (identifiers
);
223 extern parserDefinition
* MakefileParser (void)
225 static const char *const patterns
[] = { "[Mm]akefile", "GNUmakefile", NULL
};
226 static const char *const extensions
[] = { "mak", "mk", NULL
};
227 parserDefinition
* const def
= parserNew ("Make");
228 def
->kinds
= MakeKinds
;
229 def
->kindCount
= KIND_COUNT (MakeKinds
);
230 def
->patterns
= patterns
;
231 def
->extensions
= extensions
;
232 def
->parser
= findMakeTags
;
236 /* vi:set tabstop=4 shiftwidth=4: */