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

📄 c.c

📁 ultraEdit的Ctag标签工具的实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (c == EOF)
    {
	verbose ("%s: failed to find match for '%c' at line %lu\n",
		getInputFileName (), begin, inputLineNumber);
	if (braceMatching)
	    longjmp (Exception, (int) ExceptionBraceFormattingError);
	else
	    longjmp (Exception, (int) ExceptionFormattingError);
    }
}

static void skipParens (void)
{
    const int c = skipToNonWhite ();

    if (c == '(')
	skipToMatch ("()");
    else
	cppUngetc (c);
}

static void skipBraces (void)
{
    const int c = skipToNonWhite ();

    if (c == '{')
	skipToMatch ("{}");
    else
	cppUngetc (c);
}

static keywordId analyzeKeyword (const char *const name)
{
    const keywordId id = (keywordId) lookupKeyword (name, getSourceLanguage ());
    return id;
}

static void analyzeIdentifier (tokenInfo *const token)
{
    char *const name = vStringValue (token->name);
    const char *replacement = NULL;
    boolean parensToo = FALSE;

    if (isLanguage (Lang_java)  ||
	! isIgnoreToken (name, &parensToo, &replacement))
    {
	if (replacement != NULL)
	    token->keyword = analyzeKeyword (replacement);
	else
	    token->keyword = analyzeKeyword (vStringValue (token->name));

	if (token->keyword == KEYWORD_NONE)
	    token->type = TOKEN_NAME;
	else
	    token->type = TOKEN_KEYWORD;
    }
    else
    {
	initToken (token);
	if (parensToo)
	{
	    int c = skipToNonWhite ();

	    if (c == '(')
		skipToMatch ("()");
	}
    }
}

static void readIdentifier (tokenInfo *const token, const int firstChar)
{
    vString *const name = token->name;
    int c = firstChar;
    boolean first = TRUE;

    initToken (token);

    do
    {
	vStringPut (name, c);
	if (CollectingSignature)
	{
	    if (!first)
		vStringPut (Signature, c);
	    first = FALSE;
	}
	c = cppGetc ();
    } while (isident (c) || (isLanguage (Lang_java) && isHighChar (c)));
    vStringTerminate (name);
    cppUngetc (c);		/* unget non-identifier character */

    analyzeIdentifier (token);
}

static void readPackageName (tokenInfo *const token, const int firstChar)
{
    vString *const name = token->name;
    int c = firstChar;

    initToken (token);

    while (isident (c)  ||  c == '.')
    {
	vStringPut (name, c);
	c = cppGetc ();
    }
    vStringTerminate (name);
    cppUngetc (c);		/* unget non-package character */
}

static void readPackage (statementInfo *const st)
{
    tokenInfo *const token = activeToken (st);
    Assert (isType (token, TOKEN_KEYWORD));
    readPackageName (token, skipToNonWhite ());
    token->type = TOKEN_NAME;
    st->declaration = DECL_PACKAGE;
    st->gotName = TRUE;
    st->haveQualifyingName = TRUE;
}

static void processName (statementInfo *const st)
{
    Assert (isType (activeToken (st), TOKEN_NAME));
    if (st->gotName  &&  st->declaration == DECL_NONE)
	st->declaration = DECL_BASE;
    st->gotName = TRUE;
    st->haveQualifyingName = TRUE;
}

static void readOperator (statementInfo *const st)
{
    const char *const acceptable = "+-*/%^&|~!=<>,[]";
    const tokenInfo* const prev = prevToken (st,1);
    tokenInfo *const token = activeToken (st);
    vString *const name = token->name;
    int c = skipToNonWhite ();

    /*  When we arrive here, we have the keyword "operator" in 'name'.
     */
    if (isType (prev, TOKEN_KEYWORD) && (prev->keyword == KEYWORD_ENUM ||
	 prev->keyword == KEYWORD_STRUCT || prev->keyword == KEYWORD_UNION))
	;	/* ignore "operator" keyword if preceded by these keywords */
    else if (c == '(')
    {
	/*  Verify whether this is a valid function call (i.e. "()") operator.
	 */
	if (cppGetc () == ')')
	{
	    vStringPut (name, ' ');  /* always separate operator from keyword */
	    c = skipToNonWhite ();
	    if (c == '(')
		vStringCatS (name, "()");
	}
	else
	{
	    skipToMatch ("()");
	    c = cppGetc ();
	}
    }
    else if (isident1 (c))
    {
	/*  Handle "new" and "delete" operators, and conversion functions
	 *  (per 13.3.1.1.2 [2] of the C++ spec).
	 */
	boolean whiteSpace = TRUE;	/* default causes insertion of space */
	do
	{
	    if (isspace (c))
		whiteSpace = TRUE;
	    else
	    {
		if (whiteSpace)
		{
		    vStringPut (name, ' ');
		    whiteSpace = FALSE;
		}
		vStringPut (name, c);
	    }
	    c = cppGetc ();
	} while (! isOneOf (c, "(;")  &&  c != EOF);
	vStringTerminate (name);
    }
    else if (isOneOf (c, acceptable))
    {
	vStringPut (name, ' ');	/* always separate operator from keyword */
	do
	{
	    vStringPut (name, c);
	    c = cppGetc ();
	} while (isOneOf (c, acceptable));
	vStringTerminate (name);
    }

    cppUngetc (c);

    token->type	= TOKEN_NAME;
    token->keyword = KEYWORD_NONE;
    processName (st);
}

static void copyToken (tokenInfo *const dest, const tokenInfo *const src)
{
    dest->type         = src->type;
    dest->keyword      = src->keyword;
    dest->filePosition = src->filePosition;
    dest->lineNumber   = src->lineNumber;
    vStringCopy (dest->name, src->name);
}

static void setAccess (statementInfo *const st, const accessType access)
{
    if (isMember (st))
    {
	if (isLanguage (Lang_cpp))
	{
	    int c = skipToNonWhite ();

	    if (c == ':')
		reinitStatement (st, FALSE);
	    else
		cppUngetc (c);

	    st->member.accessDefault = access;
	}
	st->member.access = access;
    }
}

static void discardTypeList (tokenInfo *const token)
{
    int c = skipToNonWhite ();
    while (isident1 (c))
    {
	readIdentifier (token, c);
	c = skipToNonWhite ();
	if (c == '.'  ||  c == ',')
	    c = skipToNonWhite ();
    }
    cppUngetc (c);
}

static void addParentClass (statementInfo *const st, tokenInfo *const token)
{
    if (vStringLength (token->name) > 0  &&
	vStringLength (st->parentClasses) > 0)
    {
	vStringPut (st->parentClasses, ',');
    }
    vStringCat (st->parentClasses, token->name);
}

static void readParents (statementInfo *const st, const int qualifier)
{
    tokenInfo *const token = newToken ();
    tokenInfo *const parent = newToken ();
    int c;

    do
    {
	c = skipToNonWhite ();
	if (isident1 (c))
	{
	    readIdentifier (token, c);
	    if (isType (token, TOKEN_NAME))
		vStringCat (parent->name, token->name);
	    else
	    {
		addParentClass (st, parent);
		initToken (parent);
	    }
	}
	else if (c == qualifier)
	    vStringPut (parent->name, c);
	else if (c == '<')
	    skipToMatch ("<>");
	else if (isType (token, TOKEN_NAME))
	{
	    addParentClass (st, parent);
	    initToken (parent);
	}
    } while (c != '{'  &&  c != EOF);
    cppUngetc (c);
    deleteToken (parent);
    deleteToken (token);
}

static void skipStatement (statementInfo *const st)
{
    st->declaration = DECL_IGNORE;
    skipToOneOf (";");
}

static void processToken (tokenInfo *const token, statementInfo *const st)
{
    switch (token->keyword)		/* is it a reserved word? */
    {
	default: break;

	case KEYWORD_NONE:	processName (st);			break;
	case KEYWORD_ABSTRACT:	st->implementation = IMP_ABSTRACT;	break;
	case KEYWORD_ATTRIBUTE:	skipParens (); initToken (token);	break;
	case KEYWORD_BIND:	st->declaration = DECL_BASE;		break;
	case KEYWORD_BIT:	st->declaration = DECL_BASE;		break;
	case KEYWORD_CATCH:	skipParens (); skipBraces ();		break;
	case KEYWORD_CHAR:	st->declaration = DECL_BASE;		break;
	case KEYWORD_CLASS:	st->declaration = DECL_CLASS;		break;
	case KEYWORD_CONST:	st->declaration = DECL_BASE;		break;
	case KEYWORD_DOUBLE:	st->declaration = DECL_BASE;		break;
	case KEYWORD_ENUM:	st->declaration = DECL_ENUM;		break;
	case KEYWORD_EXTENDS:	readParents (st, '.');
				setToken (st, TOKEN_NONE);		break;
	case KEYWORD_FLOAT:	st->declaration = DECL_BASE;		break;
	case KEYWORD_FUNCTION:	st->declaration = DECL_BASE;		break;
	case KEYWORD_FRIEND:	st->scope	= SCOPE_FRIEND;		break;
	case KEYWORD_GOTO:	skipStatement (st);			break;
	case KEYWORD_IMPLEMENTS:readParents (st, '.');
				setToken (st, TOKEN_NONE);		break;
	case KEYWORD_IMPORT:	skipStatement (st);			break;
	case KEYWORD_INT:	st->declaration = DECL_BASE;		break;
	case KEYWORD_INTEGER:	st->declaration = DECL_BASE;		break;
	case KEYWORD_INTERFACE: st->declaration = DECL_INTERFACE;	break;
	case KEYWORD_LOCAL:	setAccess (st, ACCESS_LOCAL);		break;
	case KEYWORD_LONG:	st->declaration = DECL_BASE;		break;
	case KEYWORD_NAMESPACE: st->declaration = DECL_NAMESPACE;	break;
	case KEYWORD_OPERATOR:	readOperator (st);			break;
	case KEYWORD_PACKAGE:	readPackage (st);			break;
	case KEYWORD_PRIVATE:	setAccess (st, ACCESS_PRIVATE);		break;
	case KEYWORD_PROGRAM:	st->declaration = DECL_PROGRAM;		break;
	case KEYWORD_PROTECTED:	setAccess (st, ACCESS_PROTECTED);	break;
	case KEYWORD_PUBLIC:	setAccess (st, ACCESS_PUBLIC);		break;
	case KEYWORD_RETURN:	skipStatement (st);			break;
	case KEYWORD_SHORT:	st->declaration = DECL_BASE;		break;
	case KEYWORD_SIGNED:	st->declaration = DECL_BASE;		break;
	case KEYWORD_STRING:	st->declaration = DECL_BASE;		break;
	case KEYWORD_STRUCT:	st->declaration = DECL_STRUCT;		break;
	case KEYWORD_TASK:	st->declaration = DECL_TASK;		break;
	case KEYWORD_THROWS:	discardTypeList (token);		break;
	case KEYWORD_UNION:	st->declaration = DECL_UNION;		break;
	case KEYWORD_UNSIGNED:	st->declaration = DECL_BASE;		break;
	case KEYWORD_USING:	skipStatement (st);			break;
	case KEYWORD_VOID:	st->declaration = DECL_BASE;		break;
	case KEYWORD_VOLATILE:	st->declaration = DECL_BASE;		break;
	case KEYWORD_VIRTUAL:	st->implementation = IMP_VIRTUAL;	break;

	case KEYWORD_EVENT:
	    if (isLanguage (Lang_csharp))
		st->declaration = DECL_EVENT;
	    break;

	case KEYWORD_TYPEDEF:
	    reinitStatement (st, FALSE);
	    st->scope = SCOPE_TYPEDEF;
	    break;

	case KEYWORD_EXTERN:
	    if (! isLanguage (Lang_csharp) || !st->gotName)
	    {
		reinitStatement (st, FALSE);
		st->scope = SCOPE_EXTERN;
		st->declaration = DECL_BASE;
	    }
	    break;

	case KEYWORD_STATIC:
	    if (! (isLanguage (Lang_java) || isLanguage (Lang_csharp)))
	    {
		reinitStatement (st, FALSE);
		st->scope = SCOPE_STATIC;
		st->declaration = DECL_BASE;
	    }
	    break;

	case KEYWORD_FOR:
	case KEYWORD_IF:
	case KEYWORD_SWITCH:
	case KEYWORD_WHILE:
	{
	    int c = skipToNonWhite ();
	    if (c == '(')
		skipToMatch ("()");
	    break;
	}
    }
}

/*
*   Parenthesis handling functions
*/

static void restartStatement (statementInfo *const st)
{
    tokenInfo *const save = newToken ();
    tokenInfo *token = activeToken (st);

    copyToken (save, token);
    DebugStatement ( if (debug (DEBUG_PARSE)) printf ("<ES>");)
    reinitStatement (st, FALSE);
    token = activeToken (st);
    copyToken (token, save);
    deleteToken (save);
    processToken (token, st);
}

/*  Skips over a the mem-initializer-list of a ctor-initializer, defined as:
 *
 *  mem-initializer-list:
 *    mem-initializer, mem-initializer-list
 *
 *  mem-initializer:
 *    [::] [nested-name-spec] class-name (...)
 *    identifier
 */
static void skipMemIntializerList (tokenInfo *const token)
{
    int c;

    do
    {
	c = skipToNonWhite ();
	while (isident1 (c)  ||  c == ':')
	{
	    if (c != ':')
		readIdentifier (token, c);
	    c = skipToNonWhite ();
	}
	if (c == '<')
	{
	    skipToMatch ("<>");
	    c = skipToNonWhite ();
	}
	if (c == '(')
	{
	    skipToMatch ("()");
	    c = skipToNonWhite ();
	}
    } while (c == ',');
    cppUngetc (c);
}

static void skipMacro (statementInfo *const st)
{
    tokenInfo *const prev2 = prevToken (st, 2);

    if (isType (prev2, TOKEN_NAME))
	retardToken (st);
    skipToMatch ("()");
}

/*  Skips over characters following the parameter list. This will be either
 *  non-ANSI style function declarations or C++ stuff. Our choices:
 *
 *  C (K&R):

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -