⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse.c

📁 ultraEdit的Ctag标签工具的实现源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
*   $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 + -