Kaydet (Commit) 945a4154 authored tarafından Enrico Tröger's avatar Enrico Tröger

Update Makefile parser from CTags SVN and improve it to detect targets in Makefiles.

git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2388 ea778897-0a13-0410-b9d1-a72fbfd435f5
üst 5c01fffb
......@@ -4,6 +4,9 @@
src/highlighting.c:
Add styles to customize line and search marker and add
translucency setting.
* tagmanager/make.c, src/symbols.c:
Update Makefile parser from CTags SVN and improve it to detect
targets in Makefiles.
2008-03-21 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
......
......@@ -740,6 +740,12 @@ static void init_tag_list(gint idx)
NULL);
break;
}
case GEANY_FILETYPES_MAKE:
tag_list_add_groups(tag_store,
&tv_iters.tag_function, _("Targets"), "classviewer-method",
&tv_iters.tag_macro, _("Macros"), "classviewer-macro",
NULL);
break;
case GEANY_FILETYPES_D:
default:
{
......
/*
* $Id$
*
* Copyright (c) 2000-2001, Darren Hiebert
* Copyright (c) 2000-2005, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License.
......@@ -11,10 +12,13 @@
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include "general.h" /* must always come first */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "options.h"
#include "parse.h"
#include "read.h"
#include "vstring.h"
......@@ -23,80 +27,192 @@
* DATA DEFINITIONS
*/
typedef enum {
K_MACRO
K_MACRO, K_TARGET
} shKind;
static kindOption MakeKinds [] = {
{ TRUE, 'm', "macro", "macros"}
{ TRUE, 'm', "macro", "macros"},
{ TRUE, 'f', "function", "targets"}
};
/*
* FUNCTION DEFINITIONS
*/
static int nextChar (void)
{
int c = fileGetc ();
if (c == '\\')
{
c = fileGetc ();
if (c == '\n')
c = fileGetc ();
}
return c;
}
static void skipLine (void)
{
int c;
do
c = nextChar ();
while (c != EOF && c != '\n');
if (c == '\n')
fileUngetc (c);
}
static int skipToNonWhite (void)
{
int c;
do
c = nextChar ();
while (c != '\n' && isspace (c));
return c;
}
static boolean isIdentifier (int c)
{
return (boolean)(isalnum (c) || c == '_');
return (boolean)(c != '\0' && (isalnum (c) || strchr (".-_", c) != NULL));
}
static void findMakeTags (void)
static void readIdentifier (const int first, vString *const id)
{
int c = first;
vStringClear (id);
while (isIdentifier (c))
{
vStringPut (id, c);
c = nextChar ();
}
fileUngetc (c);
vStringTerminate (id);
}
static void skipToMatch (const char *const pair)
{
vString *name = vStringNew ();
const unsigned char *line;
const int begin = pair [0], end = pair [1];
const unsigned long inputLineNumber = getInputLineNumber ();
int matchLevel = 1;
int c = '\0';
while ((line = fileReadLine ()) != NULL)
{
const unsigned char* cp = line;
boolean possible = TRUE;
while (matchLevel > 0)
{
c = nextChar ();
if (c == begin)
++matchLevel;
else if (c == end)
--matchLevel;
else if (c == '\n')
break;
}
if (c == EOF)
verbose ("%s: failed to find match for '%c' at line %lu\n",
getInputFileName (), begin, inputLineNumber);
}
while (isspace ((int) *cp))
++cp;
if (*cp == '#')
continue;
static void findMakeTags (void)
{
vString *name = vStringNew ();
boolean newline = TRUE;
boolean in_define = FALSE;
boolean in_rule = FALSE;
boolean variable_possible = TRUE;
int c;
while (*cp != '\0')
while ((c = nextChar ()) != EOF)
{
/* We look for any sequence of identifier characters following
* either a white space or a colon and followed by either = or :=
*/
if (possible && isIdentifier ((int) *cp))
{
while (isIdentifier ((int) *cp))
if (newline)
{
if (in_rule)
{
if (c == '\t')
{
skipLine (); /* skip rule */
continue;
}
else
in_rule = FALSE;
}
variable_possible = (boolean)(!in_rule);
newline = FALSE;
}
if (c == '\n')
newline = TRUE;
else if (isspace (c))
continue;
else if (c == '#')
skipLine ();
else if (c == '(')
skipToMatch ("()");
else if (c == '{')
skipToMatch ("{}");
else if (c == ':')
{
vStringPut (name, (int) *cp);
++cp;
variable_possible = TRUE;
in_rule = TRUE;
}
else if (variable_possible && isIdentifier (c))
{
readIdentifier (c, name);
if (strcmp (vStringValue (name), "endef") == 0)
in_define = FALSE;
else if (in_define)
skipLine ();
else if (strcmp (vStringValue (name), "define") == 0 &&
isIdentifier (c))
{
in_define = TRUE;
c = skipToNonWhite ();
readIdentifier (c, name);
makeSimpleTag (name, MakeKinds, K_MACRO);
skipLine ();
}
else {
c = skipToNonWhite ();
if (strchr (":?+", c) != NULL)
{
boolean append = (boolean)(c == '+');
if (c == ':')
{
in_rule = TRUE;
makeSimpleTag (name, MakeKinds, K_TARGET);
}
c = nextChar ();
if (c != '=')
fileUngetc (c);
else if (append)
{
skipLine ();
continue;
}
}
if (c == '=')
{
makeSimpleTag (name, MakeKinds, K_MACRO);
in_rule = FALSE;
skipLine ();
}
}
}
vStringTerminate (name);
while (isspace ((int) *cp))
++cp;
if ( *cp == ':')
++cp;
if ( *cp == '=')
makeSimpleTag (name, MakeKinds, K_MACRO);
vStringClear (name);
}
else if (isspace ((int) *cp) || *cp == ':')
possible = TRUE;
else
possible = FALSE;
if (*cp != '\0')
++cp;
else
variable_possible = FALSE;
}
}
vStringDelete (name);
vStringDelete (name);
}
extern parserDefinition* MakefileParser (void)
{
static const char *const patterns [] = { "[Mm]akefile", NULL };
static const char *const extensions [] = { "mak", "mk", NULL };
parserDefinition* const def = parserNew ("Make");
def->kinds = MakeKinds;
def->kindCount = KIND_COUNT (MakeKinds);
def->patterns = patterns;
def->extensions = extensions;
def->parser = findMakeTags;
return def;
static const char *const patterns [] = { "[Mm]akefile", NULL };
static const char *const extensions [] = { "mak", "mk", NULL };
parserDefinition* const def = parserNew ("Make");
def->kinds = MakeKinds;
def->kindCount = KIND_COUNT (MakeKinds);
def->patterns = patterns;
def->extensions = extensions;
def->parser = findMakeTags;
return def;
}
/* vi:set tabstop=8 shiftwidth=4: */
/* vi:set tabstop=4 shiftwidth=4: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment