📄 parse.c
字号:
/*
* $Id: parse.c,v 1.11 2003/10/13 02:35:45 darren Exp $
*
* Copyright (c) 1996-2003, 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>
#ifdef HAVE_FNMATCH_H
#include <fnmatch.h>
#endif
#include "debug.h"
#include "entry.h"
#include "main.h"
#define OPTION_WRITE
#include "options.h"
#include "parsers.h"
#include "read.h"
#include "routines.h"
#include "vstring.h"
/*
* DATA DEFINITIONS
*/
static parserDefinitionFunc* BuiltInParsers[] = { PARSER_LIST };
static parserDefinition** LanguageTable = NULL;
static unsigned int LanguageCount = 0;
/*
* FUNCTION DEFINITIONS
*/
extern void makeSimpleTag (
const vString* const name, kindOption* const kinds, const int kind)
{
if (kinds [kind].enabled && name != NULL && vStringLength (name) > 0)
{
tagEntryInfo e;
initTagEntry (&e, vStringValue (name));
e.kindName = kinds [kind].name;
e.kind = kinds [kind].letter;
makeTagEntry (&e);
}
}
/*
* 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)
{
const char* result;
if (language == LANG_IGNORE)
result = "unknown";
else
{
Assert (0 <= language && language < (int) LanguageCount);
result = LanguageTable [language]->name;
}
return result;
}
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 (strcasecmp (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 ((int) *p) ; ++p)
; /* no-op */
for ( ; *p != '\0' && ! isspace ((int) *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;
FILE* const fp = fopen (fileName, "r");
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)
{
fileStatus *status = eStat (fileName);
if (status->isExecutable)
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);
}
if (Option.verbose)
printLanguageMap (language);
verbose ("\n");
}
extern void installLanguageMapDefaults (void)
{
unsigned int i;
for (i = 0 ; i < LanguageCount ; ++i)
{
verbose (" %s: ", getLanguageName (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*);
verbose ("Installing parsers: ");
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)
{
verbose ("%s%s", i > 0 ? ", " : "", def->name);
def->id = LanguageCount++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -