📄 c.c
字号:
/*
* $Id: c.c,v 1.28 2004/02/28 15:37:52 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 parsing and scanning C, C++ and Java
* source files.
*/
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include <string.h>
#include <setjmp.h>
#include "debug.h"
#include "entry.h"
#include "get.h"
#include "keyword.h"
#include "options.h"
#include "parse.h"
#include "read.h"
#include "routines.h"
/*
* MACROS
*/
#define MaxFields 6
#define stringValue(a) #a
#define activeToken(st) ((st)->token [(int) (st)->tokenIndex])
#define parentDecl(st) ((st)->parent == NULL ? \
DECL_NONE : (st)->parent->declaration)
#define isType(token,t) (boolean) ((token)->type == (t))
#define insideEnumBody(st) ((st)->parent == NULL ? FALSE : \
(boolean) ((st)->parent->declaration == DECL_ENUM))
#define isExternCDecl(st,c) (boolean) ((c) == STRING_SYMBOL && \
! (st)->haveQualifyingName && (st)->scope == SCOPE_EXTERN)
#define isOneOf(c,s) (boolean) (strchr ((s), (c)) != NULL)
#define isHighChar(c) ((unsigned char)(c) >= 0xc0)
/*
* DATA DECLARATIONS
*/
enum { NumTokens = 3 };
typedef enum eException {
ExceptionNone, ExceptionEOF, ExceptionFormattingError,
ExceptionBraceFormattingError
} exception_t;
/* Used to specify type of keyword.
*/
typedef enum eKeywordId {
KEYWORD_NONE = -1,
KEYWORD_ATTRIBUTE, KEYWORD_ABSTRACT,
KEYWORD_BOOLEAN, KEYWORD_BYTE, KEYWORD_BAD_STATE, KEYWORD_BAD_TRANS,
KEYWORD_BIND, KEYWORD_BIND_VAR, KEYWORD_BIT,
KEYWORD_CASE, KEYWORD_CATCH, KEYWORD_CHAR, KEYWORD_CLASS, KEYWORD_CONST,
KEYWORD_CONSTRAINT, KEYWORD_COVERAGE_BLOCK, KEYWORD_COVERAGE_DEF,
KEYWORD_DEFAULT, KEYWORD_DELEGATE, KEYWORD_DO, KEYWORD_DOUBLE,
KEYWORD_ELSE, KEYWORD_ENUM, KEYWORD_EXPLICIT, KEYWORD_EXTERN,
KEYWORD_EXTENDS, KEYWORD_EVENT,
KEYWORD_FINAL, KEYWORD_FLOAT, KEYWORD_FOR, KEYWORD_FRIEND, KEYWORD_FUNCTION,
KEYWORD_GOTO,
KEYWORD_IF, KEYWORD_IMPLEMENTS, KEYWORD_IMPORT, KEYWORD_INLINE, KEYWORD_INT,
KEYWORD_INOUT, KEYWORD_INPUT, KEYWORD_INTEGER, KEYWORD_INTERFACE,
KEYWORD_INTERNAL,
KEYWORD_LOCAL, KEYWORD_LONG,
KEYWORD_M_BAD_STATE, KEYWORD_M_BAD_TRANS, KEYWORD_M_STATE, KEYWORD_M_TRANS,
KEYWORD_MUTABLE,
KEYWORD_NAMESPACE, KEYWORD_NEW, KEYWORD_NEWCOV, KEYWORD_NATIVE,
KEYWORD_OPERATOR, KEYWORD_OUTPUT, KEYWORD_OVERLOAD, KEYWORD_OVERRIDE,
KEYWORD_PACKED, KEYWORD_PORT, KEYWORD_PACKAGE, KEYWORD_PRIVATE,
KEYWORD_PROGRAM, KEYWORD_PROTECTED, KEYWORD_PUBLIC,
KEYWORD_REGISTER, KEYWORD_RETURN,
KEYWORD_SHADOW, KEYWORD_STATE,
KEYWORD_SHORT, KEYWORD_SIGNED, KEYWORD_STATIC, KEYWORD_STRING,
KEYWORD_STRUCT, KEYWORD_SWITCH, KEYWORD_SYNCHRONIZED,
KEYWORD_TASK, KEYWORD_TEMPLATE, KEYWORD_THIS, KEYWORD_THROW,
KEYWORD_THROWS, KEYWORD_TRANSIENT, KEYWORD_TRANS, KEYWORD_TRANSITION,
KEYWORD_TRY, KEYWORD_TYPEDEF, KEYWORD_TYPENAME,
KEYWORD_UINT, KEYWORD_ULONG, KEYWORD_UNION, KEYWORD_UNSIGNED, KEYWORD_USHORT,
KEYWORD_USING,
KEYWORD_VIRTUAL, KEYWORD_VOID, KEYWORD_VOLATILE,
KEYWORD_WCHAR_T, KEYWORD_WHILE
} keywordId;
/* Used to determine whether keyword is valid for the current language and
* what its ID is.
*/
typedef struct sKeywordDesc {
const char *name;
keywordId id;
short isValid [5]; /* indicates languages for which kw is valid */
} keywordDesc;
/* Used for reporting the type of object parsed by nextToken ().
*/
typedef enum eTokenType {
TOKEN_NONE, /* none */
TOKEN_ARGS, /* a parenthetical pair and its contents */
TOKEN_BRACE_CLOSE,
TOKEN_BRACE_OPEN,
TOKEN_COLON, /* the colon character */
TOKEN_COMMA, /* the comma character */
TOKEN_DOUBLE_COLON, /* double colon indicates nested-name-specifier */
TOKEN_KEYWORD,
TOKEN_NAME, /* an unknown name */
TOKEN_PACKAGE, /* a Java package name */
TOKEN_PAREN_NAME, /* a single name in parentheses */
TOKEN_SEMICOLON, /* the semicolon character */
TOKEN_SPEC, /* a storage class specifier, qualifier, type, etc. */
TOKEN_COUNT
} tokenType;
/* This describes the scoping of the current statement.
*/
typedef enum eTagScope {
SCOPE_GLOBAL, /* no storage class specified */
SCOPE_STATIC, /* static storage class */
SCOPE_EXTERN, /* external storage class */
SCOPE_FRIEND, /* declares access only */
SCOPE_TYPEDEF, /* scoping depends upon context */
SCOPE_COUNT
} tagScope;
typedef enum eDeclaration {
DECL_NONE,
DECL_BASE, /* base type (default) */
DECL_CLASS,
DECL_ENUM,
DECL_EVENT,
DECL_FUNCTION,
DECL_IGNORE, /* non-taggable "declaration" */
DECL_INTERFACE,
DECL_NAMESPACE,
DECL_NOMANGLE, /* C++ name demangling block */
DECL_PACKAGE,
DECL_PROGRAM, /* Vera program */
DECL_STRUCT,
DECL_TASK, /* Vera task */
DECL_UNION,
DECL_COUNT
} declType;
typedef enum eVisibilityType {
ACCESS_UNDEFINED,
ACCESS_LOCAL,
ACCESS_PRIVATE,
ACCESS_PROTECTED,
ACCESS_PUBLIC,
ACCESS_DEFAULT, /* Java-specific */
ACCESS_COUNT
} accessType;
/* Information about the parent class of a member (if any).
*/
typedef struct sMemberInfo {
accessType access; /* access of current statement */
accessType accessDefault; /* access default for current statement */
} memberInfo;
typedef struct sTokenInfo {
tokenType type;
keywordId keyword;
vString* name; /* the name of the token */
unsigned long lineNumber; /* line number of tag */
fpos_t filePosition; /* file position of line containing name */
} tokenInfo;
typedef enum eImplementation {
IMP_DEFAULT,
IMP_ABSTRACT,
IMP_VIRTUAL,
IMP_PURE_VIRTUAL,
IMP_COUNT
} impType;
/* Describes the statement currently undergoing analysis.
*/
typedef struct sStatementInfo {
tagScope scope;
declType declaration; /* specifier associated with TOKEN_SPEC */
boolean gotName; /* was a name parsed yet? */
boolean haveQualifyingName; /* do we have a name we are considering? */
boolean gotParenName; /* was a name inside parentheses parsed yet? */
boolean gotArgs; /* was a list of parameters parsed yet? */
boolean isPointer; /* is 'name' a pointer? */
boolean inFunction; /* are we inside of a function? */
boolean assignment; /* have we handled an '='? */
boolean notVariable; /* has a variable declaration been disqualified ? */
impType implementation; /* abstract or concrete implementation? */
unsigned int tokenIndex; /* currently active token */
tokenInfo* token [(int) NumTokens];
tokenInfo* context; /* accumulated scope of current statement */
tokenInfo* blockName; /* name of current block */
memberInfo member; /* information regarding parent class/struct */
vString* parentClasses; /* parent classes */
struct sStatementInfo *parent; /* statement we are nested within */
} statementInfo;
/* Describes the type of tag being generated.
*/
typedef enum eTagType {
TAG_UNDEFINED,
TAG_CLASS, /* class name */
TAG_ENUM, /* enumeration name */
TAG_ENUMERATOR, /* enumerator (enumeration value) */
TAG_EVENT, /* event */
TAG_FIELD, /* field (Java) */
TAG_FUNCTION, /* function definition */
TAG_INTERFACE, /* interface declaration */
TAG_LOCAL, /* local variable definition */
TAG_MEMBER, /* structure, class or interface member */
TAG_METHOD, /* method declaration */
TAG_NAMESPACE, /* namespace name */
TAG_PACKAGE, /* package name */
TAG_PROGRAM, /* program name */
TAG_PROPERTY, /* property name */
TAG_PROTOTYPE, /* function prototype or declaration */
TAG_STRUCT, /* structure name */
TAG_TASK, /* task name */
TAG_TYPEDEF, /* typedef name */
TAG_UNION, /* union name */
TAG_VARIABLE, /* variable definition */
TAG_EXTERN_VAR, /* external variable declaration */
TAG_COUNT /* must be last */
} tagType;
typedef struct sParenInfo {
boolean isPointer;
boolean isParamList;
boolean isKnrParamList;
boolean isNameCandidate;
boolean invalidContents;
boolean nestedArgs;
unsigned int parameterCount;
} parenInfo;
/*
* DATA DEFINITIONS
*/
static jmp_buf Exception;
static langType Lang_c;
static langType Lang_cpp;
static langType Lang_csharp;
static langType Lang_java;
static langType Lang_vera;
static vString *Signature;
static boolean CollectingSignature;
/* Used to index into the CKinds table. */
typedef enum {
CK_UNDEFINED = -1,
CK_CLASS, CK_DEFINE, CK_ENUMERATOR, CK_FUNCTION,
CK_ENUMERATION, CK_LOCAL, CK_MEMBER, CK_NAMESPACE, CK_PROTOTYPE,
CK_STRUCT, CK_TYPEDEF, CK_UNION, CK_VARIABLE,
CK_EXTERN_VARIABLE
} cKind;
static kindOption CKinds [] = {
{ TRUE, 'c', "class", "classes"},
{ TRUE, 'd', "macro", "macro definitions"},
{ TRUE, 'e', "enumerator", "enumerators (values inside an enumeration)"},
{ TRUE, 'f', "function", "function definitions"},
{ TRUE, 'g', "enum", "enumeration names"},
{ FALSE, 'l', "local", "local variables"},
{ TRUE, 'm', "member", "class, struct, and union members"},
{ TRUE, 'n', "namespace", "namespaces"},
{ FALSE, 'p', "prototype", "function prototypes"},
{ TRUE, 's', "struct", "structure names"},
{ TRUE, 't', "typedef", "typedefs"},
{ TRUE, 'u', "union", "union names"},
{ TRUE, 'v', "variable", "variable definitions"},
{ FALSE, 'x', "externvar", "external variable declarations"},
};
typedef enum {
CSK_UNDEFINED = -1,
CSK_CLASS, CSK_DEFINE, CSK_ENUMERATOR, CSK_EVENT, CSK_FIELD,
CSK_ENUMERATION, CSK_INTERFACE, CSK_LOCAL, CSK_METHOD,
CSK_NAMESPACE, CSK_PROPERTY, CSK_STRUCT, CSK_TYPEDEF
} csharpKind;
static kindOption CsharpKinds [] = {
{ TRUE, 'c', "class", "classes"},
{ TRUE, 'd', "macro", "macro definitions"},
{ TRUE, 'e', "enumerator", "enumerators (values inside an enumeration)"},
{ TRUE, 'E', "event", "events"},
{ TRUE, 'f', "field", "fields"},
{ TRUE, 'g', "enum", "enumeration names"},
{ TRUE, 'i', "interface", "interfaces"},
{ FALSE, 'l', "local", "local variables"},
{ TRUE, 'm', "method", "methods"},
{ TRUE, 'n', "namespace", "namespaces"},
{ TRUE, 'p', "property", "properties"},
{ TRUE, 's', "struct", "structure names"},
{ TRUE, 't', "typedef", "typedefs"},
};
/* Used to index into the JavaKinds table. */
typedef enum {
JK_UNDEFINED = -1,
JK_CLASS, JK_FIELD, JK_INTERFACE, JK_LOCAL, JK_METHOD,
JK_PACKAGE, JK_ACCESS, JK_CLASS_PREFIX
} javaKind;
static kindOption JavaKinds [] = {
{ TRUE, 'c', "class", "classes"},
{ TRUE, 'f', "field", "fields"},
{ TRUE, 'i', "interface", "interfaces"},
{ FALSE, 'l', "local", "local variables"},
{ TRUE, 'm', "method", "methods"},
{ TRUE, 'p', "package", "packages"},
};
/* Used to index into the VeraKinds table. */
typedef enum {
VK_UNDEFINED = -1,
VK_CLASS, VK_DEFINE, VK_ENUMERATOR, VK_FUNCTION,
VK_ENUMERATION, VK_LOCAL, VK_MEMBER, VK_PROGRAM, VK_PROTOTYPE,
VK_TASK, VK_TYPEDEF, VK_VARIABLE,
VK_EXTERN_VARIABLE
} veraKind;
static kindOption VeraKinds [] = {
{ TRUE, 'c', "class", "classes"},
{ TRUE, 'd', "macro", "macro definitions"},
{ TRUE, 'e', "enumerator", "enumerators (values inside an enumeration)"},
{ TRUE, 'f', "function", "function definitions"},
{ TRUE, 'g', "enum", "enumeration names"},
{ FALSE, 'l', "local", "local variables"},
{ TRUE, 'm', "member", "class, struct, and union members"},
{ TRUE, 'p', "program", "programs"},
{ FALSE, 'P', "prototype", "function prototypes"},
{ TRUE, 't', "task", "tasks"},
{ TRUE, 'T', "typedef", "typedefs"},
{ TRUE, 'v', "variable", "variable definitions"},
{ FALSE, 'x', "externvar", "external variable declarations"}
};
static const keywordDesc KeywordTable [] = {
/* C++ */
/* ANSI C | C# Java */
/* | | | | Vera */
/* keyword keyword ID | | | | | */
{ "__attribute__", KEYWORD_ATTRIBUTE, { 1, 1, 1, 0, 0 } },
{ "abstract", KEYWORD_ABSTRACT, { 0, 0, 1, 1, 0 } },
{ "bad_state", KEYWORD_BAD_STATE, { 0, 0, 0, 0, 1 } },
{ "bad_trans", KEYWORD_BAD_TRANS, { 0, 0, 0, 0, 1 } },
{ "bind", KEYWORD_BIND, { 0, 0, 0, 0, 1 } },
{ "bind_var", KEYWORD_BIND_VAR, { 0, 0, 0, 0, 1 } },
{ "bit", KEYWORD_BIT, { 0, 0, 0, 0, 1 } },
{ "boolean", KEYWORD_BOOLEAN, { 0, 0, 0, 1, 0 } },
{ "byte", KEYWORD_BYTE, { 0, 0, 0, 1, 0 } },
{ "case", KEYWORD_CASE, { 1, 1, 1, 1, 0 } },
{ "catch", KEYWORD_CATCH, { 0, 1, 1, 0, 0 } },
{ "char", KEYWORD_CHAR, { 1, 1, 1, 1, 0 } },
{ "class", KEYWORD_CLASS, { 0, 1, 1, 1, 1 } },
{ "const", KEYWORD_CONST, { 1, 1, 1, 1, 0 } },
{ "constraint", KEYWORD_CONSTRAINT, { 0, 0, 0, 0, 1 } },
{ "coverage_block", KEYWORD_COVERAGE_BLOCK, { 0, 0, 0, 0, 1 } },
{ "coverage_def", KEYWORD_COVERAGE_DEF, { 0, 0, 0, 0, 1 } },
{ "do", KEYWORD_DO, { 1, 1, 1, 1, 0 } },
{ "default", KEYWORD_DEFAULT, { 1, 1, 1, 1, 0 } },
{ "delegate", KEYWORD_DELEGATE, { 0, 0, 1, 0, 0 } },
{ "double", KEYWORD_DOUBLE, { 1, 1, 1, 1, 0 } },
{ "else", KEYWORD_ELSE, { 1, 1, 0, 1, 0 } },
{ "enum", KEYWORD_ENUM, { 1, 1, 1, 0, 1 } },
{ "event", KEYWORD_EVENT, { 0, 0, 1, 0, 1 } },
{ "explicit", KEYWORD_EXPLICIT, { 0, 1, 1, 0, 0 } },
{ "extends", KEYWORD_EXTENDS, { 0, 0, 0, 1, 1 } },
{ "extern", KEYWORD_EXTERN, { 1, 1, 1, 0, 1 } },
{ "final", KEYWORD_FINAL, { 0, 0, 0, 1, 0 } },
{ "float", KEYWORD_FLOAT, { 1, 1, 1, 1, 0 } },
{ "for", KEYWORD_FOR, { 1, 1, 1, 1, 0 } },
{ "friend", KEYWORD_FRIEND, { 0, 1, 0, 0, 0 } },
{ "function", KEYWORD_FUNCTION, { 0, 0, 0, 0, 1 } },
{ "goto", KEYWORD_GOTO, { 1, 1, 1, 1, 0 } },
{ "if", KEYWORD_IF, { 1, 1, 1, 1, 0 } },
{ "implements", KEYWORD_IMPLEMENTS, { 0, 0, 0, 1, 0 } },
{ "import", KEYWORD_IMPORT, { 0, 0, 0, 1, 0 } },
{ "inline", KEYWORD_INLINE, { 0, 1, 0, 0, 0 } },
{ "inout", KEYWORD_INOUT, { 0, 0, 0, 0, 1 } },
{ "input", KEYWORD_INPUT, { 0, 0, 0, 0, 1 } },
{ "int", KEYWORD_INT, { 1, 1, 1, 1, 0 } },
{ "integer", KEYWORD_INTEGER, { 0, 0, 0, 0, 1 } },
{ "interface", KEYWORD_INTERFACE, { 0, 0, 1, 1, 1 } },
{ "internal", KEYWORD_INTERNAL, { 0, 0, 1, 0, 0 } },
{ "local", KEYWORD_LOCAL, { 0, 0, 0, 0, 1 } },
{ "long", KEYWORD_LONG, { 1, 1, 1, 1, 0 } },
{ "m_bad_state", KEYWORD_M_BAD_STATE, { 0, 0, 0, 0, 1 } },
{ "m_bad_trans", KEYWORD_M_BAD_TRANS, { 0, 0, 0, 0, 1 } },
{ "m_state", KEYWORD_M_STATE, { 0, 0, 0, 0, 1 } },
{ "m_trans", KEYWORD_M_TRANS, { 0, 0, 0, 0, 1 } },
{ "mutable", KEYWORD_MUTABLE, { 0, 1, 0, 0, 0 } },
{ "namespace", KEYWORD_NAMESPACE, { 0, 1, 1, 0, 0 } },
{ "native", KEYWORD_NATIVE, { 0, 0, 0, 1, 0 } },
{ "new", KEYWORD_NEW, { 0, 1, 1, 1, 0 } },
{ "newcov", KEYWORD_NEWCOV, { 0, 0, 0, 0, 1 } },
{ "operator", KEYWORD_OPERATOR, { 0, 1, 1, 0, 0 } },
{ "output", KEYWORD_OUTPUT, { 0, 0, 0, 0, 1 } },
{ "overload", KEYWORD_OVERLOAD, { 0, 1, 0, 0, 0 } },
{ "override", KEYWORD_OVERRIDE, { 0, 0, 1, 0, 0 } },
{ "package", KEYWORD_PACKAGE, { 0, 0, 0, 1, 0 } },
{ "packed", KEYWORD_PACKED, { 0, 0, 0, 0, 1 } },
{ "port", KEYWORD_PORT, { 0, 0, 0, 0, 1 } },
{ "private", KEYWORD_PRIVATE, { 0, 1, 1, 1, 0 } },
{ "program", KEYWORD_PROGRAM, { 0, 0, 0, 0, 1 } },
{ "protected", KEYWORD_PROTECTED, { 0, 1, 1, 1, 1 } },
{ "public", KEYWORD_PUBLIC, { 0, 1, 1, 1, 1 } },
{ "register", KEYWORD_REGISTER, { 1, 1, 0, 0, 0 } },
{ "return", KEYWORD_RETURN, { 1, 1, 1, 1, 0 } },
{ "shadow", KEYWORD_SHADOW, { 0, 0, 0, 0, 1 } },
{ "short", KEYWORD_SHORT, { 1, 1, 1, 1, 0 } },
{ "signed", KEYWORD_SIGNED, { 1, 1, 0, 0, 0 } },
{ "state", KEYWORD_STATE, { 0, 0, 0, 0, 1 } },
{ "static", KEYWORD_STATIC, { 1, 1, 1, 1, 1 } },
{ "string", KEYWORD_STRING, { 0, 0, 1, 0, 1 } },
{ "struct", KEYWORD_STRUCT, { 1, 1, 1, 0, 0 } },
{ "switch", KEYWORD_SWITCH, { 1, 1, 1, 1, 0 } },
{ "synchronized", KEYWORD_SYNCHRONIZED, { 0, 0, 0, 1, 0 } },
{ "task", KEYWORD_TASK, { 0, 0, 0, 0, 1 } },
{ "template", KEYWORD_TEMPLATE, { 0, 1, 0, 0, 0 } },
{ "this", KEYWORD_THIS, { 0, 1, 1, 1, 0 } },
{ "throw", KEYWORD_THROW, { 0, 1, 1, 1, 0 } },
{ "throws", KEYWORD_THROWS, { 0, 0, 0, 1, 0 } },
{ "trans", KEYWORD_TRANS, { 0, 0, 0, 0, 1 } },
{ "transition", KEYWORD_TRANSITION, { 0, 0, 0, 0, 1 } },
{ "transient", KEYWORD_TRANSIENT, { 0, 0, 0, 1, 0 } },
{ "try", KEYWORD_TRY, { 0, 1, 1, 0, 0 } },
{ "typedef", KEYWORD_TYPEDEF, { 1, 1, 1, 0, 1 } },
{ "typename", KEYWORD_TYPENAME, { 0, 1, 0, 0, 0 } },
{ "uint", KEYWORD_UINT, { 0, 0, 1, 0, 0 } },
{ "ulong", KEYWORD_ULONG, { 0, 0, 1, 0, 0 } },
{ "union", KEYWORD_UNION, { 1, 1, 0, 0, 0 } },
{ "unsigned", KEYWORD_UNSIGNED, { 1, 1, 1, 0, 0 } },
{ "ushort", KEYWORD_USHORT, { 0, 0, 1, 0, 0 } },
{ "using", KEYWORD_USING, { 0, 1, 1, 0, 0 } },
{ "virtual", KEYWORD_VIRTUAL, { 0, 1, 1, 0, 1 } },
{ "void", KEYWORD_VOID, { 1, 1, 1, 1, 1 } },
{ "volatile", KEYWORD_VOLATILE, { 1, 1, 1, 1, 0 } },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -