📄 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 } }, { "wchar_t", KEYWORD_WCHAR_T, { 1, 1, 1, 0, 0 } }, { "while", KEYWORD_WHILE, { 1, 1, 1, 1, 0 } }};/** FUNCTION PROTOTYPES*/static void createTags (const unsigned int nestLevel, statementInfo *const parent);/** FUNCTION DEFINITIONS*/extern boolean includingDefineTags (void){ return CKinds [CK_DEFINE].enabled;}/** Token management
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -