Merge branch 'ctags/make'

Import make parser improvements from fishman/ctags#272
This commit is contained in:
Colomban Wendling 2015-04-20 20:04:47 +02:00
commit b839611e51
13 changed files with 129 additions and 119 deletions

View File

@ -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))
vStringPut (id, c);
}
else {
vStringPut (id, c);
}
c_prev = c;
c = c_next;
if (c == '(' || c == '}')
depth++;
else if (depth > 0 && (c == ')' || c == '}'))
depth--;
vStringPut (id, c);
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;
in_rule = 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)
in_define = FALSE;
else if (in_define)
skipLine ();
else if (strncmp (vStringValue (name), "define", 6) == 0 &&
isIdentifier (c))
stringListAdd (identifiers, name);
if (stringListCount (identifiers) == 1)
{
in_define = TRUE;
c = skipToNonWhite ();
newMacroFromDefine (name);
skipLine ();
}
else {
c = skipToNonWhite ();
if (strchr (":?+", c) != NULL)
{
boolean append = (boolean)(c == '+');
boolean was_colon = (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
{
fileUngetc (c);
}
}
else if (c == '=')
{
newMacro (name);
in_rule = FALSE;
if (in_define && ! strcmp (vStringValue (name), "endef"))
in_define = FALSE;
else if (in_define)
skipLine ();
}
else
else if (! strcmp (vStringValue (name), "define"))
{
fileUngetc (c);
in_define = TRUE;
c = skipToNonWhite (nextChar ());
vStringClear (name);
/* all remaining characters on the line are the name -- even spaces */
while (c != EOF && c != '\n')
{
vStringPut (name, c);
c = nextChar ();
}
if (c == '\n')
fileUngetc (c);
vStringTerminate (name);
vStringStripTrailing (name);
newMacro (name);
}
else if (! strcmp (vStringValue (name), "export"))
stringListClear (identifiers);
}
}
else
variable_possible = FALSE;
}
vStringDelete (name);
stringListDelete (identifiers);
}
extern parserDefinition* MakefileParser (void)

View File

@ -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 \

View 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"

View File

@ -0,0 +1,2 @@
# format=tagmanager
allÌ16Ö0

View File

@ -0,0 +1,8 @@
%.o: %.c
touch $@
%.p %.q: %.d
touch $@
%a b%:
touch $@

View File

@ -0,0 +1,6 @@
# format=tagmanager
%.oÌ16Ö0
%.pÌ16Ö0
%.qÌ16Ö0
%aÌ16Ö0
b%Ì16Ö0

View File

@ -0,0 +1,8 @@
all: foo bar
foo bar: baz
echo $@
baz:
echo $@

View File

@ -0,0 +1,5 @@
# format=tagmanager
allÌ16Ö0
barÌ16Ö0
bazÌ16Ö0
fooÌ16Ö0

View File

@ -0,0 +1 @@
$(obj)/raid6int1.c: F := 6

View File

@ -0,0 +1,3 @@
# format=tagmanager
$(obj)/raid6int1.cÌ16Ö0
FÌ65536Ö0

View File

@ -0,0 +1,2 @@
fixme:
cmd -g FOO=BAR

View File

@ -0,0 +1,2 @@
# format=tagmanager
fixmeÌ16Ö0

View File

@ -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