Merge branch 'ctags/make'
Import make parser improvements from fishman/ctags#272
This commit is contained in:
commit
b839611e51
@ -59,25 +59,23 @@ static void skipLine (void)
|
||||
fileUngetc (c);
|
||||
}
|
||||
|
||||
static int skipToNonWhite (void)
|
||||
static int skipToNonWhite (int c)
|
||||
{
|
||||
int c;
|
||||
do
|
||||
while (c != '\n' && isspace (c))
|
||||
c = nextChar ();
|
||||
while (c != '\n' && isspace (c));
|
||||
return c;
|
||||
}
|
||||
|
||||
static boolean isIdentifier (int c)
|
||||
{
|
||||
return (boolean)(c != '\0' && (isalnum (c) || strchr (".-_/", c) != NULL));
|
||||
return (boolean)(c != '\0' && (isalnum (c) || strchr (".-_/$(){}%", c) != NULL));
|
||||
}
|
||||
|
||||
static boolean isSpecialTarget (vString *const name)
|
||||
{
|
||||
size_t i = 0;
|
||||
/* All special targets begin with '.'. */
|
||||
if (vStringChar (name, i++) != '.') {
|
||||
if (vStringLength (name) < 1 || vStringChar (name, i++) != '.') {
|
||||
return FALSE;
|
||||
}
|
||||
while (i < vStringLength (name)) {
|
||||
@ -105,67 +103,27 @@ static void newMacro (vString *const name)
|
||||
makeSimpleTag (name, MakeKinds, K_MACRO);
|
||||
}
|
||||
|
||||
static void newMacroFromDefine (vString *const name)
|
||||
{
|
||||
/* name is something like "define JAVAHPP_RULE", find the space and jump to the next char */
|
||||
char *name_val = strchr (vStringValue (name), ' ');
|
||||
|
||||
if (name_val != NULL) {
|
||||
vStringCopyS (name, name_val + 1);
|
||||
makeSimpleTag (name, MakeKinds, K_MACRO);
|
||||
}
|
||||
}
|
||||
|
||||
static void readIdentifier (const int first, vString *const id)
|
||||
{
|
||||
int depth = 0;
|
||||
int c = first;
|
||||
int c_prev = first;
|
||||
int c_next = first;
|
||||
vStringClear (id);
|
||||
while (isIdentifier (c) || c == ' ')
|
||||
while (isIdentifier (c) || (depth > 0 && c != EOF && c != '\n'))
|
||||
{
|
||||
c_next = nextChar ();
|
||||
if (c == ' ') {
|
||||
/* add the space character only if the previous and
|
||||
* next character are valid identifiers */
|
||||
if (isIdentifier (c_prev) && isIdentifier (c_next))
|
||||
if (c == '(' || c == '}')
|
||||
depth++;
|
||||
else if (depth > 0 && (c == ')' || c == '}'))
|
||||
depth--;
|
||||
vStringPut (id, c);
|
||||
}
|
||||
else {
|
||||
vStringPut (id, c);
|
||||
}
|
||||
c_prev = c;
|
||||
c = c_next;
|
||||
c = nextChar ();
|
||||
}
|
||||
fileUngetc (c);
|
||||
vStringTerminate (id);
|
||||
}
|
||||
|
||||
static void skipToMatch (const char *const pair)
|
||||
{
|
||||
const int begin = pair [0], end = pair [1];
|
||||
const unsigned long inputLineNumber = getInputLineNumber ();
|
||||
int matchLevel = 1;
|
||||
int c = '\0';
|
||||
|
||||
while (matchLevel > 0)
|
||||
{
|
||||
c = nextChar ();
|
||||
if (c == begin)
|
||||
++matchLevel;
|
||||
else if (c == end)
|
||||
--matchLevel;
|
||||
else if (c == '\n' || c == EOF)
|
||||
break;
|
||||
}
|
||||
if (c == EOF)
|
||||
verbose ("%s: failed to find match for '%c' at line %lu\n",
|
||||
getInputFileName (), begin, inputLineNumber);
|
||||
}
|
||||
|
||||
static void findMakeTags (void)
|
||||
{
|
||||
vString *name = vStringNew ();
|
||||
stringList *identifiers = stringListNew ();
|
||||
boolean newline = TRUE;
|
||||
boolean in_define = FALSE;
|
||||
boolean in_rule = FALSE;
|
||||
@ -178,14 +136,15 @@ static void findMakeTags (void)
|
||||
{
|
||||
if (in_rule)
|
||||
{
|
||||
if (c == '\t')
|
||||
if (c == '\t' || (c = skipToNonWhite (c)) == '#')
|
||||
{
|
||||
skipLine (); /* skip rule */
|
||||
continue;
|
||||
skipLine (); /* skip rule or comment */
|
||||
c = nextChar ();
|
||||
}
|
||||
else
|
||||
else if (c != '\n')
|
||||
in_rule = FALSE;
|
||||
}
|
||||
stringListClear (identifiers);
|
||||
variable_possible = (boolean)(!in_rule);
|
||||
newline = FALSE;
|
||||
}
|
||||
@ -195,77 +154,70 @@ static void findMakeTags (void)
|
||||
continue;
|
||||
else if (c == '#')
|
||||
skipLine ();
|
||||
else if (c == '(')
|
||||
skipToMatch ("()");
|
||||
else if (c == '{')
|
||||
skipToMatch ("{}");
|
||||
else if (c == ':')
|
||||
else if (variable_possible && c == '?')
|
||||
{
|
||||
variable_possible = TRUE;
|
||||
c = nextChar ();
|
||||
fileUngetc (c);
|
||||
variable_possible = (c == '=');
|
||||
}
|
||||
else if (variable_possible && c == ':' &&
|
||||
stringListCount (identifiers) > 0)
|
||||
{
|
||||
c = nextChar ();
|
||||
fileUngetc (c);
|
||||
if (c != '=')
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < stringListCount (identifiers); i++)
|
||||
newTarget (stringListItem (identifiers, i));
|
||||
stringListClear (identifiers);
|
||||
in_rule = TRUE;
|
||||
}
|
||||
}
|
||||
else if (variable_possible && c == '=' &&
|
||||
stringListCount (identifiers) == 1)
|
||||
{
|
||||
newMacro (stringListItem (identifiers, 0));
|
||||
skipLine ();
|
||||
in_rule = FALSE;
|
||||
}
|
||||
else if (variable_possible && isIdentifier (c))
|
||||
{
|
||||
vString *name = vStringNew ();
|
||||
readIdentifier (c, name);
|
||||
if (strncmp (vStringValue (name), "endef", 5) == 0)
|
||||
stringListAdd (identifiers, name);
|
||||
|
||||
if (stringListCount (identifiers) == 1)
|
||||
{
|
||||
if (in_define && ! strcmp (vStringValue (name), "endef"))
|
||||
in_define = FALSE;
|
||||
else if (in_define)
|
||||
skipLine ();
|
||||
else if (strncmp (vStringValue (name), "define", 6) == 0 &&
|
||||
isIdentifier (c))
|
||||
else if (! strcmp (vStringValue (name), "define"))
|
||||
{
|
||||
in_define = TRUE;
|
||||
c = skipToNonWhite ();
|
||||
newMacroFromDefine (name);
|
||||
skipLine ();
|
||||
}
|
||||
else {
|
||||
c = skipToNonWhite ();
|
||||
if (strchr (":?+", c) != NULL)
|
||||
c = skipToNonWhite (nextChar ());
|
||||
vStringClear (name);
|
||||
/* all remaining characters on the line are the name -- even spaces */
|
||||
while (c != EOF && c != '\n')
|
||||
{
|
||||
boolean append = (boolean)(c == '+');
|
||||
boolean was_colon = (c == ':');
|
||||
vStringPut (name, c);
|
||||
c = nextChar ();
|
||||
if (was_colon)
|
||||
{
|
||||
if (c == '=')
|
||||
{
|
||||
newMacro (name);
|
||||
in_rule = FALSE;
|
||||
skipLine ();
|
||||
}
|
||||
else
|
||||
{
|
||||
in_rule = TRUE;
|
||||
newTarget (name);
|
||||
}
|
||||
}
|
||||
else if (append)
|
||||
{
|
||||
skipLine ();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == '\n')
|
||||
fileUngetc (c);
|
||||
}
|
||||
}
|
||||
else if (c == '=')
|
||||
{
|
||||
vStringTerminate (name);
|
||||
vStringStripTrailing (name);
|
||||
newMacro (name);
|
||||
in_rule = FALSE;
|
||||
skipLine ();
|
||||
}
|
||||
else
|
||||
{
|
||||
fileUngetc (c);
|
||||
}
|
||||
else if (! strcmp (vStringValue (name), "export"))
|
||||
stringListClear (identifiers);
|
||||
}
|
||||
}
|
||||
else
|
||||
variable_possible = FALSE;
|
||||
}
|
||||
vStringDelete (name);
|
||||
stringListDelete (identifiers);
|
||||
}
|
||||
|
||||
extern parserDefinition* MakefileParser (void)
|
||||
|
@ -200,6 +200,11 @@ test_sources = \
|
||||
line_directives.c \
|
||||
local.c \
|
||||
macros.c \
|
||||
make-comment-in-rule.mak \
|
||||
make-gnumake-pattern-rules.mak \
|
||||
make-multi-target.mak \
|
||||
make-target-with-parentheses.mak \
|
||||
make-variable-on-cmdline.mak \
|
||||
masm.asm \
|
||||
matlab_backtracking.m \
|
||||
matlab_test.m \
|
||||
|
17
tests/ctags/make-comment-in-rule.mak
Normal file
17
tests/ctags/make-comment-in-rule.mak
Normal file
@ -0,0 +1,17 @@
|
||||
# all this is one single rule
|
||||
all:
|
||||
a=1; echo "$$a"
|
||||
# foo
|
||||
b=2; echo "$$b"
|
||||
# foo
|
||||
c=3; echo "$$c"
|
||||
# foo
|
||||
d=4; echo "$$d"
|
||||
# foo
|
||||
e=5; echo "$$e"
|
||||
|
||||
|
||||
f=6; echo "$$f"
|
||||
# foo
|
||||
|
||||
g=7; echo "$$g"
|
2
tests/ctags/make-comment-in-rule.mak.tags
Normal file
2
tests/ctags/make-comment-in-rule.mak.tags
Normal file
@ -0,0 +1,2 @@
|
||||
# format=tagmanager
|
||||
allÌ16Ö0
|
8
tests/ctags/make-gnumake-pattern-rules.mak
Normal file
8
tests/ctags/make-gnumake-pattern-rules.mak
Normal file
@ -0,0 +1,8 @@
|
||||
%.o: %.c
|
||||
touch $@
|
||||
|
||||
%.p %.q: %.d
|
||||
touch $@
|
||||
|
||||
%a b%:
|
||||
touch $@
|
6
tests/ctags/make-gnumake-pattern-rules.mak.tags
Normal file
6
tests/ctags/make-gnumake-pattern-rules.mak.tags
Normal file
@ -0,0 +1,6 @@
|
||||
# format=tagmanager
|
||||
%.oÌ16Ö0
|
||||
%.pÌ16Ö0
|
||||
%.qÌ16Ö0
|
||||
%aÌ16Ö0
|
||||
b%Ì16Ö0
|
8
tests/ctags/make-multi-target.mak
Normal file
8
tests/ctags/make-multi-target.mak
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
all: foo bar
|
||||
|
||||
foo bar: baz
|
||||
echo $@
|
||||
|
||||
baz:
|
||||
echo $@
|
5
tests/ctags/make-multi-target.mak.tags
Normal file
5
tests/ctags/make-multi-target.mak.tags
Normal file
@ -0,0 +1,5 @@
|
||||
# format=tagmanager
|
||||
allÌ16Ö0
|
||||
barÌ16Ö0
|
||||
bazÌ16Ö0
|
||||
fooÌ16Ö0
|
1
tests/ctags/make-target-with-parentheses.mak
Normal file
1
tests/ctags/make-target-with-parentheses.mak
Normal file
@ -0,0 +1 @@
|
||||
$(obj)/raid6int1.c: F := 6
|
3
tests/ctags/make-target-with-parentheses.mak.tags
Normal file
3
tests/ctags/make-target-with-parentheses.mak.tags
Normal file
@ -0,0 +1,3 @@
|
||||
# format=tagmanager
|
||||
$(obj)/raid6int1.cÌ16Ö0
|
||||
FÌ65536Ö0
|
2
tests/ctags/make-variable-on-cmdline.mak
Normal file
2
tests/ctags/make-variable-on-cmdline.mak
Normal file
@ -0,0 +1,2 @@
|
||||
fixme:
|
||||
cmd -g FOO=BAR
|
2
tests/ctags/make-variable-on-cmdline.mak.tags
Normal file
2
tests/ctags/make-variable-on-cmdline.mak.tags
Normal file
@ -0,0 +1,2 @@
|
||||
# format=tagmanager
|
||||
fixmeÌ16Ö0
|
@ -1,15 +1,14 @@
|
||||
# format=tagmanager
|
||||
$(obj)/raid6int1.cÌ16Ö0
|
||||
AÌ65536Ö0
|
||||
BÌ65536Ö0
|
||||
CÌ65536Ö0
|
||||
DÌ65536Ö0
|
||||
EÌ65536Ö0
|
||||
ENV_VAR1Ì65536Ö0
|
||||
ENV_VAR2Ì65536Ö0
|
||||
FÌ65536Ö0
|
||||
GÌ65536Ö0
|
||||
HÌ65536Ö0
|
||||
IÌ65536Ö0
|
||||
a.oÌ16Ö0
|
||||
b.oÌ16Ö0
|
||||
defaultÌ16Ö0
|
||||
export IÌ65536Ö0
|
||||
|
Loading…
x
Reference in New Issue
Block a user