2005-11-22 12:26:26 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Copyright (c) 1996-2001, Darren Hiebert
|
|
|
|
*
|
|
|
|
* This source code is released for free distribution under the terms of the
|
|
|
|
* GNU General Public License.
|
|
|
|
*
|
|
|
|
* This module contains functions for managing source languages and
|
|
|
|
* dispatching files to the appropriate language parser.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* INCLUDE FILES
|
|
|
|
*/
|
|
|
|
#include "general.h" /* must always come first */
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include "entry.h"
|
|
|
|
#include "main.h"
|
|
|
|
#define OPTION_WRITE
|
|
|
|
#include "options.h"
|
2006-05-10 19:52:42 +00:00
|
|
|
#include "parsers.h"
|
2005-11-22 12:26:26 +00:00
|
|
|
#include "read.h"
|
|
|
|
#include "vstring.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DATA DEFINITIONS
|
|
|
|
*/
|
|
|
|
static parserDefinitionFunc* BuiltInParsers[] = { PARSER_LIST };
|
|
|
|
parserDefinition** LanguageTable = NULL;
|
|
|
|
static unsigned int LanguageCount = 0;
|
|
|
|
tagEntryFunction TagEntryFunction = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION DEFINITIONS
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern void makeSimpleTag (const vString* const name,
|
|
|
|
kindOption* const kinds, const int kind)
|
|
|
|
{
|
|
|
|
if (name != NULL && vStringLength (name) > 0)
|
|
|
|
{
|
|
|
|
tagEntryInfo e;
|
|
|
|
initTagEntry (&e, vStringValue (name));
|
|
|
|
|
|
|
|
e.kindName = kinds [kind].name;
|
|
|
|
e.kind = kinds [kind].letter;
|
|
|
|
|
|
|
|
makeTagEntry (&e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-10 19:52:42 +00:00
|
|
|
|
|
|
|
extern void makeSimpleScopedTag (const vString* const name,
|
|
|
|
kindOption* const kinds, const int kind,
|
|
|
|
const char* scope, const char *scope2,
|
|
|
|
const char *access)
|
|
|
|
{
|
|
|
|
if (name != NULL && vStringLength (name) > 0)
|
|
|
|
{
|
|
|
|
tagEntryInfo e;
|
|
|
|
initTagEntry (&e, vStringValue (name));
|
|
|
|
|
|
|
|
e.kindName = kinds [kind].name;
|
|
|
|
e.kind = kinds [kind].letter;
|
|
|
|
e.extensionFields.scope[0] = scope;
|
|
|
|
e.extensionFields.scope[1] = scope2;
|
|
|
|
e.extensionFields.access = access;
|
|
|
|
|
|
|
|
makeTagEntry (&e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-22 12:26:26 +00:00
|
|
|
/*
|
|
|
|
* parserDescription mapping management
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern parserDefinition* parserNew (const char* name)
|
|
|
|
{
|
|
|
|
parserDefinition* result = xCalloc (1, parserDefinition);
|
|
|
|
result->name = eStrdup (name);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern const char *getLanguageName (const langType language)
|
|
|
|
{
|
|
|
|
//Assert (0 <= language && language < (int) LanguageCount);
|
|
|
|
if (language < 0) return NULL;
|
|
|
|
return LanguageTable [language]->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern langType getNamedLanguage (const char *const name)
|
|
|
|
{
|
|
|
|
langType result = LANG_IGNORE;
|
|
|
|
unsigned int i;
|
|
|
|
Assert (name != NULL);
|
|
|
|
for (i = 0 ; i < LanguageCount && result == LANG_IGNORE ; ++i)
|
|
|
|
{
|
|
|
|
if (LanguageTable [i]->name != NULL)
|
|
|
|
if (stricmp (name, LanguageTable [i]->name) == 0)
|
|
|
|
result = i;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static langType getExtensionLanguage (const char *const extension)
|
|
|
|
{
|
|
|
|
langType result = LANG_IGNORE;
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0 ; i < LanguageCount && result == LANG_IGNORE ; ++i)
|
|
|
|
{
|
|
|
|
stringList* const exts = LanguageTable [i]->currentExtensions;
|
|
|
|
if (exts != NULL && stringListExtensionMatched (exts, extension))
|
|
|
|
result = i;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static langType getPatternLanguage (const char *const fileName)
|
|
|
|
{
|
|
|
|
langType result = LANG_IGNORE;
|
|
|
|
const char* base = baseFilename (fileName);
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0 ; i < LanguageCount && result == LANG_IGNORE ; ++i)
|
|
|
|
{
|
|
|
|
stringList* const ptrns = LanguageTable [i]->currentPatterns;
|
|
|
|
if (ptrns != NULL && stringListFileMatched (ptrns, base))
|
|
|
|
result = i;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SYS_INTERPRETER
|
|
|
|
|
|
|
|
/* The name of the language interpreter, either directly or as the argument
|
|
|
|
* to "env".
|
|
|
|
*/
|
|
|
|
static vString* determineInterpreter (const char* const cmd)
|
|
|
|
{
|
|
|
|
vString* const interpreter = vStringNew ();
|
|
|
|
const char* p = cmd;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
vStringClear (interpreter);
|
|
|
|
for ( ; isspace (*p) ; ++p)
|
|
|
|
; /* no-op */
|
|
|
|
for ( ; *p != '\0' && ! isspace (*p) ; ++p)
|
|
|
|
vStringPut (interpreter, (int) *p);
|
|
|
|
vStringTerminate (interpreter);
|
|
|
|
} while (strcmp (vStringValue (interpreter), "env") == 0);
|
|
|
|
return interpreter;
|
|
|
|
}
|
|
|
|
|
|
|
|
static langType getInterpreterLanguage (const char *const fileName)
|
|
|
|
{
|
|
|
|
langType result = LANG_IGNORE;
|
2007-07-17 12:04:46 +00:00
|
|
|
FILE* const fp = g_fopen (fileName, "r");
|
2005-11-22 12:26:26 +00:00
|
|
|
if (fp != NULL)
|
|
|
|
{
|
|
|
|
vString* const vLine = vStringNew ();
|
|
|
|
const char* const line = readLine (vLine, fp);
|
|
|
|
if (line != NULL && line [0] == '#' && line [1] == '!')
|
|
|
|
{
|
|
|
|
const char* const lastSlash = strrchr (line, '/');
|
|
|
|
const char *const cmd = lastSlash != NULL ? lastSlash+1 : line+2;
|
|
|
|
vString* const interpreter = determineInterpreter (cmd);
|
|
|
|
result = getExtensionLanguage (vStringValue (interpreter));
|
|
|
|
vStringDelete (interpreter);
|
|
|
|
}
|
|
|
|
vStringDelete (vLine);
|
|
|
|
fclose (fp);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern langType getFileLanguage (const char *const fileName)
|
|
|
|
{
|
|
|
|
langType language = Option.language;
|
|
|
|
if (language == LANG_AUTO)
|
|
|
|
{
|
|
|
|
language = getExtensionLanguage (fileExtension (fileName));
|
|
|
|
if (language == LANG_IGNORE)
|
|
|
|
language = getPatternLanguage (fileName);
|
|
|
|
#ifdef SYS_INTERPRETER
|
|
|
|
if (language == LANG_IGNORE && isExecutable (fileName))
|
|
|
|
language = getInterpreterLanguage (fileName);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return language;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void printLanguageMap (const langType language)
|
|
|
|
{
|
|
|
|
boolean first = TRUE;
|
|
|
|
unsigned int i;
|
|
|
|
stringList* map = LanguageTable [language]->currentPatterns;
|
|
|
|
Assert (0 <= language && language < (int) LanguageCount);
|
|
|
|
for (i = 0 ; map != NULL && i < stringListCount (map) ; ++i)
|
|
|
|
{
|
|
|
|
printf ("%s(%s)", (first ? "" : " "),
|
|
|
|
vStringValue (stringListItem (map, i)));
|
|
|
|
first = FALSE;
|
|
|
|
}
|
|
|
|
map = LanguageTable [language]->currentExtensions;
|
|
|
|
for (i = 0 ; map != NULL && i < stringListCount (map) ; ++i)
|
|
|
|
{
|
|
|
|
printf ("%s.%s", (first ? "" : " "),
|
|
|
|
vStringValue (stringListItem (map, i)));
|
|
|
|
first = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void installLanguageMapDefault (const langType language)
|
|
|
|
{
|
|
|
|
Assert (language >= 0);
|
|
|
|
if (LanguageTable [language]->currentPatterns != NULL)
|
|
|
|
stringListDelete (LanguageTable [language]->currentPatterns);
|
|
|
|
if (LanguageTable [language]->currentExtensions != NULL)
|
|
|
|
stringListDelete (LanguageTable [language]->currentExtensions);
|
|
|
|
|
|
|
|
if (LanguageTable [language]->patterns == NULL)
|
|
|
|
LanguageTable [language]->currentPatterns = stringListNew ();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LanguageTable [language]->currentPatterns =
|
|
|
|
stringListNewFromArgv (LanguageTable [language]->patterns);
|
|
|
|
}
|
|
|
|
if (LanguageTable [language]->extensions == NULL)
|
|
|
|
LanguageTable [language]->currentExtensions = stringListNew ();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LanguageTable [language]->currentExtensions =
|
|
|
|
stringListNewFromArgv (LanguageTable [language]->extensions);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void installLanguageMapDefaults (void)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0 ; i < LanguageCount ; ++i)
|
|
|
|
{
|
|
|
|
installLanguageMapDefault (i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void clearLanguageMap (const langType language)
|
|
|
|
{
|
|
|
|
Assert (0 <= language && language < (int) LanguageCount);
|
|
|
|
stringListClear (LanguageTable [language]->currentPatterns);
|
|
|
|
stringListClear (LanguageTable [language]->currentExtensions);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void addLanguagePatternMap (const langType language, const char* ptrn)
|
|
|
|
{
|
|
|
|
vString* const str = vStringNewInit (ptrn);
|
|
|
|
Assert (0 <= language && language < (int) LanguageCount);
|
|
|
|
if (LanguageTable [language]->currentPatterns == NULL)
|
|
|
|
LanguageTable [language]->currentPatterns = stringListNew ();
|
|
|
|
stringListAdd (LanguageTable [language]->currentPatterns, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void addLanguageExtensionMap (const langType language,
|
|
|
|
const char* extension)
|
|
|
|
{
|
|
|
|
vString* const str = vStringNewInit (extension);
|
|
|
|
Assert (0 <= language && language < (int) LanguageCount);
|
|
|
|
stringListAdd (LanguageTable [language]->currentExtensions, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void enableLanguages (const boolean state)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0 ; i < LanguageCount ; ++i)
|
|
|
|
LanguageTable [i]->enabled = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void enableLanguage (const langType language, const boolean state)
|
|
|
|
{
|
|
|
|
Assert (0 <= language && language < (int) LanguageCount);
|
|
|
|
LanguageTable [language]->enabled = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void initializeParsers (void)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0 ; i < LanguageCount ; ++i)
|
|
|
|
if (LanguageTable [i]->initialize != NULL)
|
|
|
|
(LanguageTable [i]->initialize) ((langType) i);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void initializeParsing (void)
|
|
|
|
{
|
|
|
|
unsigned int builtInCount;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
builtInCount = sizeof (BuiltInParsers) / sizeof (BuiltInParsers [0]);
|
|
|
|
LanguageTable = xMalloc (builtInCount, parserDefinition*);
|
|
|
|
|
|
|
|
for (i = 0 ; i < builtInCount ; ++i)
|
|
|
|
{
|
|
|
|
parserDefinition* const def = (*BuiltInParsers [i]) ();
|
|
|
|
if (def != NULL)
|
|
|
|
{
|
|
|
|
boolean accepted = FALSE;
|
|
|
|
if (def->name == NULL || def->name[0] == '\0')
|
|
|
|
error (FATAL, "parser definition must contain name\n");
|
|
|
|
else if (def->regex)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_REGEX
|
|
|
|
def->parser = findRegexTags;
|
|
|
|
accepted = TRUE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if ((def->parser == NULL) == (def->parser2 == NULL))
|
|
|
|
error (FATAL,
|
|
|
|
"%s parser definition must define one and only one parsing routine\n",
|
|
|
|
def->name);
|
|
|
|
else
|
|
|
|
accepted = TRUE;
|
|
|
|
if (accepted)
|
|
|
|
{
|
|
|
|
def->id = LanguageCount++;
|
|
|
|
LanguageTable [def->id] = def;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enableLanguages (TRUE);
|
|
|
|
initializeParsers ();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void freeParserResources (void)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0 ; i < LanguageCount ; ++i)
|
|
|
|
{
|
|
|
|
freeList (&LanguageTable [i]->currentPatterns);
|
|
|
|
freeList (&LanguageTable [i]->currentExtensions);
|
|
|
|
eFree (LanguageTable [i]->name);
|
|
|
|
LanguageTable [i]->name = NULL;
|
|
|
|
eFree (LanguageTable [i]);
|
|
|
|
}
|
|
|
|
eFree (LanguageTable);
|
|
|
|
LanguageTable = NULL;
|
|
|
|
LanguageCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Option parsing
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern void processLanguageDefineOption (const char *const option,
|
|
|
|
const char *const __unused__ parameter)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_REGEX
|
|
|
|
if (parameter [0] == '\0')
|
|
|
|
error (WARNING, "No language specified for \"%s\" option", option);
|
|
|
|
else if (getNamedLanguage (parameter) != LANG_IGNORE)
|
|
|
|
error (WARNING, "Language \"%s\" already defined", parameter);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned int i = LanguageCount++;
|
|
|
|
parserDefinition* const def = parserNew (parameter);
|
|
|
|
def->parser = findRegexTags;
|
|
|
|
def->currentPatterns = stringListNew ();
|
|
|
|
def->currentExtensions = stringListNew ();
|
|
|
|
def->regex = TRUE;
|
|
|
|
def->enabled = TRUE;
|
|
|
|
def->id = i;
|
|
|
|
LanguageTable = xRealloc (LanguageTable, i + 1, parserDefinition*);
|
|
|
|
LanguageTable [i] = def;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
error (WARNING, "regex support not available; required for --%s option",
|
|
|
|
option);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static kindOption *langKindOption (const langType language, const int flag)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
kindOption* result = NULL;
|
|
|
|
const parserDefinition* lang;
|
|
|
|
Assert (0 <= language && language < (int) LanguageCount);
|
|
|
|
lang = LanguageTable [language];
|
|
|
|
for (i=0 ; i < lang->kindCount && result == NULL ; ++i)
|
|
|
|
if (lang->kinds [i].letter == flag)
|
|
|
|
result = &lang->kinds [i];
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void processLegacyKindOption (const char *const parameter)
|
|
|
|
{
|
|
|
|
const langType lang = getNamedLanguage ("c");
|
|
|
|
boolean clear = FALSE;
|
|
|
|
const char* p = parameter;
|
|
|
|
boolean mode = TRUE;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
error (WARNING, "-i option is deprecated; use --c-types option instead");
|
|
|
|
if (*p == '=')
|
|
|
|
{
|
|
|
|
clear = TRUE;
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
if (clear && *p != '+' && *p != '-')
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0 ; i < LanguageTable [lang]->kindCount ; ++i)
|
|
|
|
LanguageTable [lang]->kinds [i].enabled = FALSE;
|
|
|
|
Option.include.fileNames= FALSE;
|
|
|
|
Option.include.fileScope= FALSE;
|
|
|
|
}
|
|
|
|
while ((c = *p++) != '\0') switch (c)
|
|
|
|
{
|
|
|
|
case '+': mode = TRUE; break;
|
|
|
|
case '-': mode = FALSE; break;
|
|
|
|
|
|
|
|
case 'F': Option.include.fileNames = mode; break;
|
|
|
|
case 'S': Option.include.fileScope = mode; break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
kindOption* const opt = langKindOption (lang, c);
|
|
|
|
if (opt != NULL)
|
|
|
|
opt->enabled = mode;
|
|
|
|
else
|
|
|
|
error (WARNING, "Unsupported parameter '%c' for -i option", c);
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void disableLanguageKinds (const langType language)
|
|
|
|
{
|
|
|
|
if (LanguageTable [language]->regex)
|
|
|
|
#ifdef HAVE_REGEX
|
|
|
|
disableRegexKinds (language);
|
|
|
|
#else
|
|
|
|
;
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0 ; i < LanguageTable [language]->kindCount ; ++i)
|
|
|
|
LanguageTable [language]->kinds [i].enabled = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean enableLanguageKind (const langType language,
|
|
|
|
const int kind, const boolean mode)
|
|
|
|
{
|
|
|
|
boolean result = FALSE;
|
|
|
|
if (LanguageTable [language]->regex)
|
|
|
|
#ifdef HAVE_REGEX
|
|
|
|
result = enableRegexKind (language, kind, mode);
|
|
|
|
#else
|
|
|
|
;
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kindOption* const opt = langKindOption (language, kind);
|
|
|
|
if (opt != NULL)
|
|
|
|
{
|
|
|
|
opt->enabled = mode;
|
|
|
|
result = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void processLangKindOption (const langType language,
|
|
|
|
const char *const option,
|
|
|
|
const char *const parameter)
|
|
|
|
{
|
|
|
|
const char *p = parameter;
|
|
|
|
boolean mode = TRUE;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
Assert (0 <= language && language < (int) LanguageCount);
|
|
|
|
if (*p != '+' && *p != '-')
|
|
|
|
disableLanguageKinds (language);
|
|
|
|
while ((c = *p++) != '\0') switch (c)
|
|
|
|
{
|
|
|
|
case '+': mode = TRUE; break;
|
|
|
|
case '-': mode = FALSE; break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
if (! enableLanguageKind (language, c, mode))
|
|
|
|
error (WARNING, "Unsupported parameter '%c' for --%s option",
|
|
|
|
c, option);
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern boolean processKindOption (const char *const option,
|
|
|
|
const char *const parameter)
|
|
|
|
{
|
|
|
|
boolean handled = FALSE;
|
|
|
|
const char* const dash = strchr (option, '-');
|
|
|
|
if (dash != NULL &&
|
|
|
|
(strcmp (dash + 1, "types") == 0 || strcmp (dash + 1, "kinds") == 0))
|
|
|
|
{
|
|
|
|
langType language;
|
|
|
|
vString* langName = vStringNew ();
|
|
|
|
vStringNCopyS (langName, option, dash - option);
|
|
|
|
language = getNamedLanguage (vStringValue (langName));
|
|
|
|
if (language == LANG_IGNORE)
|
|
|
|
error (WARNING, "Unknown language specified in \"%s\" option", option);
|
|
|
|
else
|
|
|
|
processLangKindOption (language, option, parameter);
|
|
|
|
vStringDelete (langName);
|
|
|
|
handled = TRUE;
|
|
|
|
}
|
|
|
|
return handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printLangugageKindOption (const kindOption* const kind)
|
|
|
|
{
|
|
|
|
printf (" %c %s%s\n", kind->letter,
|
|
|
|
kind->description != NULL ? kind->description :
|
|
|
|
(kind->name != NULL ? kind->name : ""),
|
|
|
|
kind->enabled ? "" : " [off]");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printLangugageKindOptions (const langType language)
|
|
|
|
{
|
|
|
|
const parserDefinition* lang;
|
|
|
|
Assert (0 <= language && language < (int) LanguageCount);
|
|
|
|
lang = LanguageTable [language];
|
|
|
|
if (lang->kinds != NULL || lang->regex)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
char* const name = newLowerString (lang->name);
|
|
|
|
printf (" --%s-types=[+|-]kinds\n", name);
|
|
|
|
eFree (name);
|
|
|
|
if (lang->kinds != NULL)
|
|
|
|
for (i = 0 ; i < lang->kindCount ; ++i)
|
|
|
|
printLangugageKindOption (lang->kinds + i);
|
|
|
|
#ifdef HAVE_REGEX
|
|
|
|
printRegexKindOptions (language);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void printKindOptions (void)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
printf (
|
|
|
|
"\n The following options are used to specify which language-specific tag\n\
|
|
|
|
types (or kinds) should be included in the tag file. \"Kinds\" is a group of\n\
|
|
|
|
one-letter flags designating kinds of tags to either include or exclude from\n\
|
|
|
|
the output. Each letter or group of letters may be preceded by either '+' to\n\
|
|
|
|
add it to those already included, or '-' to exclude it from the output. In\n\
|
|
|
|
the absence of any preceding '+' or '-' sign, only those kinds listed in\n\
|
|
|
|
\"kinds\" will be included in the output. Below each option is a list of the\n\
|
|
|
|
flags accepted. All kinds are enabled by default unless otherwise noted.\n\n");
|
|
|
|
|
|
|
|
for (i = 0 ; i < LanguageCount ; ++i)
|
|
|
|
printLangugageKindOptions (i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* File parsing
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void makeFileTag (const char *const fileName)
|
|
|
|
{
|
|
|
|
if (Option.include.fileNames)
|
|
|
|
{
|
|
|
|
tagEntryInfo tag;
|
|
|
|
initTagEntry (&tag, baseFilename (fileName));
|
|
|
|
|
|
|
|
tag.isFileEntry = TRUE;
|
|
|
|
tag.lineNumberEntry = TRUE;
|
|
|
|
tag.lineNumber = 1;
|
|
|
|
tag.kindName = "file";
|
|
|
|
tag.kind = 'F';
|
|
|
|
|
|
|
|
makeTagEntry (&tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean createTagsForFile (const char *const fileName,
|
|
|
|
const langType language,
|
|
|
|
const unsigned int passCount)
|
|
|
|
{
|
|
|
|
boolean retried = FALSE;
|
|
|
|
|
|
|
|
if (fileOpen (fileName, language))
|
|
|
|
{
|
|
|
|
|
|
|
|
makeFileTag (fileName);
|
|
|
|
|
|
|
|
if (LanguageTable [language]->parser != NULL)
|
|
|
|
LanguageTable [language]->parser ();
|
|
|
|
else if (LanguageTable [language]->parser2 != NULL)
|
|
|
|
retried = LanguageTable [language]->parser2 (passCount);
|
|
|
|
|
|
|
|
|
|
|
|
fileClose ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return retried;
|
|
|
|
}
|
|
|
|
|
|
|
|
static boolean createTagsWithFallback (const char *const fileName,
|
|
|
|
const langType language)
|
|
|
|
{
|
|
|
|
const unsigned long numTags = TagFile.numTags.added;
|
|
|
|
fpos_t tagFilePosition;
|
|
|
|
unsigned int passCount = 0;
|
|
|
|
boolean tagFileResized = FALSE;
|
|
|
|
|
|
|
|
fgetpos (TagFile.fp, &tagFilePosition);
|
|
|
|
while (createTagsForFile (fileName, language, ++passCount))
|
|
|
|
{
|
|
|
|
/* Restore prior state of tag file.
|
|
|
|
*/
|
|
|
|
fsetpos (TagFile.fp, &tagFilePosition);
|
|
|
|
TagFile.numTags.added = numTags;
|
|
|
|
tagFileResized = TRUE;
|
|
|
|
}
|
|
|
|
return tagFileResized;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern boolean parseFile (const char *const fileName)
|
|
|
|
{
|
|
|
|
boolean tagFileResized = FALSE;
|
|
|
|
langType language = Option.language;
|
|
|
|
if (Option.language == LANG_AUTO)
|
|
|
|
language = getFileLanguage (fileName);
|
|
|
|
Assert (language != LANG_AUTO);
|
|
|
|
if (Option.filter)
|
|
|
|
openTagFile ();
|
|
|
|
|
|
|
|
tagFileResized = createTagsWithFallback (fileName, language);
|
|
|
|
|
|
|
|
addTotals (1, 0L, 0L);
|
|
|
|
|
|
|
|
return tagFileResized;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vi:set tabstop=8 shiftwidth=4 nowrap: */
|