12f581560SJiří Techet /*
22f581560SJiří Techet * Copyright (c) 1996-2003, Darren Hiebert
32f581560SJiří Techet *
42f581560SJiří Techet * This source code is released for free distribution under the terms of the
52f581560SJiří Techet * GNU General Public License version 2 or (at your option) any later version.
62f581560SJiří Techet *
7d9071cadSJiří Techet * This module contains functions for parsing and scanning C#, D and Java
82f581560SJiří Techet * source files.
92f581560SJiří Techet */
102f581560SJiří Techet
112f581560SJiří Techet /*
122f581560SJiří Techet * INCLUDE FILES
132f581560SJiří Techet */
142f581560SJiří Techet #include "general.h" /* must always come first */
152f581560SJiří Techet
162f581560SJiří Techet #include <string.h>
172f581560SJiří Techet #include <setjmp.h>
182f581560SJiří Techet
192f581560SJiří Techet #include "debug.h"
202f581560SJiří Techet #include "entry.h"
212f581560SJiří Techet #include "cpreprocessor.h"
222f581560SJiří Techet #include "keyword.h"
232f581560SJiří Techet #include "options.h"
242f581560SJiří Techet #include "parse.h"
252f581560SJiří Techet #include "read.h"
262f581560SJiří Techet #include "routines.h"
272f581560SJiří Techet #include "selectors.h"
282f581560SJiří Techet #include "xtag.h"
292f581560SJiří Techet
302f581560SJiří Techet /*
312f581560SJiří Techet * MACROS
322f581560SJiří Techet */
332f581560SJiří Techet
342f581560SJiří Techet #define activeToken(st) ((st)->token [(int) (st)->tokenIndex])
352f581560SJiří Techet #define parentDecl(st) ((st)->parent == NULL ? \
362f581560SJiří Techet DECL_NONE : (st)->parent->declaration)
372f581560SJiří Techet #define isType(token,t) (bool) ((token)->type == (t))
382f581560SJiří Techet #define insideEnumBody(st) ((st)->parent == NULL ? false : \
392f581560SJiří Techet (bool) ((st)->parent->declaration == DECL_ENUM))
402f581560SJiří Techet #define insideAnnotationBody(st) ((st)->parent == NULL ? false : \
412f581560SJiří Techet (bool) ((st)->parent->declaration == DECL_ANNOTATION))
422f581560SJiří Techet
432f581560SJiří Techet #define isOneOf(c,s) (bool) (strchr ((s), (c)) != NULL)
442f581560SJiří Techet
452f581560SJiří Techet #define isHighChar(c) ((c) != EOF && (unsigned int)(c) >= 0xc0 && \
462f581560SJiří Techet (unsigned int)(c) <= 0xff)
472f581560SJiří Techet
482f581560SJiří Techet /*
492f581560SJiří Techet * DATA DECLARATIONS
502f581560SJiří Techet */
512f581560SJiří Techet
522f581560SJiří Techet enum { NumTokens = 3 };
532f581560SJiří Techet
542f581560SJiří Techet typedef enum eException {
552f581560SJiří Techet ExceptionNone, ExceptionEOF, ExceptionFormattingError,
562f581560SJiří Techet ExceptionBraceFormattingError
572f581560SJiří Techet } exception_t;
582f581560SJiří Techet
592f581560SJiří Techet /* Used to specify type of keyword.
602f581560SJiří Techet */
612f581560SJiří Techet enum eKeywordId {
622f581560SJiří Techet KEYWORD_ALIAS, KEYWORD_ATTRIBUTE, KEYWORD_ABSTRACT,
636d30e5b1SJiří Techet KEYWORD_BOOLEAN, KEYWORD_BYTE,
646d30e5b1SJiří Techet KEYWORD_CASE, KEYWORD_CATCH, KEYWORD_CHAR, KEYWORD_CLASS, KEYWORD_CONST,
652f581560SJiří Techet KEYWORD_DEFAULT, KEYWORD_DELEGATE, KEYWORD_DELETE, KEYWORD_DO,
662f581560SJiří Techet KEYWORD_DOUBLE,
672f581560SJiří Techet KEYWORD_ELSE, KEYWORD_ENUM, KEYWORD_EXPLICIT, KEYWORD_EXTERN,
682f581560SJiří Techet KEYWORD_EXTENDS, KEYWORD_EVENT,
692f581560SJiří Techet KEYWORD_FINAL, KEYWORD_FLOAT, KEYWORD_FOR, KEYWORD_FOREACH,
702f581560SJiří Techet KEYWORD_FRIEND, KEYWORD_FUNCTION,
712f581560SJiří Techet KEYWORD_GOTO,
722f581560SJiří Techet KEYWORD_IF, KEYWORD_IMPLEMENTS, KEYWORD_IMPORT, KEYWORD_INLINE, KEYWORD_INT,
736d30e5b1SJiří Techet KEYWORD_INOUT, KEYWORD_INTERFACE,
742f581560SJiří Techet KEYWORD_INTERNAL,
756d30e5b1SJiří Techet KEYWORD_LONG,
762f581560SJiří Techet KEYWORD_MUTABLE,
776d30e5b1SJiří Techet KEYWORD_NAMESPACE, KEYWORD_NEW, KEYWORD_NATIVE,
786d30e5b1SJiří Techet KEYWORD_OPERATOR, KEYWORD_OVERLOAD, KEYWORD_OVERRIDE,
796d30e5b1SJiří Techet KEYWORD_PACKAGE, KEYWORD_PRIVATE,
806d30e5b1SJiří Techet KEYWORD_PROTECTED, KEYWORD_PUBLIC,
812f581560SJiří Techet KEYWORD_REGISTER, KEYWORD_RETURN,
822f581560SJiří Techet KEYWORD_SHORT, KEYWORD_SIGNED, KEYWORD_STATIC, KEYWORD_STRING,
832f581560SJiří Techet KEYWORD_STRUCT, KEYWORD_SWITCH, KEYWORD_SYNCHRONIZED,
841f8ea58bSJiří Techet KEYWORD_TEMPLATE, KEYWORD_THIS, KEYWORD_THROW,
856d30e5b1SJiří Techet KEYWORD_THROWS, KEYWORD_TRANSIENT,
862f581560SJiří Techet KEYWORD_TRY, KEYWORD_TYPEDEF, KEYWORD_TYPENAME,
872f581560SJiří Techet KEYWORD_UINT, KEYWORD_ULONG, KEYWORD_UNION, KEYWORD_UNSIGNED, KEYWORD_USHORT,
882f581560SJiří Techet KEYWORD_USING,
892f581560SJiří Techet KEYWORD_VIRTUAL, KEYWORD_VOID, KEYWORD_VOLATILE,
902f581560SJiří Techet KEYWORD_WCHAR_T, KEYWORD_WHILE,
912f581560SJiří Techet KEYWORD_ALIGN, KEYWORD_ASM, KEYWORD_ASSERT, KEYWORD_AUTO,
922f581560SJiří Techet KEYWORD_BODY, KEYWORD_BOOL, KEYWORD_BREAK, KEYWORD_CAST,
932f581560SJiří Techet KEYWORD_CDOUBLE, KEYWORD_CENT, KEYWORD_CFLOAT, KEYWORD_CONTINUE,
942f581560SJiří Techet KEYWORD_CREAL, KEYWORD_DCHAR, KEYWORD_DEBUG,
952f581560SJiří Techet KEYWORD_DEPRECATED, KEYWORD_EXPORT, KEYWORD_FALSE, KEYWORD_FINALLY,
962f581560SJiří Techet KEYWORD_FOREACH_REVERSE, KEYWORD_IDOUBLE, KEYWORD_IFLOAT,
972f581560SJiří Techet KEYWORD_IN, KEYWORD_INVARIANT, KEYWORD_IREAL, KEYWORD_IS,
982f581560SJiří Techet KEYWORD_LAZY, KEYWORD_MIXIN, KEYWORD_MODULE, KEYWORD_NULL,
992f581560SJiří Techet KEYWORD_OUT, KEYWORD_PRAGMA, KEYWORD_REAL, KEYWORD_SCOPE,
1002f581560SJiří Techet KEYWORD_SUPER, KEYWORD_TRUE, KEYWORD_TYPEID, KEYWORD_TYPEOF,
1012f581560SJiří Techet KEYWORD_UBYTE, KEYWORD_UCENT, KEYWORD_UNITTEST, KEYWORD_VERSION,
1022f581560SJiří Techet KEYWORD_WCHAR, KEYWORD_WITH
1032f581560SJiří Techet };
1042f581560SJiří Techet typedef int keywordId; /* to allow KEYWORD_NONE */
1052f581560SJiří Techet
1062f581560SJiří Techet /* Used to determine whether keyword is valid for the current language and
1072f581560SJiří Techet * what its ID is.
1082f581560SJiří Techet */
1092f581560SJiří Techet typedef struct sKeywordDesc {
1102f581560SJiří Techet const char *name;
1112f581560SJiří Techet keywordId id;
1122f581560SJiří Techet short isValid [6]; /* indicates languages for which kw is valid */
1132f581560SJiří Techet } keywordDesc;
1142f581560SJiří Techet
1152f581560SJiří Techet /* Used for reporting the type of object parsed by nextToken ().
1162f581560SJiří Techet */
1172f581560SJiří Techet typedef enum eTokenType {
1182f581560SJiří Techet TOKEN_NONE, /* none */
1192f581560SJiří Techet TOKEN_ARGS, /* a parenthetical pair and its contents */
1202f581560SJiří Techet TOKEN_BRACE_CLOSE,
1212f581560SJiří Techet TOKEN_BRACE_OPEN,
1222f581560SJiří Techet TOKEN_COLON, /* the colon character */
1232f581560SJiří Techet TOKEN_COMMA, /* the comma character */
1242f581560SJiří Techet TOKEN_DOUBLE_COLON, /* double colon indicates nested-name-specifier */
1252f581560SJiří Techet TOKEN_KEYWORD,
1262f581560SJiří Techet TOKEN_NAME, /* an unknown name */
1272f581560SJiří Techet TOKEN_PACKAGE, /* a Java package name */
1282f581560SJiří Techet TOKEN_PAREN_NAME, /* a single name in parentheses */
1292f581560SJiří Techet TOKEN_SEMICOLON, /* the semicolon character */
1302f581560SJiří Techet TOKEN_SPEC, /* a storage class specifier, qualifier, type, etc. */
1312f581560SJiří Techet TOKEN_COUNT
1322f581560SJiří Techet } tokenType;
1332f581560SJiří Techet
1342f581560SJiří Techet /* This describes the scoping of the current statement.
1352f581560SJiří Techet */
1362f581560SJiří Techet typedef enum eTagScope {
1372f581560SJiří Techet SCOPE_GLOBAL, /* no storage class specified */
1382f581560SJiří Techet SCOPE_STATIC, /* static storage class */
1392f581560SJiří Techet SCOPE_EXTERN, /* external storage class */
1402f581560SJiří Techet SCOPE_FRIEND, /* declares access only */
1412f581560SJiří Techet SCOPE_TYPEDEF, /* scoping depends upon context */
1422f581560SJiří Techet SCOPE_COUNT
1432f581560SJiří Techet } tagScope;
1442f581560SJiří Techet
1452f581560SJiří Techet typedef enum eDeclaration {
1462f581560SJiří Techet DECL_NONE,
1472f581560SJiří Techet DECL_BASE, /* base type (default) */
1482f581560SJiří Techet DECL_CLASS,
1492f581560SJiří Techet DECL_ENUM,
1502f581560SJiří Techet DECL_EVENT,
1512f581560SJiří Techet DECL_FUNCTION,
1522f581560SJiří Techet DECL_FUNCTION_TEMPLATE, /* D-only */
1532f581560SJiří Techet DECL_IGNORE, /* non-taggable "declaration" */
1542f581560SJiří Techet DECL_INTERFACE,
1552f581560SJiří Techet DECL_MIXIN,
1562f581560SJiří Techet DECL_NAMESPACE,
1572f581560SJiří Techet DECL_PACKAGE,
1582f581560SJiří Techet DECL_PACKAGEREF,
1592f581560SJiří Techet DECL_PRIVATE,
1602f581560SJiří Techet DECL_PROTECTED,
1612f581560SJiří Techet DECL_PUBLIC,
1622f581560SJiří Techet DECL_STRUCT,
1632f581560SJiří Techet DECL_TEMPLATE, /* D-only */
1642f581560SJiří Techet DECL_UNION,
1652f581560SJiří Techet DECL_USING,
1662f581560SJiří Techet DECL_VERSION, /* D conditional compile */
1672f581560SJiří Techet DECL_ANNOTATION, /* Java annotation */
1682f581560SJiří Techet DECL_COUNT
1692f581560SJiří Techet } declType;
1702f581560SJiří Techet
1712f581560SJiří Techet typedef enum eVisibilityType {
1722f581560SJiří Techet ACCESS_UNDEFINED,
1732f581560SJiří Techet ACCESS_PRIVATE,
1742f581560SJiří Techet ACCESS_PROTECTED,
1752f581560SJiří Techet ACCESS_PUBLIC,
1762f581560SJiří Techet ACCESS_DEFAULT, /* Java-specific */
1772f581560SJiří Techet ACCESS_COUNT
1782f581560SJiří Techet } accessType;
1792f581560SJiří Techet
1802f581560SJiří Techet /* Information about the parent class of a member (if any).
1812f581560SJiří Techet */
1822f581560SJiří Techet typedef struct sMemberInfo {
1832f581560SJiří Techet accessType access; /* access of current statement */
1842f581560SJiří Techet accessType accessDefault; /* access default for current statement */
1852f581560SJiří Techet } memberInfo;
1862f581560SJiří Techet
1872f581560SJiří Techet typedef struct sTokenInfo {
1882f581560SJiří Techet tokenType type;
1892f581560SJiří Techet keywordId keyword;
1902f581560SJiří Techet vString* name; /* the name of the token */
1912f581560SJiří Techet unsigned long lineNumber; /* line number of tag */
1922f581560SJiří Techet MIOPos filePosition; /* file position of line containing name */
1932f581560SJiří Techet } tokenInfo;
1942f581560SJiří Techet
1952f581560SJiří Techet typedef enum eImplementation {
1962f581560SJiří Techet IMP_DEFAULT,
1972f581560SJiří Techet IMP_ABSTRACT,
1982f581560SJiří Techet IMP_VIRTUAL,
1992f581560SJiří Techet IMP_PURE_VIRTUAL,
2002f581560SJiří Techet IMP_COUNT
2012f581560SJiří Techet } impType;
2022f581560SJiří Techet
2032f581560SJiří Techet /* Describes the statement currently undergoing analysis.
2042f581560SJiří Techet */
2052f581560SJiří Techet typedef struct sStatementInfo {
2062f581560SJiří Techet tagScope scope;
2072f581560SJiří Techet declType declaration; /* specifier associated with TOKEN_SPEC */
2082f581560SJiří Techet bool gotName; /* was a name parsed yet? */
2092f581560SJiří Techet bool haveQualifyingName; /* do we have a name we are considering? */
2102f581560SJiří Techet bool gotParenName; /* was a name inside parentheses parsed yet? */
2112f581560SJiří Techet bool gotArgs; /* was a list of parameters parsed yet? */
2122f581560SJiří Techet bool isPointer; /* is 'name' a pointer? */
2132f581560SJiří Techet bool inFunction; /* are we inside of a function? */
2142f581560SJiří Techet bool assignment; /* have we handled an '='? */
2152f581560SJiří Techet bool notVariable; /* has a variable declaration been disqualified ? */
2162f581560SJiří Techet impType implementation; /* abstract or concrete implementation? */
2172f581560SJiří Techet unsigned int tokenIndex; /* currently active token */
2182f581560SJiří Techet tokenInfo* token [(int) NumTokens];
2192f581560SJiří Techet tokenInfo* context; /* accumulated scope of current statement */
2202f581560SJiří Techet tokenInfo* blockName; /* name of current block */
2212f581560SJiří Techet memberInfo member; /* information regarding parent class/struct */
2222f581560SJiří Techet vString* parentClasses; /* parent classes */
2232f581560SJiří Techet struct sStatementInfo *parent; /* statement we are nested within */
2242f581560SJiří Techet } statementInfo;
2252f581560SJiří Techet
2262f581560SJiří Techet /* Describes the type of tag being generated.
2272f581560SJiří Techet */
2282f581560SJiří Techet typedef enum eTagType {
2292f581560SJiří Techet TAG_UNDEFINED,
2302f581560SJiří Techet TAG_CLASS, /* class name */
2312f581560SJiří Techet TAG_ENUM, /* enumeration name */
2322f581560SJiří Techet TAG_ENUMERATOR, /* enumerator (enumeration value) */
2332f581560SJiří Techet TAG_EVENT, /* event */
2342f581560SJiří Techet TAG_FIELD, /* field (Java) */
2352f581560SJiří Techet TAG_FUNCTION, /* function definition */
2362f581560SJiří Techet TAG_INTERFACE, /* interface declaration */
2372f581560SJiří Techet TAG_LOCAL, /* local variable definition */
2382f581560SJiří Techet TAG_MEMBER, /* structure, class or interface member */
2392f581560SJiří Techet TAG_METHOD, /* method declaration */
2402f581560SJiří Techet TAG_MIXIN, /* D mixin */
2412f581560SJiří Techet TAG_NAMESPACE, /* namespace name */
2422f581560SJiří Techet TAG_PACKAGE, /* package name / D module name */
2432f581560SJiří Techet TAG_PACKAGEREF, /* referenced package name */
2442f581560SJiří Techet TAG_PROPERTY, /* property name */
2452f581560SJiří Techet TAG_PROTOTYPE, /* function prototype or declaration */
2462f581560SJiří Techet TAG_STRUCT, /* structure name */
2472f581560SJiří Techet TAG_TYPEDEF, /* typedef name / D alias name */
2482f581560SJiří Techet TAG_TEMPLATE, /* D template name */
2492f581560SJiří Techet TAG_UNION, /* union name */
2502f581560SJiří Techet TAG_VARIABLE, /* variable definition */
2512f581560SJiří Techet TAG_EXTERN_VAR, /* external variable declaration */
2522f581560SJiří Techet TAG_VERSION, /* conditional template compilation */
2532f581560SJiří Techet TAG_LABEL, /* goto label */
2542f581560SJiří Techet TAG_ANNOTATION, /* Java annotation definition */
2552f581560SJiří Techet TAG_COUNT /* must be last */
2562f581560SJiří Techet } tagType;
2572f581560SJiří Techet
2582f581560SJiří Techet typedef struct sParenInfo {
2592f581560SJiří Techet bool isPointer;
2602f581560SJiří Techet bool isParamList;
2612f581560SJiří Techet bool isNameCandidate;
2622f581560SJiří Techet bool invalidContents;
2632f581560SJiří Techet bool nestedArgs;
2642f581560SJiří Techet unsigned int parameterCount;
2652f581560SJiří Techet } parenInfo;
2662f581560SJiří Techet
2672f581560SJiří Techet /*
2682f581560SJiří Techet * DATA DEFINITIONS
2692f581560SJiří Techet */
2702f581560SJiří Techet
2712f581560SJiří Techet static jmp_buf Exception;
2722f581560SJiří Techet
2732f581560SJiří Techet static langType Lang_csharp;
2742f581560SJiří Techet static langType Lang_d;
2752f581560SJiří Techet static langType Lang_java;
2762f581560SJiří Techet static vString *Signature;
2772f581560SJiří Techet static bool CollectingSignature;
2782f581560SJiří Techet
2792f581560SJiří Techet /* Number used to uniquely identify anonymous structs and unions. */
2802f581560SJiří Techet static int AnonymousID = 0;
2812f581560SJiří Techet
2822f581560SJiří Techet #define COMMONK_UNDEFINED -1
2832f581560SJiří Techet
2842f581560SJiří Techet
2852f581560SJiří Techet typedef enum {
2862f581560SJiří Techet CSK_UNDEFINED = COMMONK_UNDEFINED,
2872f581560SJiří Techet CSK_CLASS, CSK_DEFINE, CSK_ENUMERATOR, CSK_EVENT, CSK_FIELD,
2882f581560SJiří Techet CSK_ENUMERATION, CSK_INTERFACE, CSK_LOCAL, CSK_METHOD,
2892f581560SJiří Techet CSK_NAMESPACE, CSK_PROPERTY, CSK_STRUCT, CSK_TYPEDEF
2902f581560SJiří Techet } csharpKind;
2912f581560SJiří Techet
2922f581560SJiří Techet static kindDefinition CsharpKinds [] = {
2932f581560SJiří Techet { true, 'c', "class", "classes"},
2942f581560SJiří Techet { true, 'd', "macro", "macro definitions"},
2952f581560SJiří Techet { true, 'e', "enumerator", "enumerators (values inside an enumeration)"},
2962f581560SJiří Techet { true, 'E', "event", "events"},
2972f581560SJiří Techet { true, 'f', "field", "fields"},
2982f581560SJiří Techet { true, 'g', "enum", "enumeration names"},
2992f581560SJiří Techet { true, 'i', "interface", "interfaces"},
3002f581560SJiří Techet { false, 'l', "local", "local variables"},
3012f581560SJiří Techet { true, 'm', "method", "methods"},
3022f581560SJiří Techet { true, 'n', "namespace", "namespaces"},
3032f581560SJiří Techet { true, 'p', "property", "properties"},
3042f581560SJiří Techet { true, 's', "struct", "structure names"},
3052f581560SJiří Techet { true, 't', "typedef", "typedefs"},
3062f581560SJiří Techet };
3072f581560SJiří Techet
3082f581560SJiří Techet typedef enum
3092f581560SJiří Techet {
3102f581560SJiří Techet DK_UNDEFINED = COMMONK_UNDEFINED,
3112f581560SJiří Techet DK_ALIAS, DK_CLASS, DK_ENUMERATION, DK_ENUMERATOR, DK_EXTERN_VARIABLE, DK_FUNCTION,
3122f581560SJiří Techet DK_INTERFACE, DK_LOCAL, DK_MEMBER, DK_MIXIN, DK_MODULE, DK_NAMESPACE,
3132f581560SJiří Techet DK_PROTOTYPE, DK_STRUCT, DK_TEMPLATE, DK_UNION,
3142f581560SJiří Techet DK_VARIABLE, DK_VERSION
3152f581560SJiří Techet } dKind;
3162f581560SJiří Techet
3172f581560SJiří Techet static kindDefinition DKinds [] = {
3182f581560SJiří Techet { true, 'a', "alias", "aliases"},
3192f581560SJiří Techet { true, 'c', "class", "classes"},
3202f581560SJiří Techet { true, 'g', "enum", "enumeration names"},
3212f581560SJiří Techet { true, 'e', "enumerator", "enumerators (values inside an enumeration)"},
3222f581560SJiří Techet { false, 'x', "externvar", "external variable declarations"},
3232f581560SJiří Techet { true, 'f', "function", "function definitions"},
3242f581560SJiří Techet { true, 'i', "interface", "interfaces"},
3252f581560SJiří Techet { false, 'l', "local", "local variables"},
3262f581560SJiří Techet { true, 'm', "member", "class, struct, and union members"},
3272f581560SJiří Techet { true, 'X', "mixin", "mixins"},
3282f581560SJiří Techet { true, 'M', "module", "modules"},
3292f581560SJiří Techet { true, 'n', "namespace", "namespaces"},
3302f581560SJiří Techet { false, 'p', "prototype", "function prototypes"},
3312f581560SJiří Techet { true, 's', "struct", "structure names"},
3322f581560SJiří Techet { true, 'T', "template", "templates"},
3332f581560SJiří Techet { true, 'u', "union", "union names"},
3342f581560SJiří Techet { true, 'v', "variable", "variable definitions"},
3352f581560SJiří Techet { true, 'V', "version", "version statements"}
3362f581560SJiří Techet };
3372f581560SJiří Techet
3382f581560SJiří Techet /* Used to index into the JavaKinds table. */
3392f581560SJiří Techet typedef enum {
3402f581560SJiří Techet JAVAR_PACKAGE_IMPORTED,
3412f581560SJiří Techet } javaPackageRole;
3422f581560SJiří Techet
3432f581560SJiří Techet static roleDefinition JavaPackageRoles [] = {
3442f581560SJiří Techet { true, "imported", "imported package"},
3452f581560SJiří Techet };
3462f581560SJiří Techet
3472f581560SJiří Techet typedef enum {
3482f581560SJiří Techet JK_UNDEFINED = COMMONK_UNDEFINED,
3492f581560SJiří Techet JK_ANNOTATION, JK_CLASS, JK_ENUM_CONSTANT, JK_FIELD, JK_ENUM, JK_INTERFACE,
3502f581560SJiří Techet JK_LOCAL, JK_METHOD, JK_PACKAGE, JK_ACCESS, JK_CLASS_PREFIX
3512f581560SJiří Techet } javaKind;
3522f581560SJiří Techet
3532f581560SJiří Techet static kindDefinition JavaKinds [] = {
3542f581560SJiří Techet { true, 'a', "annotation", "annotation declarations" },
3552f581560SJiří Techet { true, 'c', "class", "classes"},
3562f581560SJiří Techet { true, 'e', "enumConstant", "enum constants"},
3572f581560SJiří Techet { true, 'f', "field", "fields"},
3582f581560SJiří Techet { true, 'g', "enum", "enum types"},
3592f581560SJiří Techet { true, 'i', "interface", "interfaces"},
3602f581560SJiří Techet { false, 'l', "local", "local variables"},
3612f581560SJiří Techet { true, 'm', "method", "methods"},
3622f581560SJiří Techet { true, 'p', "package", "packages",
3632f581560SJiří Techet .referenceOnly = false, ATTACH_ROLES(JavaPackageRoles)},
3642f581560SJiří Techet };
3652f581560SJiří Techet
3662f581560SJiří Techet static const keywordDesc KeywordTable [] = {
3676afc0c60SJiří Techet /* D */
3686afc0c60SJiří Techet /* C# | Java */
3691f8ea58bSJiří Techet /* | | | */
3701f8ea58bSJiří Techet /* keyword keyword ID | | */
3711f8ea58bSJiří Techet { "__attribute__", KEYWORD_ATTRIBUTE, { 1, 1, 0 } },
3721f8ea58bSJiří Techet { "abstract", KEYWORD_ABSTRACT, { 1, 1, 1 } },
3731f8ea58bSJiří Techet { "alias", KEYWORD_ALIAS, { 0, 1, 0 } },
3741f8ea58bSJiří Techet { "align", KEYWORD_ALIGN, { 0, 1, 0 } },
3751f8ea58bSJiří Techet { "asm", KEYWORD_ASM, { 0, 1, 0 } },
3761f8ea58bSJiří Techet { "assert", KEYWORD_ASSERT, { 0, 1, 0 } },
3771f8ea58bSJiří Techet { "auto", KEYWORD_AUTO, { 0, 1, 0 } },
3781f8ea58bSJiří Techet { "body", KEYWORD_BODY, { 0, 1, 0 } },
3791f8ea58bSJiří Techet { "bool", KEYWORD_BOOL, { 0, 1, 0 } },
3801f8ea58bSJiří Techet { "boolean", KEYWORD_BOOLEAN, { 0, 0, 1 } },
3811f8ea58bSJiří Techet { "break", KEYWORD_BREAK, { 0, 1, 0 } },
3821f8ea58bSJiří Techet { "byte", KEYWORD_BYTE, { 0, 1, 1 } },
3831f8ea58bSJiří Techet { "case", KEYWORD_CASE, { 1, 1, 1 } },
3841f8ea58bSJiří Techet { "cast", KEYWORD_CAST, { 0, 1, 0 } },
3851f8ea58bSJiří Techet { "catch", KEYWORD_CATCH, { 1, 1, 1 } },
3861f8ea58bSJiří Techet { "cdouble", KEYWORD_CDOUBLE, { 0, 1, 0 } },
3871f8ea58bSJiří Techet { "cent", KEYWORD_CENT, { 0, 1, 0 } },
3881f8ea58bSJiří Techet { "cfloat", KEYWORD_CFLOAT, { 0, 1, 0 } },
3891f8ea58bSJiří Techet { "char", KEYWORD_CHAR, { 1, 1, 1 } },
3901f8ea58bSJiří Techet { "class", KEYWORD_CLASS, { 1, 1, 1 } },
3911f8ea58bSJiří Techet { "const", KEYWORD_CONST, { 1, 1, 1 } },
3921f8ea58bSJiří Techet { "continue", KEYWORD_CONTINUE, { 0, 1, 0 } },
3931f8ea58bSJiří Techet { "creal", KEYWORD_CREAL, { 0, 1, 0 } },
3941f8ea58bSJiří Techet { "dchar", KEYWORD_DCHAR, { 0, 1, 0 } },
3951f8ea58bSJiří Techet { "debug", KEYWORD_DEBUG, { 0, 1, 0 } },
3961f8ea58bSJiří Techet { "default", KEYWORD_DEFAULT, { 1, 1, 1 } },
3971f8ea58bSJiří Techet { "delegate", KEYWORD_DELEGATE, { 1, 1, 0 } },
3981f8ea58bSJiří Techet { "delete", KEYWORD_DELETE, { 0, 1, 0 } },
3991f8ea58bSJiří Techet { "deprecated", KEYWORD_DEPRECATED, { 0, 1, 0 } },
4001f8ea58bSJiří Techet { "do", KEYWORD_DO, { 1, 1, 1 } },
4011f8ea58bSJiří Techet { "double", KEYWORD_DOUBLE, { 1, 1, 1 } },
4021f8ea58bSJiří Techet { "else", KEYWORD_ELSE, { 1, 1, 1 } },
4031f8ea58bSJiří Techet { "enum", KEYWORD_ENUM, { 1, 1, 1 } },
4041f8ea58bSJiří Techet { "event", KEYWORD_EVENT, { 1, 0, 0 } },
4051f8ea58bSJiří Techet { "explicit", KEYWORD_EXPLICIT, { 1, 1, 0 } },
4061f8ea58bSJiří Techet { "export", KEYWORD_EXPORT, { 0, 1, 0 } },
4071f8ea58bSJiří Techet { "extends", KEYWORD_EXTENDS, { 0, 0, 1 } },
4081f8ea58bSJiří Techet { "extern", KEYWORD_EXTERN, { 1, 1, 0 } },
4091f8ea58bSJiří Techet { "false", KEYWORD_FALSE, { 0, 1, 0 } },
4101f8ea58bSJiří Techet { "final", KEYWORD_FINAL, { 0, 1, 1 } },
4111f8ea58bSJiří Techet { "finally", KEYWORD_FINALLY, { 0, 1, 0 } },
4121f8ea58bSJiří Techet { "float", KEYWORD_FLOAT, { 1, 1, 1 } },
4131f8ea58bSJiří Techet { "for", KEYWORD_FOR, { 1, 1, 1 } },
4141f8ea58bSJiří Techet { "foreach", KEYWORD_FOREACH, { 1, 1, 0 } },
4151f8ea58bSJiří Techet { "foreach_reverse", KEYWORD_FOREACH_REVERSE, { 0, 1, 0 } },
4161f8ea58bSJiří Techet { "friend", KEYWORD_FRIEND, { 0, 1, 0 } },
4171f8ea58bSJiří Techet { "function", KEYWORD_FUNCTION, { 0, 1, 0 } },
4181f8ea58bSJiří Techet { "goto", KEYWORD_GOTO, { 1, 1, 1 } },
4191f8ea58bSJiří Techet { "idouble", KEYWORD_IDOUBLE, { 0, 1, 0 } },
4201f8ea58bSJiří Techet { "if", KEYWORD_IF, { 1, 1, 1 } },
4211f8ea58bSJiří Techet { "ifloat", KEYWORD_IFLOAT, { 0, 1, 0 } },
4221f8ea58bSJiří Techet { "implements", KEYWORD_IMPLEMENTS, { 0, 0, 1 } },
4231f8ea58bSJiří Techet { "import", KEYWORD_IMPORT, { 0, 1, 1 } },
4241f8ea58bSJiří Techet { "in", KEYWORD_IN, { 0, 1, 0 } },
4251f8ea58bSJiří Techet { "inline", KEYWORD_INLINE, { 0, 1, 0 } },
4261f8ea58bSJiří Techet { "inout", KEYWORD_INOUT, { 0, 1, 0 } },
4271f8ea58bSJiří Techet { "int", KEYWORD_INT, { 1, 1, 1 } },
4281f8ea58bSJiří Techet { "interface", KEYWORD_INTERFACE, { 1, 1, 1 } },
4291f8ea58bSJiří Techet { "internal", KEYWORD_INTERNAL, { 1, 0, 0 } },
4301f8ea58bSJiří Techet { "invariant", KEYWORD_INVARIANT, { 0, 1, 0 } },
4311f8ea58bSJiří Techet { "ireal", KEYWORD_IREAL, { 0, 1, 0 } },
4321f8ea58bSJiří Techet { "is", KEYWORD_IS, { 0, 1, 0 } },
4331f8ea58bSJiří Techet { "lazy", KEYWORD_LAZY, { 0, 1, 0 } },
4341f8ea58bSJiří Techet { "long", KEYWORD_LONG, { 1, 1, 1 } },
4351f8ea58bSJiří Techet { "mixin", KEYWORD_MIXIN, { 0, 1, 0 } },
4361f8ea58bSJiří Techet { "module", KEYWORD_MODULE, { 0, 1, 0 } },
4371f8ea58bSJiří Techet { "mutable", KEYWORD_MUTABLE, { 0, 1, 0 } },
4381f8ea58bSJiří Techet { "namespace", KEYWORD_NAMESPACE, { 1, 1, 0 } },
4391f8ea58bSJiří Techet { "native", KEYWORD_NATIVE, { 0, 0, 1 } },
4401f8ea58bSJiří Techet { "new", KEYWORD_NEW, { 1, 1, 1 } },
4411f8ea58bSJiří Techet { "null", KEYWORD_NULL, { 0, 1, 0 } },
4421f8ea58bSJiří Techet { "operator", KEYWORD_OPERATOR, { 1, 1, 0 } },
4431f8ea58bSJiří Techet { "out", KEYWORD_OUT, { 0, 1, 0 } },
4441f8ea58bSJiří Techet { "overload", KEYWORD_OVERLOAD, { 0, 1, 0 } },
4451f8ea58bSJiří Techet { "override", KEYWORD_OVERRIDE, { 1, 1, 0 } },
4461f8ea58bSJiří Techet { "package", KEYWORD_PACKAGE, { 0, 1, 1 } },
4471f8ea58bSJiří Techet { "pragma", KEYWORD_PRAGMA, { 0, 1, 0 } },
4481f8ea58bSJiří Techet { "private", KEYWORD_PRIVATE, { 1, 1, 1 } },
4491f8ea58bSJiří Techet { "protected", KEYWORD_PROTECTED, { 1, 1, 1 } },
4501f8ea58bSJiří Techet { "public", KEYWORD_PUBLIC, { 1, 1, 1 } },
4511f8ea58bSJiří Techet { "real", KEYWORD_REAL, { 0, 1, 0 } },
4521f8ea58bSJiří Techet { "register", KEYWORD_REGISTER, { 0, 1, 0 } },
4531f8ea58bSJiří Techet { "return", KEYWORD_RETURN, { 1, 1, 1 } },
4541f8ea58bSJiří Techet { "scope", KEYWORD_SCOPE, { 0, 1, 0 } },
4551f8ea58bSJiří Techet { "short", KEYWORD_SHORT, { 1, 1, 1 } },
4561f8ea58bSJiří Techet { "signed", KEYWORD_SIGNED, { 0, 1, 0 } },
4571f8ea58bSJiří Techet { "static", KEYWORD_STATIC, { 1, 1, 1 } },
4581f8ea58bSJiří Techet { "string", KEYWORD_STRING, { 1, 0, 0 } },
4591f8ea58bSJiří Techet { "struct", KEYWORD_STRUCT, { 1, 1, 0 } },
4601f8ea58bSJiří Techet { "super", KEYWORD_SUPER, { 0, 1, 0 } },
4611f8ea58bSJiří Techet { "switch", KEYWORD_SWITCH, { 1, 1, 1 } },
4621f8ea58bSJiří Techet { "synchronized", KEYWORD_SYNCHRONIZED, { 0, 1, 1 } },
4631f8ea58bSJiří Techet { "template", KEYWORD_TEMPLATE, { 0, 1, 0 } },
4641f8ea58bSJiří Techet { "this", KEYWORD_THIS, { 1, 0, 1 } },
4651f8ea58bSJiří Techet { "throw", KEYWORD_THROW, { 1, 1, 1 } },
4661f8ea58bSJiří Techet { "throws", KEYWORD_THROWS, { 0, 0, 1 } },
4671f8ea58bSJiří Techet { "transient", KEYWORD_TRANSIENT, { 0, 0, 1 } },
4681f8ea58bSJiří Techet { "true", KEYWORD_TRUE, { 0, 1, 0 } },
4691f8ea58bSJiří Techet { "try", KEYWORD_TRY, { 1, 1, 0 } },
4701f8ea58bSJiří Techet { "typedef", KEYWORD_TYPEDEF, { 1, 1, 0 } },
4711f8ea58bSJiří Techet { "typeid", KEYWORD_TYPEID, { 0, 1, 0 } },
4721f8ea58bSJiří Techet { "typename", KEYWORD_TYPENAME, { 0, 1, 0 } },
4731f8ea58bSJiří Techet { "typeof", KEYWORD_TYPEOF, { 0, 1, 0 } },
4741f8ea58bSJiří Techet { "ubyte", KEYWORD_UBYTE, { 0, 1, 0 } },
4751f8ea58bSJiří Techet { "ucent", KEYWORD_UCENT, { 0, 1, 0 } },
4761f8ea58bSJiří Techet { "uint", KEYWORD_UINT, { 1, 1, 0 } },
4771f8ea58bSJiří Techet { "ulong", KEYWORD_ULONG, { 1, 1, 0 } },
4781f8ea58bSJiří Techet { "union", KEYWORD_UNION, { 0, 1, 0 } },
4791f8ea58bSJiří Techet { "unittest", KEYWORD_UNITTEST, { 0, 1, 0 } },
4801f8ea58bSJiří Techet { "unsigned", KEYWORD_UNSIGNED, { 1, 1, 0 } },
4811f8ea58bSJiří Techet { "ushort", KEYWORD_USHORT, { 1, 1, 0 } },
4821f8ea58bSJiří Techet { "using", KEYWORD_USING, { 1, 1, 0 } },
4831f8ea58bSJiří Techet { "version", KEYWORD_VERSION, { 0, 1, 0 } },
4841f8ea58bSJiří Techet { "virtual", KEYWORD_VIRTUAL, { 1, 1, 0 } },
4851f8ea58bSJiří Techet { "void", KEYWORD_VOID, { 1, 1, 1 } },
4861f8ea58bSJiří Techet { "volatile", KEYWORD_VOLATILE, { 1, 1, 1 } },
4871f8ea58bSJiří Techet { "wchar", KEYWORD_WCHAR, { 0, 1, 0 } },
4881f8ea58bSJiří Techet { "wchar_t", KEYWORD_WCHAR_T, { 1, 0, 0 } },
4891f8ea58bSJiří Techet { "while", KEYWORD_WHILE, { 1, 1, 1 } },
4901f8ea58bSJiří Techet { "with", KEYWORD_WITH, { 0, 1, 0 } },
4912f581560SJiří Techet };
4922f581560SJiří Techet
4932f581560SJiří Techet /*
4942f581560SJiří Techet * FUNCTION PROTOTYPES
4952f581560SJiří Techet */
4962f581560SJiří Techet static void createTags (const unsigned int nestLevel, statementInfo *const parent);
4972f581560SJiří Techet
4982f581560SJiří Techet /*
4992f581560SJiří Techet * FUNCTION DEFINITIONS
5002f581560SJiří Techet */
5012f581560SJiří Techet
5022f581560SJiří Techet /*
5032f581560SJiří Techet * Token management
5042f581560SJiří Techet */
5052f581560SJiří Techet
initToken(tokenInfo * const token)5062f581560SJiří Techet static void initToken (tokenInfo* const token)
5072f581560SJiří Techet {
5082f581560SJiří Techet token->type = TOKEN_NONE;
5092f581560SJiří Techet token->keyword = KEYWORD_NONE;
5102f581560SJiří Techet token->lineNumber = getInputLineNumber ();
5112f581560SJiří Techet token->filePosition = getInputFilePosition ();
5122f581560SJiří Techet vStringClear (token->name);
5132f581560SJiří Techet }
5142f581560SJiří Techet
advanceToken(statementInfo * const st)5152f581560SJiří Techet static void advanceToken (statementInfo* const st)
5162f581560SJiří Techet {
5172f581560SJiří Techet if (st->tokenIndex >= (unsigned int) NumTokens - 1)
5182f581560SJiří Techet st->tokenIndex = 0;
5192f581560SJiří Techet else
5202f581560SJiří Techet ++st->tokenIndex;
5212f581560SJiří Techet initToken (st->token [st->tokenIndex]);
5222f581560SJiří Techet }
5232f581560SJiří Techet
prevToken(const statementInfo * const st,unsigned int n)5242f581560SJiří Techet static tokenInfo *prevToken (const statementInfo *const st, unsigned int n)
5252f581560SJiří Techet {
5262f581560SJiří Techet unsigned int tokenIndex;
5272f581560SJiří Techet unsigned int num = (unsigned int) NumTokens;
5282f581560SJiří Techet Assert (n < num);
5292f581560SJiří Techet tokenIndex = (st->tokenIndex + num - n) % num;
5302f581560SJiří Techet return st->token [tokenIndex];
5312f581560SJiří Techet }
5322f581560SJiří Techet
setToken(statementInfo * const st,const tokenType type)5332f581560SJiří Techet static void setToken (statementInfo *const st, const tokenType type)
5342f581560SJiří Techet {
5352f581560SJiří Techet tokenInfo *token;
5362f581560SJiří Techet token = activeToken (st);
5372f581560SJiří Techet initToken (token);
5382f581560SJiří Techet token->type = type;
5392f581560SJiří Techet }
5402f581560SJiří Techet
newToken(void)5412f581560SJiří Techet static tokenInfo *newToken (void)
5422f581560SJiří Techet {
5432f581560SJiří Techet tokenInfo *const token = xMalloc (1, tokenInfo);
5442f581560SJiří Techet token->name = vStringNew ();
5452f581560SJiří Techet initToken (token);
5462f581560SJiří Techet return token;
5472f581560SJiří Techet }
5482f581560SJiří Techet
deleteToken(tokenInfo * const token)5492f581560SJiří Techet static void deleteToken (tokenInfo *const token)
5502f581560SJiří Techet {
5512f581560SJiří Techet if (token != NULL)
5522f581560SJiří Techet {
5532f581560SJiří Techet vStringDelete (token->name);
5542f581560SJiří Techet eFree (token);
5552f581560SJiří Techet }
5562f581560SJiří Techet }
5572f581560SJiří Techet
accessString(const accessType access)5582f581560SJiří Techet static const char *accessString (const accessType access)
5592f581560SJiří Techet {
5602f581560SJiří Techet static const char *const names [] = {
5616d30e5b1SJiří Techet "?", "private", "protected", "public", "default"
5622f581560SJiří Techet };
5632f581560SJiří Techet Assert (ARRAY_SIZE (names) == ACCESS_COUNT);
5642f581560SJiří Techet Assert ((int) access < ACCESS_COUNT);
5652f581560SJiří Techet return names [(int) access];
5662f581560SJiří Techet }
5672f581560SJiří Techet
implementationString(const impType imp)5682f581560SJiří Techet static const char *implementationString (const impType imp)
5692f581560SJiří Techet {
5702f581560SJiří Techet static const char *const names [] ={
5712f581560SJiří Techet "?", "abstract", "virtual", "pure virtual"
5722f581560SJiří Techet };
5732f581560SJiří Techet Assert (ARRAY_SIZE (names) == IMP_COUNT);
5742f581560SJiří Techet Assert ((int) imp < IMP_COUNT);
5752f581560SJiří Techet return names [(int) imp];
5762f581560SJiří Techet }
5772f581560SJiří Techet
5782f581560SJiří Techet /*
5792f581560SJiří Techet * Debugging functions
5802f581560SJiří Techet */
5812f581560SJiří Techet
5822f581560SJiří Techet #ifdef DEBUG
5832f581560SJiří Techet
5842f581560SJiří Techet #define boolString(c) ((c) ? "true" : "false")
5852f581560SJiří Techet
tokenString(const tokenType type)5862f581560SJiří Techet static const char *tokenString (const tokenType type)
5872f581560SJiří Techet {
5882f581560SJiří Techet static const char *const names [] = {
5892f581560SJiří Techet "none", "args", "}", "{", "colon", "comma", "double colon", "keyword",
5902f581560SJiří Techet "name", "package", "paren-name", "semicolon", "specifier"
5912f581560SJiří Techet };
5922f581560SJiří Techet Assert (ARRAY_SIZE (names) == TOKEN_COUNT);
5932f581560SJiří Techet Assert ((int) type < TOKEN_COUNT);
5942f581560SJiří Techet return names [(int) type];
5952f581560SJiří Techet }
5962f581560SJiří Techet
scopeString(const tagScope scope)5972f581560SJiří Techet static const char *scopeString (const tagScope scope)
5982f581560SJiří Techet {
5992f581560SJiří Techet static const char *const names [] = {
6002f581560SJiří Techet "global", "static", "extern", "friend", "typedef"
6012f581560SJiří Techet };
6022f581560SJiří Techet Assert (ARRAY_SIZE (names) == SCOPE_COUNT);
6032f581560SJiří Techet Assert ((int) scope < SCOPE_COUNT);
6042f581560SJiří Techet return names [(int) scope];
6052f581560SJiří Techet }
6062f581560SJiří Techet
declString(const declType declaration)6072f581560SJiří Techet static const char *declString (const declType declaration)
6082f581560SJiří Techet {
6092f581560SJiří Techet static const char *const names [] = {
6102f581560SJiří Techet "?", "base", "class", "enum", "event", "function", "function template",
6119f85e64cSJiří Techet "ignore", "interface", "mixin", "namespace", "package", "package ref",
6126d30e5b1SJiří Techet "private", "protected", "public", "struct", "template",
6132f581560SJiří Techet "union", "using", "version", "annotation"
6142f581560SJiří Techet };
6152f581560SJiří Techet Assert (ARRAY_SIZE (names) == DECL_COUNT);
6162f581560SJiří Techet Assert ((int) declaration < DECL_COUNT);
6172f581560SJiří Techet return names [(int) declaration];
6182f581560SJiří Techet }
6192f581560SJiří Techet
keywordString(const keywordId keyword)6202f581560SJiří Techet static const char *keywordString (const keywordId keyword)
6212f581560SJiří Techet {
6222f581560SJiří Techet const size_t count = ARRAY_SIZE (KeywordTable);
6232f581560SJiří Techet const char *name = "none";
6242f581560SJiří Techet size_t i;
6252f581560SJiří Techet for (i = 0 ; i < count ; ++i)
6262f581560SJiří Techet {
6272f581560SJiří Techet const keywordDesc *p = &KeywordTable [i];
6282f581560SJiří Techet if (p->id == keyword)
6292f581560SJiří Techet {
6302f581560SJiří Techet name = p->name;
6312f581560SJiří Techet break;
6322f581560SJiří Techet }
6332f581560SJiří Techet }
6342f581560SJiří Techet return name;
6352f581560SJiří Techet }
6362f581560SJiří Techet
pt(tokenInfo * const token)6372f581560SJiří Techet static void CTAGS_ATTR_UNUSED pt (tokenInfo *const token)
6382f581560SJiří Techet {
6392f581560SJiří Techet if (isType (token, TOKEN_NAME))
6402f581560SJiří Techet printf ("type: %-12s: %-13s line: %lu\n",
6412f581560SJiří Techet tokenString (token->type), vStringValue (token->name),
6422f581560SJiří Techet token->lineNumber);
6432f581560SJiří Techet else if (isType (token, TOKEN_KEYWORD))
6442f581560SJiří Techet printf ("type: %-12s: %-13s line: %lu\n",
6452f581560SJiří Techet tokenString (token->type), keywordString (token->keyword),
6462f581560SJiří Techet token->lineNumber);
6472f581560SJiří Techet else
6482f581560SJiří Techet printf ("type: %-12s line: %lu\n",
6492f581560SJiří Techet tokenString (token->type), token->lineNumber);
6502f581560SJiří Techet }
6512f581560SJiří Techet
ps(statementInfo * const st)6522f581560SJiří Techet static void CTAGS_ATTR_UNUSED ps (statementInfo *const st)
6532f581560SJiří Techet {
6542f581560SJiří Techet #define P "[%-7u]"
6552f581560SJiří Techet static unsigned int id = 0;
6562f581560SJiří Techet unsigned int i;
6572f581560SJiří Techet printf (P"scope: %s decl: %s gotName: %s gotParenName: %s\n", id,
6582f581560SJiří Techet scopeString (st->scope), declString (st->declaration),
6592f581560SJiří Techet boolString (st->gotName), boolString (st->gotParenName));
6602f581560SJiří Techet printf (P"haveQualifyingName: %s\n", id, boolString (st->haveQualifyingName));
6612f581560SJiří Techet printf (P"access: %s default: %s\n", id, accessString (st->member.access),
6622f581560SJiří Techet accessString (st->member.accessDefault));
6632f581560SJiří Techet printf (P"token : ", id);
6642f581560SJiří Techet pt (activeToken (st));
6652f581560SJiří Techet for (i = 1 ; i < (unsigned int) NumTokens ; ++i)
6662f581560SJiří Techet {
6672f581560SJiří Techet printf (P"prev %u : ", id, i);
6682f581560SJiří Techet pt (prevToken (st, i));
6692f581560SJiří Techet }
6702f581560SJiří Techet printf (P"context: ", id);
6712f581560SJiří Techet pt (st->context);
6722f581560SJiří Techet id++;
6732f581560SJiří Techet #undef P
6742f581560SJiří Techet }
6752f581560SJiří Techet
6762f581560SJiří Techet #endif
6772f581560SJiří Techet
6782f581560SJiří Techet /*
6792f581560SJiří Techet * Statement management
6802f581560SJiří Techet */
6812f581560SJiří Techet
isContextualKeyword(const tokenInfo * const token)6822f581560SJiří Techet static bool isContextualKeyword (const tokenInfo *const token)
6832f581560SJiří Techet {
6842f581560SJiří Techet bool result;
6852f581560SJiří Techet switch (token->keyword)
6862f581560SJiří Techet {
6872f581560SJiří Techet case KEYWORD_CLASS:
6882f581560SJiří Techet case KEYWORD_ENUM:
6892f581560SJiří Techet case KEYWORD_INTERFACE:
6902f581560SJiří Techet case KEYWORD_NAMESPACE:
6912f581560SJiří Techet case KEYWORD_STRUCT:
6922f581560SJiří Techet case KEYWORD_UNION:
6932f581560SJiří Techet case KEYWORD_VERSION:
6942f581560SJiří Techet case KEYWORD_TEMPLATE:
6952f581560SJiří Techet result = true;
6962f581560SJiří Techet break;
6972f581560SJiří Techet
6982f581560SJiří Techet default: result = false; break;
6992f581560SJiří Techet }
7002f581560SJiří Techet return result;
7012f581560SJiří Techet }
7022f581560SJiří Techet
isContextualStatement(const statementInfo * const st)7032f581560SJiří Techet static bool isContextualStatement (const statementInfo *const st)
7042f581560SJiří Techet {
7052f581560SJiří Techet bool result = false;
7062f581560SJiří Techet if (st != NULL) switch (st->declaration)
7072f581560SJiří Techet {
7082f581560SJiří Techet case DECL_CLASS:
7092f581560SJiří Techet case DECL_ENUM:
7102f581560SJiří Techet case DECL_INTERFACE:
7112f581560SJiří Techet case DECL_NAMESPACE:
7122f581560SJiří Techet case DECL_PRIVATE:
7132f581560SJiří Techet case DECL_PROTECTED:
7142f581560SJiří Techet case DECL_PUBLIC:
7152f581560SJiří Techet case DECL_STRUCT:
7162f581560SJiří Techet case DECL_UNION:
7172f581560SJiří Techet case DECL_TEMPLATE:
7182f581560SJiří Techet case DECL_ANNOTATION:
7192f581560SJiří Techet result = true;
7202f581560SJiří Techet break;
7212f581560SJiří Techet
7222f581560SJiří Techet default: result = false; break;
7232f581560SJiří Techet }
7242f581560SJiří Techet return result;
7252f581560SJiří Techet }
7262f581560SJiří Techet
isMember(const statementInfo * const st)7272f581560SJiří Techet static bool isMember (const statementInfo *const st)
7282f581560SJiří Techet {
7292f581560SJiří Techet bool result;
7302f581560SJiří Techet if (isType (st->context, TOKEN_NAME))
7312f581560SJiří Techet result = true;
7322f581560SJiří Techet else
7332f581560SJiří Techet result = (bool)
7342f581560SJiří Techet (st->parent != NULL && isContextualStatement (st->parent));
7352f581560SJiří Techet return result;
7362f581560SJiří Techet }
7372f581560SJiří Techet
initMemberInfo(statementInfo * const st)7382f581560SJiří Techet static void initMemberInfo (statementInfo *const st)
7392f581560SJiří Techet {
7402f581560SJiří Techet accessType accessDefault = ACCESS_UNDEFINED;
7412f581560SJiří Techet if (st->parent != NULL) switch (st->parent->declaration)
7422f581560SJiří Techet {
7432f581560SJiří Techet case DECL_PRIVATE:
7442f581560SJiří Techet accessDefault = ACCESS_PRIVATE;
7452f581560SJiří Techet break;
7462f581560SJiří Techet case DECL_PROTECTED:
7472f581560SJiří Techet accessDefault = ACCESS_PROTECTED;
7482f581560SJiří Techet break;
7492f581560SJiří Techet case DECL_PUBLIC:
7502f581560SJiří Techet accessDefault = ACCESS_PUBLIC;
7512f581560SJiří Techet break;
7522f581560SJiří Techet case DECL_ENUM:
7532f581560SJiří Techet accessDefault = (isInputLanguage (Lang_java) ? ACCESS_PUBLIC : ACCESS_UNDEFINED);
7542f581560SJiří Techet break;
7552f581560SJiří Techet case DECL_NAMESPACE:
7562f581560SJiří Techet accessDefault = ACCESS_UNDEFINED;
7572f581560SJiří Techet break;
7582f581560SJiří Techet
7592f581560SJiří Techet case DECL_CLASS:
7602f581560SJiří Techet if (isInputLanguage (Lang_java))
7612f581560SJiří Techet accessDefault = ACCESS_DEFAULT;
7622f581560SJiří Techet else if (isInputLanguage (Lang_d))
7632f581560SJiří Techet accessDefault = ACCESS_PUBLIC;
7642f581560SJiří Techet else
7652f581560SJiří Techet accessDefault = ACCESS_PRIVATE;
7662f581560SJiří Techet break;
7672f581560SJiří Techet
7682f581560SJiří Techet case DECL_INTERFACE:
7692f581560SJiří Techet case DECL_STRUCT:
7702f581560SJiří Techet case DECL_UNION:
7712f581560SJiří Techet case DECL_ANNOTATION:
7722f581560SJiří Techet accessDefault = ACCESS_PUBLIC;
7732f581560SJiří Techet break;
7742f581560SJiří Techet
7752f581560SJiří Techet default: break;
7762f581560SJiří Techet }
7772f581560SJiří Techet st->member.accessDefault = accessDefault;
7782f581560SJiří Techet st->member.access = accessDefault;
7792f581560SJiří Techet }
7802f581560SJiří Techet
reinitStatement(statementInfo * const st,const bool partial)7812f581560SJiří Techet static void reinitStatement (statementInfo *const st, const bool partial)
7822f581560SJiří Techet {
7832f581560SJiří Techet unsigned int i;
7842f581560SJiří Techet
7852f581560SJiří Techet if (! partial)
7862f581560SJiří Techet {
7872f581560SJiří Techet st->scope = SCOPE_GLOBAL;
7882f581560SJiří Techet if (isContextualStatement (st->parent))
7892f581560SJiří Techet st->declaration = DECL_BASE;
7902f581560SJiří Techet else
7912f581560SJiří Techet st->declaration = DECL_NONE;
7922f581560SJiří Techet }
7932f581560SJiří Techet st->gotParenName = false;
7942f581560SJiří Techet st->isPointer = false;
7952f581560SJiří Techet st->inFunction = false;
7962f581560SJiří Techet st->assignment = false;
7972f581560SJiří Techet st->notVariable = false;
7982f581560SJiří Techet st->implementation = IMP_DEFAULT;
7992f581560SJiří Techet st->gotArgs = false;
8002f581560SJiří Techet st->gotName = false;
8012f581560SJiří Techet st->haveQualifyingName = false;
8022f581560SJiří Techet st->tokenIndex = 0;
8032f581560SJiří Techet
8042f581560SJiří Techet if (st->parent != NULL)
8052f581560SJiří Techet st->inFunction = st->parent->inFunction;
8062f581560SJiří Techet
8072f581560SJiří Techet for (i = 0 ; i < (unsigned int) NumTokens ; ++i)
8082f581560SJiří Techet initToken (st->token [i]);
8092f581560SJiří Techet
8102f581560SJiří Techet initToken (st->context);
8112f581560SJiří Techet
8122f581560SJiří Techet /* Keep the block name, so that a variable following after a comma will
8132f581560SJiří Techet * still have the structure name.
8142f581560SJiří Techet */
8152f581560SJiří Techet if (! partial)
8162f581560SJiří Techet initToken (st->blockName);
8172f581560SJiří Techet
8182f581560SJiří Techet vStringClear (st->parentClasses);
8192f581560SJiří Techet
8202f581560SJiří Techet /* Init member info.
8212f581560SJiří Techet */
8222f581560SJiří Techet if (! partial)
8232f581560SJiří Techet st->member.access = st->member.accessDefault;
8242f581560SJiří Techet }
8252f581560SJiří Techet
initStatement(statementInfo * const st,statementInfo * const parent)8262f581560SJiří Techet static void initStatement (statementInfo *const st, statementInfo *const parent)
8272f581560SJiří Techet {
8282f581560SJiří Techet st->parent = parent;
8292f581560SJiří Techet initMemberInfo (st);
8302f581560SJiří Techet reinitStatement (st, false);
8312f581560SJiří Techet }
8322f581560SJiří Techet
8332f581560SJiří Techet /*
8342f581560SJiří Techet * Tag generation functions
8352f581560SJiří Techet */
8362f581560SJiří Techet #define csharpTagKind(type) csharpTagKindFull(type, true)
8372f581560SJiří Techet #define csharpTagKindNoAssert(type) csharpTagKindFull(type, false)
csharpTagKindFull(const tagType type,const bool with_assert)8382f581560SJiří Techet static csharpKind csharpTagKindFull (const tagType type, const bool with_assert)
8392f581560SJiří Techet {
8402f581560SJiří Techet csharpKind result = CSK_UNDEFINED;
8412f581560SJiří Techet switch (type)
8422f581560SJiří Techet {
8432f581560SJiří Techet case TAG_CLASS: result = CSK_CLASS; break;
8442f581560SJiří Techet case TAG_ENUM: result = CSK_ENUMERATION; break;
8452f581560SJiří Techet case TAG_ENUMERATOR: result = CSK_ENUMERATOR; break;
8462f581560SJiří Techet case TAG_EVENT: result = CSK_EVENT; break;
8472f581560SJiří Techet case TAG_FIELD: result = CSK_FIELD ; break;
8482f581560SJiří Techet case TAG_INTERFACE: result = CSK_INTERFACE; break;
8492f581560SJiří Techet case TAG_LOCAL: result = CSK_LOCAL; break;
8502f581560SJiří Techet case TAG_METHOD: result = CSK_METHOD; break;
8512f581560SJiří Techet case TAG_NAMESPACE: result = CSK_NAMESPACE; break;
8522f581560SJiří Techet case TAG_PROPERTY: result = CSK_PROPERTY; break;
8532f581560SJiří Techet case TAG_STRUCT: result = CSK_STRUCT; break;
8542f581560SJiří Techet case TAG_TYPEDEF: result = CSK_TYPEDEF; break;
8552f581560SJiří Techet
8562f581560SJiří Techet default: if (with_assert) Assert ("Bad C# tag type" == NULL); break;
8572f581560SJiří Techet }
8582f581560SJiří Techet return result;
8592f581560SJiří Techet }
8602f581560SJiří Techet
8612f581560SJiří Techet #define javaTagKind(type) javaTagKindFull(type, true)
8622f581560SJiří Techet #define javaTagKindNoAssert(type) javaTagKindFull(type, false)
javaTagKindFull(const tagType type,bool with_assert)8632f581560SJiří Techet static javaKind javaTagKindFull (const tagType type, bool with_assert)
8642f581560SJiří Techet {
8652f581560SJiří Techet javaKind result = JK_UNDEFINED;
8662f581560SJiří Techet switch (type)
8672f581560SJiří Techet {
8682f581560SJiří Techet case TAG_CLASS: result = JK_CLASS; break;
8692f581560SJiří Techet case TAG_ENUM: result = JK_ENUM; break;
8702f581560SJiří Techet case TAG_ENUMERATOR: result = JK_ENUM_CONSTANT; break;
8712f581560SJiří Techet case TAG_FIELD: result = JK_FIELD; break;
8722f581560SJiří Techet case TAG_INTERFACE: result = JK_INTERFACE; break;
8732f581560SJiří Techet case TAG_LOCAL: result = JK_LOCAL; break;
8742f581560SJiří Techet case TAG_METHOD: result = JK_METHOD; break;
8752f581560SJiří Techet case TAG_PACKAGE: /* Fall through */
8762f581560SJiří Techet case TAG_PACKAGEREF: result = JK_PACKAGE; break;
8772f581560SJiří Techet case TAG_ANNOTATION: result = JK_ANNOTATION; break;
8782f581560SJiří Techet
8792f581560SJiří Techet default: if (with_assert) Assert ("Bad Java tag type" == NULL); break;
8802f581560SJiří Techet }
8812f581560SJiří Techet return result;
8822f581560SJiří Techet }
8832f581560SJiří Techet
8842f581560SJiří Techet #define dTagKind(type) dTagKindFull(type, true)
8852f581560SJiří Techet #define dTagKindNoAssert(type) dTagKindFull(type, false)
dTagKindFull(const tagType type,bool with_assert)8862f581560SJiří Techet static dKind dTagKindFull (const tagType type, bool with_assert)
8872f581560SJiří Techet {
8882f581560SJiří Techet dKind result = DK_UNDEFINED;
8892f581560SJiří Techet switch (type)
8902f581560SJiří Techet {
8912f581560SJiří Techet case TAG_TYPEDEF: result = DK_ALIAS; break;
8922f581560SJiří Techet case TAG_CLASS: result = DK_CLASS; break;
8932f581560SJiří Techet case TAG_ENUM: result = DK_ENUMERATION; break;
8942f581560SJiří Techet case TAG_ENUMERATOR: result = DK_ENUMERATOR; break;
8952f581560SJiří Techet case TAG_EXTERN_VAR: result = DK_EXTERN_VARIABLE; break;
8962f581560SJiří Techet case TAG_FUNCTION: result = DK_FUNCTION; break;
8972f581560SJiří Techet case TAG_INTERFACE: result = DK_INTERFACE; break;
8982f581560SJiří Techet case TAG_LOCAL: result = DK_LOCAL; break;
8992f581560SJiří Techet case TAG_MEMBER: result = DK_MEMBER; break;
9002f581560SJiří Techet case TAG_MIXIN: result = DK_MIXIN; break;
9012f581560SJiří Techet case TAG_PACKAGE: result = DK_MODULE; break;
9022f581560SJiří Techet case TAG_NAMESPACE: result = DK_NAMESPACE; break;
9032f581560SJiří Techet case TAG_PROTOTYPE: result = DK_PROTOTYPE; break;
9042f581560SJiří Techet case TAG_STRUCT: result = DK_STRUCT; break;
9052f581560SJiří Techet case TAG_TEMPLATE: result = DK_TEMPLATE; break;
9062f581560SJiří Techet case TAG_UNION: result = DK_UNION; break;
9072f581560SJiří Techet case TAG_VARIABLE: result = DK_VARIABLE; break;
9082f581560SJiří Techet case TAG_VERSION: result = DK_VERSION; break;
9092f581560SJiří Techet
9102f581560SJiří Techet default: if (with_assert) Assert ("Bad D tag type" == NULL); break;
9112f581560SJiří Techet }
9122f581560SJiří Techet return result;
9132f581560SJiří Techet }
9142f581560SJiří Techet
kindIndexForType(const tagType type)9152f581560SJiří Techet static int kindIndexForType (const tagType type)
9162f581560SJiří Techet {
9176afc0c60SJiří Techet int result = 0;
9182f581560SJiří Techet if (isInputLanguage (Lang_csharp))
9192f581560SJiří Techet result = csharpTagKind (type);
9202f581560SJiří Techet else if (isInputLanguage (Lang_java))
9212f581560SJiří Techet result = javaTagKind (type);
9222f581560SJiří Techet else if (isInputLanguage (Lang_d))
9232f581560SJiří Techet result = dTagKind (type);
9242f581560SJiří Techet return result;
9252f581560SJiří Techet }
9262f581560SJiří Techet
roleForType(const tagType type)9272f581560SJiří Techet static int roleForType (const tagType type)
9282f581560SJiří Techet {
9292f581560SJiří Techet int result;
9302f581560SJiří Techet
9312f581560SJiří Techet result = ROLE_DEFINITION_INDEX;
9322f581560SJiří Techet if (isInputLanguage (Lang_java))
9332f581560SJiří Techet {
9342f581560SJiří Techet if (type == TAG_PACKAGEREF)
9352f581560SJiří Techet result = JAVAR_PACKAGE_IMPORTED;
9362f581560SJiří Techet }
9372f581560SJiří Techet
9382f581560SJiří Techet return result;
9392f581560SJiří Techet }
9402f581560SJiří Techet
tagName(const tagType type)9412f581560SJiří Techet static const char *tagName (const tagType type)
9422f581560SJiří Techet {
9436afc0c60SJiří Techet const char* result = NULL;
9442f581560SJiří Techet if (isInputLanguage (Lang_csharp))
9452f581560SJiří Techet result = CsharpKinds [csharpTagKind (type)].name;
9462f581560SJiří Techet else if (isInputLanguage (Lang_java))
9472f581560SJiří Techet result = JavaKinds [javaTagKind (type)].name;
9482f581560SJiří Techet else if (isInputLanguage (Lang_d))
9492f581560SJiří Techet result = DKinds [dTagKind (type)].name;
9502f581560SJiří Techet return result;
9512f581560SJiří Techet }
9522f581560SJiří Techet
includeTag(const tagType type,const bool isFileScope)9532f581560SJiří Techet static bool includeTag (const tagType type, const bool isFileScope)
9542f581560SJiří Techet {
9552f581560SJiří Techet bool result;
9566afc0c60SJiří Techet int k = COMMONK_UNDEFINED;
9572f581560SJiří Techet
9582f581560SJiří Techet if (isFileScope && !isXtagEnabled(XTAG_FILE_SCOPE))
9592f581560SJiří Techet return false;
9602f581560SJiří Techet else if (isInputLanguage (Lang_csharp))
9612f581560SJiří Techet k = csharpTagKindNoAssert (type);
9622f581560SJiří Techet else if (isInputLanguage (Lang_java))
9632f581560SJiří Techet k = javaTagKindNoAssert (type);
9642f581560SJiří Techet else if (isInputLanguage (Lang_d))
9652f581560SJiří Techet k = dTagKindNoAssert (type);
9662f581560SJiří Techet
9672f581560SJiří Techet if (k == COMMONK_UNDEFINED)
9682f581560SJiří Techet result = false;
9692f581560SJiří Techet else
9702f581560SJiří Techet result = isInputLanguageKindEnabled (k);
9712f581560SJiří Techet
9722f581560SJiří Techet return result;
9732f581560SJiří Techet }
9742f581560SJiří Techet
declToTagType(const declType declaration)9752f581560SJiří Techet static tagType declToTagType (const declType declaration)
9762f581560SJiří Techet {
9772f581560SJiří Techet tagType type = TAG_UNDEFINED;
9782f581560SJiří Techet
9792f581560SJiří Techet switch (declaration)
9802f581560SJiří Techet {
9812f581560SJiří Techet case DECL_CLASS: type = TAG_CLASS; break;
9822f581560SJiří Techet case DECL_ENUM: type = TAG_ENUM; break;
9832f581560SJiří Techet case DECL_EVENT: type = TAG_EVENT; break;
9842f581560SJiří Techet case DECL_FUNCTION: type = TAG_FUNCTION; break;
9852f581560SJiří Techet case DECL_FUNCTION_TEMPLATE: type = TAG_FUNCTION; break;
9862f581560SJiří Techet case DECL_INTERFACE: type = TAG_INTERFACE; break;
9872f581560SJiří Techet case DECL_NAMESPACE: type = TAG_NAMESPACE; break;
9882f581560SJiří Techet case DECL_PRIVATE: type = TAG_CLASS; break;
9892f581560SJiří Techet case DECL_PROTECTED: type = TAG_CLASS; break;
9902f581560SJiří Techet case DECL_PUBLIC: type = TAG_CLASS; break;
9912f581560SJiří Techet case DECL_TEMPLATE: type = TAG_TEMPLATE; break;
9922f581560SJiří Techet case DECL_STRUCT: type = TAG_STRUCT; break;
9932f581560SJiří Techet case DECL_UNION: type = TAG_UNION; break;
9942f581560SJiří Techet case DECL_VERSION: type = TAG_VERSION; break;
9952f581560SJiří Techet case DECL_ANNOTATION: type = TAG_ANNOTATION; break;
9962f581560SJiří Techet
9972f581560SJiří Techet default: Assert ("Unexpected declaration" == NULL); break;
9982f581560SJiří Techet }
9992f581560SJiří Techet return type;
10002f581560SJiří Techet }
10012f581560SJiří Techet
accessField(const statementInfo * const st)10022f581560SJiří Techet static const char* accessField (const statementInfo *const st)
10032f581560SJiří Techet {
10042f581560SJiří Techet const char* result = NULL;
10056afc0c60SJiří Techet if (st->member.access != ACCESS_UNDEFINED)
10062f581560SJiří Techet result = accessString (st->member.access);
10072f581560SJiří Techet return result;
10082f581560SJiří Techet }
10092f581560SJiří Techet
addContextSeparator(vString * const scope)10102f581560SJiří Techet static void addContextSeparator (vString *const scope)
10112f581560SJiří Techet {
10122f581560SJiří Techet vStringPut (scope, '.');
10132f581560SJiří Techet }
10142f581560SJiří Techet
addOtherFields(tagEntryInfo * const tag,const tagType type,const statementInfo * const st,vString * const scope,vString * const typeRef)10152f581560SJiří Techet static void addOtherFields (tagEntryInfo* const tag, const tagType type,
10162f581560SJiří Techet const statementInfo *const st,
10172f581560SJiří Techet vString *const scope, vString *const typeRef)
10182f581560SJiří Techet {
10192f581560SJiří Techet /* For selected tag types, append an extension flag designating the
10202f581560SJiří Techet * parent object in which the tag is defined.
10212f581560SJiří Techet */
10222f581560SJiří Techet switch (type)
10232f581560SJiří Techet {
10242f581560SJiří Techet default: break;
10252f581560SJiří Techet
10262f581560SJiří Techet case TAG_FUNCTION:
10272f581560SJiří Techet case TAG_TEMPLATE:
10282f581560SJiří Techet case TAG_METHOD:
10292f581560SJiří Techet case TAG_PROTOTYPE:
10302f581560SJiří Techet if (vStringLength (Signature) > 0)
10312f581560SJiří Techet tag->extensionFields.signature = vStringValue (Signature);
10322f581560SJiří Techet case TAG_CLASS:
10332f581560SJiří Techet case TAG_ENUM:
10342f581560SJiří Techet case TAG_ENUMERATOR:
10352f581560SJiří Techet case TAG_EVENT:
10362f581560SJiří Techet case TAG_FIELD:
10372f581560SJiří Techet case TAG_INTERFACE:
10382f581560SJiří Techet case TAG_MEMBER:
10392f581560SJiří Techet case TAG_NAMESPACE:
10402f581560SJiří Techet case TAG_PROPERTY:
10412f581560SJiří Techet case TAG_STRUCT:
10422f581560SJiří Techet case TAG_TYPEDEF:
10432f581560SJiří Techet case TAG_UNION:
10442f581560SJiří Techet case TAG_ANNOTATION:
10452f581560SJiří Techet if (vStringLength (scope) > 0 &&
10462f581560SJiří Techet (isMember (st) || st->parent->declaration == DECL_NAMESPACE))
10472f581560SJiří Techet {
10482f581560SJiří Techet tagType ptype;
10492f581560SJiří Techet
10502f581560SJiří Techet if (isType (st->context, TOKEN_NAME))
10512f581560SJiří Techet {
10522f581560SJiří Techet tag->extensionFields.scopeKindIndex = kindIndexForType (TAG_CLASS);
10532f581560SJiří Techet tag->extensionFields.scopeName = vStringValue (scope);
10542f581560SJiří Techet }
10552f581560SJiří Techet else if ((ptype = declToTagType (parentDecl (st))) &&
10562f581560SJiří Techet includeTag (ptype, isXtagEnabled(XTAG_FILE_SCOPE)))
10572f581560SJiří Techet {
10582f581560SJiří Techet tag->extensionFields.scopeKindIndex = kindIndexForType (ptype);
10592f581560SJiří Techet tag->extensionFields.scopeName = vStringValue (scope);
10602f581560SJiří Techet }
10612f581560SJiří Techet }
10622f581560SJiří Techet if ((type == TAG_CLASS || type == TAG_INTERFACE ||
10632f581560SJiří Techet type == TAG_STRUCT || type == TAG_ANNOTATION) && vStringLength (st->parentClasses) > 0)
10642f581560SJiří Techet {
10652f581560SJiří Techet
10662f581560SJiří Techet tag->extensionFields.inheritance =
10672f581560SJiří Techet vStringValue (st->parentClasses);
10682f581560SJiří Techet }
1069*3db09da3SJiří Techet if (st->implementation != IMP_DEFAULT)
10702f581560SJiří Techet {
10712f581560SJiří Techet tag->extensionFields.implementation =
10722f581560SJiří Techet implementationString (st->implementation);
10732f581560SJiří Techet }
10742f581560SJiří Techet if (isMember (st))
10752f581560SJiří Techet {
10762f581560SJiří Techet tag->extensionFields.access = accessField (st);
10772f581560SJiří Techet }
10782f581560SJiří Techet break;
10792f581560SJiří Techet }
10802f581560SJiří Techet
10812f581560SJiří Techet /* Add typename info, type of the tag and name of struct/union/etc. */
10822f581560SJiří Techet if ((type == TAG_TYPEDEF || type == TAG_VARIABLE || type == TAG_MEMBER)
10832f581560SJiří Techet && isContextualStatement(st))
10842f581560SJiří Techet {
10852f581560SJiří Techet char *p;
10862f581560SJiří Techet
10872f581560SJiří Techet tag->extensionFields.typeRef [0] =
10882f581560SJiří Techet tagName (declToTagType (st->declaration));
10892f581560SJiří Techet p = vStringValue (st->blockName->name);
10902f581560SJiří Techet
10912f581560SJiří Techet /* If there was no {} block get the name from the token before the
10922f581560SJiří Techet * name (current token is ';' or ',', previous token is the name).
10932f581560SJiří Techet */
10942f581560SJiří Techet if (p == NULL || *p == '\0')
10952f581560SJiří Techet {
10962f581560SJiří Techet tokenInfo *const prev2 = prevToken (st, 2);
10972f581560SJiří Techet if (isType (prev2, TOKEN_NAME))
10982f581560SJiří Techet p = vStringValue (prev2->name);
10992f581560SJiří Techet }
11002f581560SJiří Techet
11012f581560SJiří Techet /* Prepend the scope name if there is one. */
11022f581560SJiří Techet if (vStringLength (scope) > 0)
11032f581560SJiří Techet {
11042f581560SJiří Techet vStringCopy(typeRef, scope);
11052f581560SJiří Techet addContextSeparator (typeRef);
11062f581560SJiří Techet vStringCatS(typeRef, p);
11072f581560SJiří Techet p = vStringValue (typeRef);
11082f581560SJiří Techet }
11092f581560SJiří Techet tag->extensionFields.typeRef [1] = p;
11102f581560SJiří Techet }
11112f581560SJiří Techet }
11122f581560SJiří Techet
findScopeHierarchy(vString * const string,const statementInfo * const st)11132f581560SJiří Techet static bool findScopeHierarchy (vString *const string, const statementInfo *const st)
11142f581560SJiří Techet {
11152f581560SJiří Techet bool found = false;
11162f581560SJiří Techet
11172f581560SJiří Techet vStringClear (string);
11182f581560SJiří Techet
11192f581560SJiří Techet if (isType (st->context, TOKEN_NAME))
11202f581560SJiří Techet {
11212f581560SJiří Techet vStringCopy (string, st->context->name);
11222f581560SJiří Techet found = true;
11232f581560SJiří Techet }
11242f581560SJiří Techet
11252f581560SJiří Techet if (st->parent != NULL)
11262f581560SJiří Techet {
11272f581560SJiří Techet vString *temp = vStringNew ();
11282f581560SJiří Techet const statementInfo *s;
11292f581560SJiří Techet for (s = st->parent ; s != NULL ; s = s->parent)
11302f581560SJiří Techet {
11312f581560SJiří Techet if (isContextualStatement (s) ||
11326d30e5b1SJiří Techet s->declaration == DECL_NAMESPACE)
11332f581560SJiří Techet {
11342f581560SJiří Techet if (s->declaration == DECL_PRIVATE ||
11352f581560SJiří Techet s->declaration == DECL_PROTECTED ||
11362f581560SJiří Techet s->declaration == DECL_PUBLIC) {
11372f581560SJiří Techet continue;
11382f581560SJiří Techet }
11392f581560SJiří Techet
11402f581560SJiří Techet found = true;
11412f581560SJiří Techet vStringCopy (temp, string);
11422f581560SJiří Techet vStringClear (string);
11432f581560SJiří Techet if (isType (s->blockName, TOKEN_NAME))
11442f581560SJiří Techet {
11452f581560SJiří Techet if (isType (s->context, TOKEN_NAME) &&
11462f581560SJiří Techet vStringLength (s->context->name) > 0)
11472f581560SJiří Techet {
11482f581560SJiří Techet vStringCat (string, s->context->name);
11492f581560SJiří Techet addContextSeparator (string);
11502f581560SJiří Techet }
11512f581560SJiří Techet vStringCat (string, s->blockName->name);
11522f581560SJiří Techet if (vStringLength (temp) > 0)
11532f581560SJiří Techet addContextSeparator (string);
11542f581560SJiří Techet vStringCat (string, temp);
11552f581560SJiří Techet }
11562f581560SJiří Techet else
11572f581560SJiří Techet {
11582f581560SJiří Techet /* Information for building scope string
11592f581560SJiří Techet is lacking. Maybe input is broken. */
11602f581560SJiří Techet found = false;
11612f581560SJiří Techet }
11622f581560SJiří Techet }
11632f581560SJiří Techet }
11642f581560SJiří Techet vStringDelete (temp);
11652f581560SJiří Techet }
11662f581560SJiří Techet return found;
11672f581560SJiří Techet }
11682f581560SJiří Techet
makeExtraTagEntry(const tagType type,tagEntryInfo * const e,vString * const scope)11692f581560SJiří Techet static void makeExtraTagEntry (const tagType type, tagEntryInfo *const e,
11702f581560SJiří Techet vString *const scope)
11712f581560SJiří Techet {
11722f581560SJiří Techet if (isXtagEnabled(XTAG_QUALIFIED_TAGS) &&
11732f581560SJiří Techet scope != NULL && vStringLength (scope) > 0)
11742f581560SJiří Techet {
11752f581560SJiří Techet vString *const scopedName = vStringNew ();
11762f581560SJiří Techet
11772f581560SJiří Techet if (type != TAG_ENUMERATOR)
11782f581560SJiří Techet vStringCopy (scopedName, scope);
11792f581560SJiří Techet else
11802f581560SJiří Techet {
11812f581560SJiří Techet /* remove last component (i.e. enumeration name) from scope */
11822f581560SJiří Techet const char* const sc = vStringValue (scope);
11832f581560SJiří Techet const char* colon = strrchr (sc, ':');
11842f581560SJiří Techet if (colon != NULL)
11852f581560SJiří Techet {
11862f581560SJiří Techet while (*colon == ':' && colon > sc)
11872f581560SJiří Techet --colon;
11882f581560SJiří Techet vStringNCopy (scopedName, scope, colon + 1 - sc);
11892f581560SJiří Techet }
11902f581560SJiří Techet }
11912f581560SJiří Techet if (vStringLength (scopedName) > 0)
11922f581560SJiří Techet {
11932f581560SJiří Techet addContextSeparator (scopedName);
11942f581560SJiří Techet vStringCatS (scopedName, e->name);
11952f581560SJiří Techet e->name = vStringValue (scopedName);
11962f581560SJiří Techet markTagExtraBit (e, XTAG_QUALIFIED_TAGS);
11972f581560SJiří Techet makeTagEntry (e);
11982f581560SJiří Techet }
11992f581560SJiří Techet vStringDelete (scopedName);
12002f581560SJiří Techet }
12012f581560SJiří Techet }
12022f581560SJiří Techet
makeTag(const tokenInfo * const token,const statementInfo * const st,bool isFileScope,const tagType type)12032f581560SJiří Techet static int makeTag (const tokenInfo *const token,
12042f581560SJiří Techet const statementInfo *const st,
12052f581560SJiří Techet bool isFileScope, const tagType type)
12062f581560SJiří Techet {
12072f581560SJiří Techet int corkIndex = CORK_NIL;
12082f581560SJiří Techet /* Nothing is really of file scope when it appears in a header file.
12092f581560SJiří Techet */
12102f581560SJiří Techet isFileScope = (bool) (isFileScope && ! isInputHeaderFile ());
12112f581560SJiří Techet
12122f581560SJiří Techet if (isType (token, TOKEN_NAME) && vStringLength (token->name) > 0 &&
12132f581560SJiří Techet includeTag (type, isFileScope))
12142f581560SJiří Techet {
12152f581560SJiří Techet vString *scope;
12162f581560SJiří Techet vString *typeRef;
12172f581560SJiří Techet bool isScopeBuilt;
12182f581560SJiří Techet /* Use "typeRef" to store the typename from addOtherFields() until
12192f581560SJiří Techet * it's used in makeTagEntry().
12202f581560SJiří Techet */
12212f581560SJiří Techet tagEntryInfo e;
12222f581560SJiří Techet int kind;
12232f581560SJiří Techet int role;
12242f581560SJiří Techet
12252f581560SJiří Techet role = roleForType (type);
12262f581560SJiří Techet if (! (role == ROLE_DEFINITION_INDEX || isXtagEnabled (XTAG_REFERENCE_TAGS)))
12272f581560SJiří Techet return CORK_NIL;
12282f581560SJiří Techet
12292f581560SJiří Techet scope = vStringNew ();
12302f581560SJiří Techet typeRef = vStringNew ();
12312f581560SJiří Techet
12322f581560SJiří Techet kind = kindIndexForType(type);
12332f581560SJiří Techet if (role == ROLE_DEFINITION_INDEX)
12342f581560SJiří Techet initTagEntry (&e, vStringValue (token->name), kind);
12352f581560SJiří Techet else
12362f581560SJiří Techet initRefTagEntry (&e, vStringValue (token->name), kind, role);
12372f581560SJiří Techet
12382f581560SJiří Techet e.lineNumber = token->lineNumber;
12392f581560SJiří Techet e.filePosition = token->filePosition;
12402f581560SJiří Techet e.isFileScope = isFileScope;
12412f581560SJiří Techet if (e.isFileScope)
12422f581560SJiří Techet markTagExtraBit (&e, XTAG_FILE_SCOPE);
12432f581560SJiří Techet
12442f581560SJiří Techet isScopeBuilt = findScopeHierarchy (scope, st);
12452f581560SJiří Techet addOtherFields (&e, type, st, scope, typeRef);
12462f581560SJiří Techet
12472f581560SJiří Techet corkIndex = makeTagEntry (&e);
12482f581560SJiří Techet if (isScopeBuilt)
12492f581560SJiří Techet makeExtraTagEntry (type, &e, scope);
12502f581560SJiří Techet vStringDelete (scope);
12512f581560SJiří Techet vStringDelete (typeRef);
12522f581560SJiří Techet }
12532f581560SJiří Techet return corkIndex;
12542f581560SJiří Techet }
12552f581560SJiří Techet
isValidTypeSpecifier(const declType declaration)12562f581560SJiří Techet static bool isValidTypeSpecifier (const declType declaration)
12572f581560SJiří Techet {
12582f581560SJiří Techet bool result;
12592f581560SJiří Techet switch (declaration)
12602f581560SJiří Techet {
12612f581560SJiří Techet case DECL_BASE:
12622f581560SJiří Techet case DECL_CLASS:
12632f581560SJiří Techet case DECL_ENUM:
12642f581560SJiří Techet case DECL_EVENT:
12652f581560SJiří Techet case DECL_STRUCT:
12662f581560SJiří Techet case DECL_UNION:
12672f581560SJiří Techet case DECL_ANNOTATION:
12682f581560SJiří Techet result = true;
12692f581560SJiří Techet break;
12702f581560SJiří Techet
12712f581560SJiří Techet default:
12722f581560SJiří Techet result = false;
12732f581560SJiří Techet break;
12742f581560SJiří Techet }
12752f581560SJiří Techet return result;
12762f581560SJiří Techet }
12772f581560SJiří Techet
qualifyEnumeratorTag(const statementInfo * const st,const tokenInfo * const nameToken)12782f581560SJiří Techet static int qualifyEnumeratorTag (const statementInfo *const st,
12792f581560SJiří Techet const tokenInfo *const nameToken)
12802f581560SJiří Techet {
12812f581560SJiří Techet int corkIndex = CORK_NIL;
12822f581560SJiří Techet if (isType (nameToken, TOKEN_NAME))
12832f581560SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_ENUMERATOR);
12842f581560SJiří Techet return corkIndex;
12852f581560SJiří Techet }
12862f581560SJiří Techet
qualifyFunctionTag(const statementInfo * const st,const tokenInfo * const nameToken)12872f581560SJiří Techet static int qualifyFunctionTag (const statementInfo *const st,
12882f581560SJiří Techet const tokenInfo *const nameToken)
12892f581560SJiří Techet {
12902f581560SJiří Techet int corkIndex = CORK_NIL;
12912f581560SJiří Techet if (isType (nameToken, TOKEN_NAME))
12922f581560SJiří Techet {
12932f581560SJiří Techet tagType type;
12942f581560SJiří Techet const bool isFileScope =
12952f581560SJiří Techet (bool) (st->member.access == ACCESS_PRIVATE ||
12962f581560SJiří Techet (!isMember (st) && st->scope == SCOPE_STATIC));
12972f581560SJiří Techet if (isInputLanguage (Lang_java) || isInputLanguage (Lang_csharp))
12982f581560SJiří Techet type = TAG_METHOD;
12992f581560SJiří Techet else
13002f581560SJiří Techet type = TAG_FUNCTION;
13012f581560SJiří Techet corkIndex = makeTag (nameToken, st, isFileScope, type);
13022f581560SJiří Techet }
13032f581560SJiří Techet return corkIndex;
13042f581560SJiří Techet }
13052f581560SJiří Techet
qualifyFunctionDeclTag(const statementInfo * const st,const tokenInfo * const nameToken)13062f581560SJiří Techet static int qualifyFunctionDeclTag (const statementInfo *const st,
13072f581560SJiří Techet const tokenInfo *const nameToken)
13082f581560SJiří Techet {
13092f581560SJiří Techet int corkIndex = CORK_NIL;
13102f581560SJiří Techet if (! isType (nameToken, TOKEN_NAME))
13112f581560SJiří Techet ;
13122f581560SJiří Techet else if (isInputLanguage (Lang_java) || isInputLanguage (Lang_csharp))
13132f581560SJiří Techet corkIndex = qualifyFunctionTag (st, nameToken);
13142f581560SJiří Techet else if (st->scope == SCOPE_TYPEDEF)
13152f581560SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_TYPEDEF);
13162f581560SJiří Techet else if (isValidTypeSpecifier (st->declaration) && ! isInputLanguage (Lang_csharp))
13172f581560SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_PROTOTYPE);
13182f581560SJiří Techet return corkIndex;
13192f581560SJiří Techet }
13202f581560SJiří Techet
qualifyCompoundTag(const statementInfo * const st,const tokenInfo * const nameToken)13212f581560SJiří Techet static int qualifyCompoundTag (const statementInfo *const st,
13222f581560SJiří Techet const tokenInfo *const nameToken)
13232f581560SJiří Techet {
13242f581560SJiří Techet int corkIndex = CORK_NIL;
13252f581560SJiří Techet if (isType (nameToken, TOKEN_NAME))
13262f581560SJiří Techet {
13272f581560SJiří Techet const tagType type = declToTagType (st->declaration);
13282f581560SJiří Techet const bool fileScoped = (bool)
13292f581560SJiří Techet (!(isInputLanguage (Lang_java) ||
13301f8ea58bSJiří Techet isInputLanguage (Lang_csharp)));
13312f581560SJiří Techet
13322f581560SJiří Techet if (type != TAG_UNDEFINED)
13332f581560SJiří Techet corkIndex = makeTag (nameToken, st, fileScoped, type);
13342f581560SJiří Techet }
13352f581560SJiří Techet return corkIndex;
13362f581560SJiří Techet }
13372f581560SJiří Techet
qualifyBlockTag(statementInfo * const st,const tokenInfo * const nameToken)13382f581560SJiří Techet static int qualifyBlockTag (statementInfo *const st,
13392f581560SJiří Techet const tokenInfo *const nameToken)
13402f581560SJiří Techet {
13412f581560SJiří Techet int corkIndex = CORK_NIL;
13422f581560SJiří Techet switch (st->declaration)
13432f581560SJiří Techet {
13442f581560SJiří Techet
13452f581560SJiří Techet case DECL_CLASS:
13462f581560SJiří Techet case DECL_ENUM:
13472f581560SJiří Techet case DECL_INTERFACE:
13482f581560SJiří Techet case DECL_NAMESPACE:
13492f581560SJiří Techet case DECL_STRUCT:
13502f581560SJiří Techet case DECL_UNION:
13512f581560SJiří Techet case DECL_TEMPLATE:
13522f581560SJiří Techet case DECL_VERSION:
13532f581560SJiří Techet case DECL_ANNOTATION:
13542f581560SJiří Techet corkIndex = qualifyCompoundTag (st, nameToken);
13552f581560SJiří Techet break;
13562f581560SJiří Techet default: break;
13572f581560SJiří Techet }
13582f581560SJiří Techet return corkIndex;
13592f581560SJiří Techet }
13602f581560SJiří Techet
qualifyVariableTag(const statementInfo * const st,const tokenInfo * const nameToken)13612f581560SJiří Techet static int qualifyVariableTag (const statementInfo *const st,
13622f581560SJiří Techet const tokenInfo *const nameToken)
13632f581560SJiří Techet {
13642f581560SJiří Techet int corkIndex = CORK_NIL;
13652f581560SJiří Techet /* We have to watch that we do not interpret a declaration of the
13662f581560SJiří Techet * form "struct tag;" as a variable definition. In such a case, the
13672f581560SJiří Techet * token preceding the name will be a keyword.
13682f581560SJiří Techet */
13692f581560SJiří Techet if (! isType (nameToken, TOKEN_NAME))
13702f581560SJiří Techet ;
13712f581560SJiří Techet else if (st->scope == SCOPE_TYPEDEF)
13722f581560SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_TYPEDEF);
13732f581560SJiří Techet else if (st->declaration == DECL_EVENT)
13742f581560SJiří Techet corkIndex = makeTag (nameToken, st, (bool) (st->member.access == ACCESS_PRIVATE),
13752f581560SJiří Techet TAG_EVENT);
13762f581560SJiří Techet else if (st->declaration == DECL_PACKAGE)
13772f581560SJiří Techet corkIndex = makeTag (nameToken, st, false, TAG_PACKAGE);
13782f581560SJiří Techet else if (st->declaration == DECL_PACKAGEREF)
13792f581560SJiří Techet corkIndex = makeTag (nameToken, st, false, TAG_PACKAGEREF);
13802f581560SJiří Techet else if (st->declaration == DECL_USING && st->assignment)
13812f581560SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_TYPEDEF);
13822f581560SJiří Techet else if (isValidTypeSpecifier (st->declaration))
13832f581560SJiří Techet {
13842f581560SJiří Techet if (st->notVariable)
13852f581560SJiří Techet ;
13862f581560SJiří Techet else if (isMember (st))
13872f581560SJiří Techet {
13882f581560SJiří Techet if (isInputLanguage (Lang_java) || isInputLanguage (Lang_csharp))
13892f581560SJiří Techet corkIndex = makeTag (nameToken, st,
13902f581560SJiří Techet (bool) (st->member.access == ACCESS_PRIVATE), TAG_FIELD);
13912f581560SJiří Techet else if (st->scope == SCOPE_GLOBAL || st->scope == SCOPE_STATIC)
13922f581560SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_MEMBER);
13932f581560SJiří Techet }
13942f581560SJiří Techet else
13952f581560SJiří Techet {
13962f581560SJiří Techet if (st->scope == SCOPE_EXTERN || ! st->haveQualifyingName)
13972f581560SJiří Techet corkIndex = makeTag (nameToken, st, false, TAG_EXTERN_VAR);
13982f581560SJiří Techet else if (st->inFunction)
13992f581560SJiří Techet corkIndex = makeTag (nameToken, st, (bool) (st->scope == SCOPE_STATIC),
14002f581560SJiří Techet TAG_LOCAL);
14012f581560SJiří Techet else
14022f581560SJiří Techet corkIndex = makeTag (nameToken, st, (bool) (st->scope == SCOPE_STATIC),
14032f581560SJiří Techet TAG_VARIABLE);
14042f581560SJiří Techet }
14052f581560SJiří Techet }
14062f581560SJiří Techet return corkIndex;
14072f581560SJiří Techet }
14082f581560SJiří Techet
14092f581560SJiří Techet /*
14102f581560SJiří Techet * Parsing functions
14112f581560SJiří Techet */
14122f581560SJiří Techet
skipToOneOf(const char * const chars)14132f581560SJiří Techet static int skipToOneOf (const char *const chars)
14142f581560SJiří Techet {
14152f581560SJiří Techet int c;
14162f581560SJiří Techet do
14172f581560SJiří Techet c = cppGetc ();
14182f581560SJiří Techet while (c != EOF && c != '\0' && strchr (chars, c) == NULL);
14192f581560SJiří Techet return c;
14202f581560SJiří Techet }
14212f581560SJiří Techet
14222f581560SJiří Techet /* Skip to the next non-white character.
14232f581560SJiří Techet */
skipToNonWhite(void)14242f581560SJiří Techet static int skipToNonWhite (void)
14252f581560SJiří Techet {
14262f581560SJiří Techet bool found = false;
14272f581560SJiří Techet int c;
14282f581560SJiří Techet
14292f581560SJiří Techet #if 0
14302f581560SJiří Techet do
14312f581560SJiří Techet c = cppGetc ();
14322f581560SJiří Techet while (cppIsspace (c));
14332f581560SJiří Techet #else
14342f581560SJiří Techet while (1)
14352f581560SJiří Techet {
14362f581560SJiří Techet c = cppGetc ();
14372f581560SJiří Techet if (cppIsspace (c))
14382f581560SJiří Techet found = true;
14392f581560SJiří Techet else
14402f581560SJiří Techet break;
14412f581560SJiří Techet }
14422f581560SJiří Techet if (CollectingSignature && found)
14432f581560SJiří Techet vStringPut (Signature, ' ');
14442f581560SJiří Techet #endif
14452f581560SJiří Techet
14462f581560SJiří Techet return c;
14472f581560SJiří Techet }
14482f581560SJiří Techet
14492f581560SJiří Techet /* Skips to the next brace in column 1. This is intended for cases where
14502f581560SJiří Techet * preprocessor constructs result in unbalanced braces.
14512f581560SJiří Techet */
skipToFormattedBraceMatch(void)14522f581560SJiří Techet static void skipToFormattedBraceMatch (void)
14532f581560SJiří Techet {
14542f581560SJiří Techet int c, next;
14552f581560SJiří Techet
14562f581560SJiří Techet c = cppGetc ();
14572f581560SJiří Techet next = cppGetc ();
14582f581560SJiří Techet while (c != EOF && (c != '\n' || next != '}'))
14592f581560SJiří Techet {
14602f581560SJiří Techet c = next;
14612f581560SJiří Techet next = cppGetc ();
14622f581560SJiří Techet }
14632f581560SJiří Techet }
14642f581560SJiří Techet
14652f581560SJiří Techet /* Skip to the matching character indicated by the pair string. If skipping
14662f581560SJiří Techet * to a matching brace and any brace is found within a different level of a
14672f581560SJiří Techet * #if conditional statement while brace formatting is in effect, we skip to
14682f581560SJiří Techet * the brace matched by its formatting. It is assumed that we have already
14692f581560SJiří Techet * read the character which starts the group (i.e. the first character of
14702f581560SJiří Techet * "pair").
14712f581560SJiří Techet */
skipToMatch(const char * const pair)14722f581560SJiří Techet static void skipToMatch (const char *const pair)
14732f581560SJiří Techet {
14742f581560SJiří Techet const bool braceMatching = (bool) (strcmp ("{}", pair) == 0);
14752f581560SJiří Techet const bool braceFormatting = (bool) (cppIsBraceFormat () && braceMatching);
14762f581560SJiří Techet const unsigned int initialLevel = cppGetDirectiveNestLevel ();
14772f581560SJiří Techet const int begin = pair [0], end = pair [1];
14782f581560SJiří Techet const unsigned long inputLineNumber = getInputLineNumber ();
14792f581560SJiří Techet int matchLevel = 1;
14802f581560SJiří Techet int c = '\0';
14812f581560SJiří Techet
14822f581560SJiří Techet while (matchLevel > 0 && (c = skipToNonWhite ()) != EOF)
14832f581560SJiří Techet {
14842f581560SJiří Techet if (CollectingSignature)
14852f581560SJiří Techet vStringPut (Signature, c);
14862f581560SJiří Techet if (c == begin)
14872f581560SJiří Techet {
14882f581560SJiří Techet ++matchLevel;
14892f581560SJiří Techet if (braceFormatting && cppGetDirectiveNestLevel () != initialLevel)
14902f581560SJiří Techet {
14912f581560SJiří Techet skipToFormattedBraceMatch ();
14922f581560SJiří Techet break;
14932f581560SJiří Techet }
14942f581560SJiří Techet }
14952f581560SJiří Techet else if (c == end)
14962f581560SJiří Techet {
14972f581560SJiří Techet --matchLevel;
14982f581560SJiří Techet if (braceFormatting && cppGetDirectiveNestLevel () != initialLevel)
14992f581560SJiří Techet {
15002f581560SJiří Techet skipToFormattedBraceMatch ();
15012f581560SJiří Techet break;
15022f581560SJiří Techet }
15032f581560SJiří Techet }
15042f581560SJiří Techet }
15052f581560SJiří Techet if (c == EOF)
15062f581560SJiří Techet {
15072f581560SJiří Techet verbose ("%s: failed to find match for '%c' at line %lu\n",
15082f581560SJiří Techet getInputFileName (), begin, inputLineNumber);
15092f581560SJiří Techet if (braceMatching)
15102f581560SJiří Techet longjmp (Exception, (int) ExceptionBraceFormattingError);
15112f581560SJiří Techet else
15122f581560SJiří Techet longjmp (Exception, (int) ExceptionFormattingError);
15132f581560SJiří Techet }
15142f581560SJiří Techet }
15152f581560SJiří Techet
skipParens(void)15162f581560SJiří Techet static void skipParens (void)
15172f581560SJiří Techet {
15182f581560SJiří Techet const int c = skipToNonWhite ();
15192f581560SJiří Techet
15202f581560SJiří Techet if (c == '(')
15212f581560SJiří Techet skipToMatch ("()");
15222f581560SJiří Techet else
15232f581560SJiří Techet cppUngetc (c);
15242f581560SJiří Techet }
15252f581560SJiří Techet
skipBraces(void)15262f581560SJiří Techet static void skipBraces (void)
15272f581560SJiří Techet {
15282f581560SJiří Techet const int c = skipToNonWhite ();
15292f581560SJiří Techet
15302f581560SJiří Techet if (c == '{')
15312f581560SJiří Techet skipToMatch ("{}");
15322f581560SJiří Techet else
15332f581560SJiří Techet cppUngetc (c);
15342f581560SJiří Techet }
15352f581560SJiří Techet
analyzeKeyword(const char * const name)15362f581560SJiří Techet static keywordId analyzeKeyword (const char *const name)
15372f581560SJiří Techet {
15382f581560SJiří Techet const keywordId id = (keywordId) lookupKeyword (name, getInputLanguage ());
15392f581560SJiří Techet return id;
15402f581560SJiří Techet }
15412f581560SJiří Techet
analyzeIdentifier(tokenInfo * const token)15422f581560SJiří Techet static void analyzeIdentifier (tokenInfo *const token)
15432f581560SJiří Techet {
15442f581560SJiří Techet const char * name = vStringValue (token->name);
15452f581560SJiří Techet
15462f581560SJiří Techet if(!name)
15472f581560SJiří Techet {
15482f581560SJiří Techet initToken(token);
15492f581560SJiří Techet return;
15502f581560SJiří Techet }
15512f581560SJiří Techet
15522f581560SJiří Techet token->keyword = analyzeKeyword (name);
15532f581560SJiří Techet
15542f581560SJiří Techet if (token->keyword == KEYWORD_NONE)
15552f581560SJiří Techet token->type = TOKEN_NAME;
15562f581560SJiří Techet else
15572f581560SJiří Techet token->type = TOKEN_KEYWORD;
15582f581560SJiří Techet }
15592f581560SJiří Techet
readIdentifier(tokenInfo * const token,const int firstChar)15602f581560SJiří Techet static void readIdentifier (tokenInfo *const token, const int firstChar)
15612f581560SJiří Techet {
15622f581560SJiří Techet vString *const name = token->name;
15632f581560SJiří Techet int c = firstChar;
15642f581560SJiří Techet bool first = true;
15652f581560SJiří Techet
15662f581560SJiří Techet initToken (token);
15672f581560SJiří Techet
15682f581560SJiří Techet do
15692f581560SJiří Techet {
15702f581560SJiří Techet vStringPut (name, c);
15712f581560SJiří Techet if (CollectingSignature)
15722f581560SJiří Techet {
15732f581560SJiří Techet if (!first)
15742f581560SJiří Techet vStringPut (Signature, c);
15752f581560SJiří Techet first = false;
15762f581560SJiří Techet }
15772f581560SJiří Techet c = cppGetc ();
15782f581560SJiří Techet } while (cppIsident (c) || ((isInputLanguage (Lang_java) || isInputLanguage (Lang_csharp)) && (isHighChar (c) || c == '.')));
15792f581560SJiří Techet cppUngetc (c); /* unget non-identifier character */
15802f581560SJiří Techet
15812f581560SJiří Techet analyzeIdentifier (token);
15822f581560SJiří Techet }
15832f581560SJiří Techet
readPackageName(tokenInfo * const token,const int firstChar,bool allowWildCard)15842f581560SJiří Techet static void readPackageName (tokenInfo *const token, const int firstChar, bool allowWildCard)
15852f581560SJiří Techet {
15862f581560SJiří Techet vString *const name = token->name;
15872f581560SJiří Techet int c = firstChar;
15882f581560SJiří Techet
15892f581560SJiří Techet initToken (token);
15902f581560SJiří Techet
15912f581560SJiří Techet while (cppIsident (c) || (allowWildCard && (c == '*')) || c == '.')
15922f581560SJiří Techet {
15932f581560SJiří Techet vStringPut (name, c);
15942f581560SJiří Techet c = cppGetc ();
15952f581560SJiří Techet }
15962f581560SJiří Techet cppUngetc (c); /* unget non-package character */
15972f581560SJiří Techet }
15982f581560SJiří Techet
readPackageOrNamespace(statementInfo * const st,const declType declaration,bool allowWildCard)15992f581560SJiří Techet static void readPackageOrNamespace (statementInfo *const st, const declType declaration, bool allowWildCard)
16002f581560SJiří Techet {
16012f581560SJiří Techet st->declaration = declaration;
16022f581560SJiří Techet
16032f581560SJiří Techet if (declaration == DECL_NAMESPACE && !isInputLanguage (Lang_csharp))
16042f581560SJiří Techet {
1605d9071cadSJiří Techet /* Namespace is specified one level at a time. */
16062f581560SJiří Techet return;
16072f581560SJiří Techet }
16082f581560SJiří Techet else
16092f581560SJiří Techet {
16102f581560SJiří Techet /* In C#, a namespace can also be specified like a Java package name. */
16112f581560SJiří Techet tokenInfo *const token = activeToken (st);
16122f581560SJiří Techet Assert (isType (token, TOKEN_KEYWORD));
16132f581560SJiří Techet readPackageName (token, skipToNonWhite (), allowWildCard);
16142f581560SJiří Techet token->type = TOKEN_NAME;
16152f581560SJiří Techet st->gotName = true;
16162f581560SJiří Techet st->haveQualifyingName = true;
16172f581560SJiří Techet }
16182f581560SJiří Techet }
16192f581560SJiří Techet
readVersionName(tokenInfo * const token,const int firstChar)16202f581560SJiří Techet static void readVersionName (tokenInfo *const token, const int firstChar)
16212f581560SJiří Techet {
16222f581560SJiří Techet vString *const name = token->name;
16232f581560SJiří Techet int c = firstChar;
16242f581560SJiří Techet
16252f581560SJiří Techet initToken (token);
16262f581560SJiří Techet
16272f581560SJiří Techet while (cppIsident (c))
16282f581560SJiří Techet {
16292f581560SJiří Techet vStringPut (name, c);
16302f581560SJiří Techet c = cppGetc ();
16312f581560SJiří Techet }
16322f581560SJiří Techet cppGetc ();
16332f581560SJiří Techet }
16342f581560SJiří Techet
readVersion(statementInfo * const st)16352f581560SJiří Techet static void readVersion (statementInfo *const st)
16362f581560SJiří Techet {
16372f581560SJiří Techet tokenInfo *const token = activeToken (st);
16382f581560SJiří Techet Assert (isType (token, TOKEN_KEYWORD));
16392f581560SJiří Techet skipToNonWhite ();
16402f581560SJiří Techet readVersionName (token, cppGetc ());
16412f581560SJiří Techet token->type = TOKEN_NAME;
16422f581560SJiří Techet st->declaration = DECL_VERSION;
16432f581560SJiří Techet st->gotName = true;
16442f581560SJiří Techet st->haveQualifyingName = true;
16452f581560SJiří Techet }
16462f581560SJiří Techet
processName(statementInfo * const st)16472f581560SJiří Techet static void processName (statementInfo *const st)
16482f581560SJiří Techet {
16492f581560SJiří Techet Assert (isType (activeToken (st), TOKEN_NAME));
16502f581560SJiří Techet if (st->gotName && st->declaration == DECL_NONE)
16512f581560SJiří Techet st->declaration = DECL_BASE;
16522f581560SJiří Techet st->gotName = true;
16532f581560SJiří Techet st->haveQualifyingName = true;
16542f581560SJiří Techet }
16552f581560SJiří Techet
readOperator(statementInfo * const st)16562f581560SJiří Techet static void readOperator (statementInfo *const st)
16572f581560SJiří Techet {
16582f581560SJiří Techet const char *const acceptable = "+-*/%^&|~!=<>,[]";
16592f581560SJiří Techet const tokenInfo* const prev = prevToken (st,1);
16602f581560SJiří Techet tokenInfo *const token = activeToken (st);
16612f581560SJiří Techet vString *const name = token->name;
16622f581560SJiří Techet int c = skipToNonWhite ();
16632f581560SJiří Techet
16642f581560SJiří Techet /* When we arrive here, we have the keyword "operator" in 'name'.
16652f581560SJiří Techet */
16662f581560SJiří Techet if (isType (prev, TOKEN_KEYWORD) && (prev->keyword == KEYWORD_ENUM ||
16672f581560SJiří Techet prev->keyword == KEYWORD_STRUCT || prev->keyword == KEYWORD_UNION))
16682f581560SJiří Techet ; /* ignore "operator" keyword if preceded by these keywords */
16692f581560SJiří Techet else if (c == '(')
16702f581560SJiří Techet {
16712f581560SJiří Techet /* Verify whether this is a valid function call (i.e. "()") operator.
16722f581560SJiří Techet */
16732f581560SJiří Techet if (cppGetc () == ')')
16742f581560SJiří Techet {
16752f581560SJiří Techet vStringPut (name, ' '); /* always separate operator from keyword */
16762f581560SJiří Techet c = skipToNonWhite ();
16772f581560SJiří Techet if (c == '(')
16782f581560SJiří Techet vStringCatS (name, "()");
16792f581560SJiří Techet }
16802f581560SJiří Techet else
16812f581560SJiří Techet {
16822f581560SJiří Techet skipToMatch ("()");
16832f581560SJiří Techet c = cppGetc ();
16842f581560SJiří Techet }
16852f581560SJiří Techet }
16862f581560SJiří Techet else if (cppIsident1 (c))
16872f581560SJiří Techet {
16882f581560SJiří Techet /* Handle "new" and "delete" operators, and conversion functions
16892f581560SJiří Techet * (per 13.3.1.1.2 [2] of the C++ spec).
16902f581560SJiří Techet */
16912f581560SJiří Techet bool whiteSpace = true; /* default causes insertion of space */
16922f581560SJiří Techet do
16932f581560SJiří Techet {
16942f581560SJiří Techet if (cppIsspace (c))
16952f581560SJiří Techet whiteSpace = true;
16962f581560SJiří Techet else
16972f581560SJiří Techet {
16982f581560SJiří Techet if (whiteSpace)
16992f581560SJiří Techet {
17002f581560SJiří Techet vStringPut (name, ' ');
17012f581560SJiří Techet whiteSpace = false;
17022f581560SJiří Techet }
17032f581560SJiří Techet vStringPut (name, c);
17042f581560SJiří Techet }
17052f581560SJiří Techet c = cppGetc ();
17062f581560SJiří Techet } while (! isOneOf (c, "(;") && c != EOF);
17072f581560SJiří Techet }
17082f581560SJiří Techet else if (isOneOf (c, acceptable))
17092f581560SJiří Techet {
17102f581560SJiří Techet vStringPut (name, ' '); /* always separate operator from keyword */
17112f581560SJiří Techet do
17122f581560SJiří Techet {
17132f581560SJiří Techet vStringPut (name, c);
17142f581560SJiří Techet c = cppGetc ();
17152f581560SJiří Techet } while (isOneOf (c, acceptable));
17162f581560SJiří Techet }
17172f581560SJiří Techet
17182f581560SJiří Techet cppUngetc (c);
17192f581560SJiří Techet
17202f581560SJiří Techet token->type = TOKEN_NAME;
17212f581560SJiří Techet token->keyword = KEYWORD_NONE;
17222f581560SJiří Techet processName (st);
17232f581560SJiří Techet }
17242f581560SJiří Techet
copyToken(tokenInfo * const dest,const tokenInfo * const src)17252f581560SJiří Techet static void copyToken (tokenInfo *const dest, const tokenInfo *const src)
17262f581560SJiří Techet {
17272f581560SJiří Techet dest->type = src->type;
17282f581560SJiří Techet dest->keyword = src->keyword;
17292f581560SJiří Techet dest->filePosition = src->filePosition;
17302f581560SJiří Techet dest->lineNumber = src->lineNumber;
17312f581560SJiří Techet vStringCopy (dest->name, src->name);
17322f581560SJiří Techet }
17332f581560SJiří Techet
setAccess(statementInfo * const st,const accessType access)17342f581560SJiří Techet static void setAccess (statementInfo *const st, const accessType access)
17352f581560SJiří Techet {
17362f581560SJiří Techet if (isInputLanguage (Lang_d))
17372f581560SJiří Techet {
17382f581560SJiří Techet int c = skipToNonWhite ();
17392f581560SJiří Techet
17402f581560SJiří Techet if (c == '{')
17412f581560SJiří Techet {
17422f581560SJiří Techet switch(access)
17432f581560SJiří Techet {
17442f581560SJiří Techet case ACCESS_PRIVATE:
17452f581560SJiří Techet st->declaration = DECL_PRIVATE;
17462f581560SJiří Techet break;
17472f581560SJiří Techet case ACCESS_PUBLIC:
17482f581560SJiří Techet st->declaration = DECL_PUBLIC;
17492f581560SJiří Techet break;
17502f581560SJiří Techet case ACCESS_PROTECTED:
17512f581560SJiří Techet st->declaration = DECL_PROTECTED;
17522f581560SJiří Techet break;
17532f581560SJiří Techet default:
17542f581560SJiří Techet break;
17552f581560SJiří Techet }
17562f581560SJiří Techet st->member.access = access;
17572f581560SJiří Techet cppUngetc (c);
17582f581560SJiří Techet }
17592f581560SJiří Techet else if (c == ':') {
17602f581560SJiří Techet reinitStatement (st, false);
17612f581560SJiří Techet st->member.accessDefault = access;
17622f581560SJiří Techet }
17632f581560SJiří Techet else {
17642f581560SJiří Techet cppUngetc (c);
17652f581560SJiří Techet }
17662f581560SJiří Techet }
17672f581560SJiří Techet
17682f581560SJiří Techet if (isMember (st))
17692f581560SJiří Techet {
17706afc0c60SJiří Techet if (isInputLanguage (Lang_d))
17712f581560SJiří Techet {
17722f581560SJiří Techet if (st->parent != NULL &&
17732f581560SJiří Techet (st->parent->declaration == DECL_PRIVATE ||
17742f581560SJiří Techet st->parent->declaration == DECL_PROTECTED ||
17752f581560SJiří Techet st->parent->declaration == DECL_PUBLIC))
17762f581560SJiří Techet {
17772f581560SJiří Techet st->member.access = st->parent->member.access;
17782f581560SJiří Techet return;
17792f581560SJiří Techet }
17802f581560SJiří Techet }
17812f581560SJiří Techet st->member.access = access;
17822f581560SJiří Techet }
17832f581560SJiří Techet }
17842f581560SJiří Techet
discardTypeList(tokenInfo * const token)17852f581560SJiří Techet static void discardTypeList (tokenInfo *const token)
17862f581560SJiří Techet {
17872f581560SJiří Techet int c = skipToNonWhite ();
17882f581560SJiří Techet while (cppIsident1 (c))
17892f581560SJiří Techet {
17902f581560SJiří Techet readIdentifier (token, c);
17912f581560SJiří Techet c = skipToNonWhite ();
17922f581560SJiří Techet if (c == '.' || c == ',')
17932f581560SJiří Techet c = skipToNonWhite ();
17942f581560SJiří Techet }
17952f581560SJiří Techet cppUngetc (c);
17962f581560SJiří Techet }
17972f581560SJiří Techet
addParentClass(statementInfo * const st,tokenInfo * const token)17982f581560SJiří Techet static void addParentClass (statementInfo *const st, tokenInfo *const token)
17992f581560SJiří Techet {
18002f581560SJiří Techet if (vStringLength (token->name) > 0 &&
18012f581560SJiří Techet vStringLength (st->parentClasses) > 0)
18022f581560SJiří Techet {
18032f581560SJiří Techet vStringPut (st->parentClasses, ',');
18042f581560SJiří Techet }
18052f581560SJiří Techet vStringCat (st->parentClasses, token->name);
18062f581560SJiří Techet }
18072f581560SJiří Techet
readParents(statementInfo * const st,const int qualifier)18082f581560SJiří Techet static void readParents (statementInfo *const st, const int qualifier)
18092f581560SJiří Techet {
18102f581560SJiří Techet tokenInfo *const token = newToken ();
18112f581560SJiří Techet tokenInfo *const parent = newToken ();
18122f581560SJiří Techet int c;
18132f581560SJiří Techet
18142f581560SJiří Techet do
18152f581560SJiří Techet {
18162f581560SJiří Techet c = skipToNonWhite ();
18172f581560SJiří Techet if (cppIsident1 (c))
18182f581560SJiří Techet {
18192f581560SJiří Techet readIdentifier (token, c);
18202f581560SJiří Techet if (isType (token, TOKEN_NAME))
18212f581560SJiří Techet vStringCat (parent->name, token->name);
18222f581560SJiří Techet else
18232f581560SJiří Techet {
18242f581560SJiří Techet addParentClass (st, parent);
18252f581560SJiří Techet initToken (parent);
18262f581560SJiří Techet }
18272f581560SJiří Techet }
18282f581560SJiří Techet else if (c == qualifier)
18292f581560SJiří Techet vStringPut (parent->name, c);
18302f581560SJiří Techet else if (c == '<')
18312f581560SJiří Techet skipToMatch ("<>");
18322f581560SJiří Techet else if (isType (token, TOKEN_NAME))
18332f581560SJiří Techet {
18342f581560SJiří Techet addParentClass (st, parent);
18352f581560SJiří Techet initToken (parent);
18362f581560SJiří Techet }
18372f581560SJiří Techet } while (c != '{' && c != EOF);
18382f581560SJiří Techet cppUngetc (c);
18392f581560SJiří Techet deleteToken (parent);
18402f581560SJiří Techet deleteToken (token);
18412f581560SJiří Techet }
18422f581560SJiří Techet
skipStatement(statementInfo * const st)18432f581560SJiří Techet static void skipStatement (statementInfo *const st)
18442f581560SJiří Techet {
18452f581560SJiří Techet st->declaration = DECL_IGNORE;
18462f581560SJiří Techet skipToOneOf (";");
18472f581560SJiří Techet }
18482f581560SJiří Techet
processAnnotation(statementInfo * const st)18492f581560SJiří Techet static void processAnnotation (statementInfo *const st)
18502f581560SJiří Techet {
18512f581560SJiří Techet st->declaration = DECL_ANNOTATION;
18522f581560SJiří Techet }
18532f581560SJiří Techet
processInterface(statementInfo * const st)18542f581560SJiří Techet static void processInterface (statementInfo *const st)
18552f581560SJiří Techet {
18562f581560SJiří Techet st->declaration = DECL_INTERFACE;
18572f581560SJiří Techet }
18582f581560SJiří Techet
checkIsClassEnum(statementInfo * const st,const declType decl)18592f581560SJiří Techet static void checkIsClassEnum (statementInfo *const st, const declType decl)
18602f581560SJiří Techet {
18612f581560SJiří Techet st->declaration = decl;
18622f581560SJiří Techet }
18632f581560SJiří Techet
processToken(tokenInfo * const token,statementInfo * const st)18642f581560SJiří Techet static void processToken (tokenInfo *const token, statementInfo *const st)
18652f581560SJiří Techet {
18662f581560SJiří Techet switch ((int)token->keyword) /* is it a reserved word? */
18672f581560SJiří Techet {
18682f581560SJiří Techet default: break;
18692f581560SJiří Techet
18702f581560SJiří Techet case KEYWORD_NONE: processName (st); break;
18712f581560SJiří Techet case KEYWORD_ABSTRACT: st->implementation = IMP_ABSTRACT; break;
18722f581560SJiří Techet case KEYWORD_ATTRIBUTE: skipParens (); initToken (token); break;
18732f581560SJiří Techet case KEYWORD_CATCH: skipParens (); skipBraces (); break;
18742f581560SJiří Techet case KEYWORD_CHAR: st->declaration = DECL_BASE; break;
18752f581560SJiří Techet case KEYWORD_CLASS: checkIsClassEnum (st, DECL_CLASS); break;
18762f581560SJiří Techet case KEYWORD_CONST: st->declaration = DECL_BASE; break;
18772f581560SJiří Techet case KEYWORD_DOUBLE: st->declaration = DECL_BASE; break;
18782f581560SJiří Techet case KEYWORD_ENUM: st->declaration = DECL_ENUM; break;
18792f581560SJiří Techet case KEYWORD_EXTENDS: readParents (st, '.');
18802f581560SJiří Techet setToken (st, TOKEN_NONE); break;
18812f581560SJiří Techet case KEYWORD_FLOAT: st->declaration = DECL_BASE; break;
18822f581560SJiří Techet case KEYWORD_FUNCTION: st->declaration = DECL_BASE; break;
18832f581560SJiří Techet case KEYWORD_FRIEND: st->scope = SCOPE_FRIEND; break;
18842f581560SJiří Techet case KEYWORD_GOTO: skipStatement (st); break;
18852f581560SJiří Techet case KEYWORD_IMPLEMENTS:readParents (st, '.');
18862f581560SJiří Techet setToken (st, TOKEN_NONE); break;
18872f581560SJiří Techet case KEYWORD_IMPORT:
18882f581560SJiří Techet if (isInputLanguage (Lang_java))
18892f581560SJiří Techet readPackageOrNamespace (st, DECL_PACKAGEREF, true);
18902f581560SJiří Techet else
18912f581560SJiří Techet skipStatement (st);
18922f581560SJiří Techet break;
18932f581560SJiří Techet case KEYWORD_INT: st->declaration = DECL_BASE; break;
18942f581560SJiří Techet case KEYWORD_INTERFACE: processInterface (st); break;
18952f581560SJiří Techet case KEYWORD_LONG: st->declaration = DECL_BASE; break;
18962f581560SJiří Techet case KEYWORD_OPERATOR: readOperator (st); break;
18972f581560SJiří Techet case KEYWORD_MIXIN: st->declaration = DECL_MIXIN; break;
18982f581560SJiří Techet case KEYWORD_PRIVATE: setAccess (st, ACCESS_PRIVATE); break;
18992f581560SJiří Techet case KEYWORD_PROTECTED: setAccess (st, ACCESS_PROTECTED); break;
19002f581560SJiří Techet case KEYWORD_PUBLIC: setAccess (st, ACCESS_PUBLIC); break;
19012f581560SJiří Techet case KEYWORD_RETURN: skipStatement (st); break;
19022f581560SJiří Techet case KEYWORD_SHORT: st->declaration = DECL_BASE; break;
19032f581560SJiří Techet case KEYWORD_SIGNED: st->declaration = DECL_BASE; break;
19042f581560SJiří Techet case KEYWORD_STRING: st->declaration = DECL_BASE; break;
19052f581560SJiří Techet case KEYWORD_STRUCT: checkIsClassEnum (st, DECL_STRUCT); break;
19062f581560SJiří Techet case KEYWORD_THROWS: discardTypeList (token); break;
19072f581560SJiří Techet case KEYWORD_UNION: st->declaration = DECL_UNION; break;
19082f581560SJiří Techet case KEYWORD_UNSIGNED: st->declaration = DECL_BASE; break;
19092f581560SJiří Techet case KEYWORD_USING: st->declaration = DECL_USING; break;
19102f581560SJiří Techet case KEYWORD_VOID: st->declaration = DECL_BASE; break;
19112f581560SJiří Techet case KEYWORD_VOLATILE: st->declaration = DECL_BASE; break;
19122f581560SJiří Techet case KEYWORD_VERSION: readVersion(st); break;
19132f581560SJiří Techet case KEYWORD_VIRTUAL: st->implementation = IMP_VIRTUAL; break;
19142f581560SJiří Techet case KEYWORD_WCHAR_T: st->declaration = DECL_BASE; break;
19152f581560SJiří Techet case KEYWORD_TEMPLATE:
19162f581560SJiří Techet if (isInputLanguage (Lang_d))
19172f581560SJiří Techet st->declaration = DECL_TEMPLATE;
19182f581560SJiří Techet break;
19192f581560SJiří Techet case KEYWORD_NAMESPACE: readPackageOrNamespace (st, DECL_NAMESPACE, false); break;
19202f581560SJiří Techet case KEYWORD_MODULE:
19212f581560SJiří Techet case KEYWORD_PACKAGE: readPackageOrNamespace (st, DECL_PACKAGE, false); break;
19222f581560SJiří Techet
19232f581560SJiří Techet case KEYWORD_EVENT:
19242f581560SJiří Techet if (isInputLanguage (Lang_csharp))
19252f581560SJiří Techet st->declaration = DECL_EVENT;
19262f581560SJiří Techet break;
19272f581560SJiří Techet
19282f581560SJiří Techet case KEYWORD_ALIAS:
19292f581560SJiří Techet case KEYWORD_TYPEDEF:
19302f581560SJiří Techet reinitStatement (st, false);
19312f581560SJiří Techet st->scope = SCOPE_TYPEDEF;
19322f581560SJiří Techet break;
19332f581560SJiří Techet
19342f581560SJiří Techet case KEYWORD_EXTERN:
19352f581560SJiří Techet if (! isInputLanguage (Lang_csharp) || !st->gotName)
19362f581560SJiří Techet {
19372f581560SJiří Techet reinitStatement (st, false);
19382f581560SJiří Techet st->scope = SCOPE_EXTERN;
19392f581560SJiří Techet st->declaration = DECL_BASE;
19402f581560SJiří Techet }
19412f581560SJiří Techet break;
19422f581560SJiří Techet
19432f581560SJiří Techet case KEYWORD_STATIC:
19442f581560SJiří Techet if (! (isInputLanguage (Lang_java) || isInputLanguage (Lang_csharp)))
19452f581560SJiří Techet {
19462f581560SJiří Techet reinitStatement (st, false);
19472f581560SJiří Techet st->scope = SCOPE_STATIC;
19482f581560SJiří Techet st->declaration = DECL_BASE;
19492f581560SJiří Techet }
19502f581560SJiří Techet break;
19512f581560SJiří Techet
19522f581560SJiří Techet case KEYWORD_FOR:
19532f581560SJiří Techet case KEYWORD_FOREACH:
19542f581560SJiří Techet case KEYWORD_IF:
19552f581560SJiří Techet case KEYWORD_SWITCH:
19562f581560SJiří Techet case KEYWORD_WHILE:
19572f581560SJiří Techet {
19582f581560SJiří Techet int c = skipToNonWhite ();
19592f581560SJiří Techet if (c == '(')
19602f581560SJiří Techet skipToMatch ("()");
19612f581560SJiří Techet break;
19622f581560SJiří Techet }
19632f581560SJiří Techet }
19642f581560SJiří Techet }
19652f581560SJiří Techet
19662f581560SJiří Techet /*
19672f581560SJiří Techet * Parenthesis handling functions
19682f581560SJiří Techet */
19692f581560SJiří Techet
restartStatement(statementInfo * const st)19702f581560SJiří Techet static void restartStatement (statementInfo *const st)
19712f581560SJiří Techet {
19722f581560SJiří Techet tokenInfo *const save = newToken ();
19732f581560SJiří Techet tokenInfo *token = activeToken (st);
19742f581560SJiří Techet
19752f581560SJiří Techet copyToken (save, token);
19762f581560SJiří Techet DebugStatement ( if (debug (DEBUG_PARSE)) printf ("<ES>");)
19772f581560SJiří Techet reinitStatement (st, false);
19782f581560SJiří Techet token = activeToken (st);
19792f581560SJiří Techet copyToken (token, save);
19802f581560SJiří Techet deleteToken (save);
19812f581560SJiří Techet processToken (token, st);
19822f581560SJiří Techet }
19832f581560SJiří Techet
19842f581560SJiří Techet /* Skips over a mem-initializer-list of a ctor-initializer, defined as:
19852f581560SJiří Techet *
19862f581560SJiří Techet * mem-initializer-list:
19872f581560SJiří Techet * mem-initializer, mem-initializer-list
19882f581560SJiří Techet *
19892f581560SJiří Techet * mem-initializer:
19902f581560SJiří Techet * [::] [nested-name-spec] class-name (...)
19912f581560SJiří Techet * identifier
19922f581560SJiří Techet */
skipMemIntializerList(tokenInfo * const token)19932f581560SJiří Techet static void skipMemIntializerList (tokenInfo *const token)
19942f581560SJiří Techet {
19952f581560SJiří Techet int c;
19962f581560SJiří Techet
19972f581560SJiří Techet do
19982f581560SJiří Techet {
19992f581560SJiří Techet c = skipToNonWhite ();
20002f581560SJiří Techet while (cppIsident1 (c) || c == ':')
20012f581560SJiří Techet {
20022f581560SJiří Techet if (c != ':')
20032f581560SJiří Techet readIdentifier (token, c);
20042f581560SJiří Techet c = skipToNonWhite ();
20052f581560SJiří Techet }
20062f581560SJiří Techet if (c == '<')
20072f581560SJiří Techet {
20082f581560SJiří Techet skipToMatch ("<>");
20092f581560SJiří Techet c = skipToNonWhite ();
20102f581560SJiří Techet }
20112f581560SJiří Techet if (c == '(')
20122f581560SJiří Techet {
20132f581560SJiří Techet skipToMatch ("()");
20142f581560SJiří Techet c = skipToNonWhite ();
20152f581560SJiří Techet }
20162f581560SJiří Techet } while (c == ',');
20172f581560SJiří Techet cppUngetc (c);
20182f581560SJiří Techet }
20192f581560SJiří Techet
2020d9071cadSJiří Techet /* Skips over characters following the parameter list.
2021d9071cadSJiří Techet * Originally written for C++, may contain unnecessary stuff.
20222f581560SJiří Techet *
2023d9071cadSJiří Techet * C#:
2024d9071cadSJiří Techet * public C(double x) : base(x) {}
20252f581560SJiří Techet */
skipPostArgumentStuff(statementInfo * const st,parenInfo * const info)20262f581560SJiří Techet static bool skipPostArgumentStuff (
20272f581560SJiří Techet statementInfo *const st, parenInfo *const info)
20282f581560SJiří Techet {
20292f581560SJiří Techet tokenInfo *const token = activeToken (st);
20302f581560SJiří Techet unsigned int parameters = info->parameterCount;
20312f581560SJiří Techet unsigned int elementCount = 0;
20322f581560SJiří Techet bool restart = false;
20332f581560SJiří Techet bool end = false;
20342f581560SJiří Techet int c = skipToNonWhite ();
20352f581560SJiří Techet
20362f581560SJiří Techet do
20372f581560SJiří Techet {
20382f581560SJiří Techet switch (c)
20392f581560SJiří Techet {
20402f581560SJiří Techet case ')': break;
20412f581560SJiří Techet case ':': skipMemIntializerList (token);break; /* ctor-initializer */
20422f581560SJiří Techet case '[': skipToMatch ("[]"); break;
20432f581560SJiří Techet case '=': cppUngetc (c); end = true; break;
20442f581560SJiří Techet case '{': cppUngetc (c); end = true; break;
20452f581560SJiří Techet case '}': cppUngetc (c); end = true; break;
20462f581560SJiří Techet
20472f581560SJiří Techet case '(':
20482f581560SJiří Techet if (elementCount > 0)
20492f581560SJiří Techet ++elementCount;
20502f581560SJiří Techet skipToMatch ("()");
20512f581560SJiří Techet break;
20522f581560SJiří Techet
20532f581560SJiří Techet case ';':
20542f581560SJiří Techet if (parameters == 0 || elementCount < 2)
20552f581560SJiří Techet {
20562f581560SJiří Techet cppUngetc (c);
20572f581560SJiří Techet end = true;
20582f581560SJiří Techet }
20592f581560SJiří Techet else if (--parameters == 0)
20602f581560SJiří Techet end = true;
20612f581560SJiří Techet break;
20622f581560SJiří Techet
20632f581560SJiří Techet default:
20642f581560SJiří Techet if (cppIsident1 (c))
20652f581560SJiří Techet {
20662f581560SJiří Techet readIdentifier (token, c);
20672f581560SJiří Techet switch (token->keyword)
20682f581560SJiří Techet {
20692f581560SJiří Techet case KEYWORD_ATTRIBUTE: skipParens (); break;
20702f581560SJiří Techet case KEYWORD_THROW: skipParens (); break;
20712f581560SJiří Techet case KEYWORD_IF: if (isInputLanguage (Lang_d)) skipParens (); break;
20722f581560SJiří Techet case KEYWORD_TRY: break;
20732f581560SJiří Techet
20742f581560SJiří Techet case KEYWORD_CONST:
20752f581560SJiří Techet case KEYWORD_VOLATILE:
20762f581560SJiří Techet if (vStringLength (Signature) > 0)
20772f581560SJiří Techet {
20782f581560SJiří Techet vStringPut (Signature, ' ');
20792f581560SJiří Techet vStringCat (Signature, token->name);
20802f581560SJiří Techet }
20812f581560SJiří Techet break;
20822f581560SJiří Techet case KEYWORD_ALIAS:
20832f581560SJiří Techet case KEYWORD_CATCH:
20842f581560SJiří Techet case KEYWORD_CLASS:
20852f581560SJiří Techet case KEYWORD_EXPLICIT:
20862f581560SJiří Techet case KEYWORD_EXTERN:
20872f581560SJiří Techet case KEYWORD_FRIEND:
20882f581560SJiří Techet case KEYWORD_INLINE:
20892f581560SJiří Techet case KEYWORD_MUTABLE:
20902f581560SJiří Techet case KEYWORD_NAMESPACE:
20912f581560SJiří Techet case KEYWORD_NEW:
20922f581560SJiří Techet case KEYWORD_OPERATOR:
20932f581560SJiří Techet case KEYWORD_OVERLOAD:
20942f581560SJiří Techet case KEYWORD_PRIVATE:
20952f581560SJiří Techet case KEYWORD_PROTECTED:
20962f581560SJiří Techet case KEYWORD_PUBLIC:
20972f581560SJiří Techet case KEYWORD_STATIC:
20982f581560SJiří Techet case KEYWORD_TEMPLATE:
20992f581560SJiří Techet case KEYWORD_TYPEDEF:
21002f581560SJiří Techet case KEYWORD_TYPENAME:
21012f581560SJiří Techet case KEYWORD_USING:
21022f581560SJiří Techet case KEYWORD_VIRTUAL:
21032f581560SJiří Techet /* Never allowed within parameter declarations. */
21042f581560SJiří Techet restart = true;
21052f581560SJiří Techet end = true;
21062f581560SJiří Techet break;
21072f581560SJiří Techet
21082f581560SJiří Techet default:
21096afc0c60SJiří Techet if (isType (token, TOKEN_NONE))
21102f581560SJiří Techet ;
21112f581560SJiří Techet else
21122f581560SJiří Techet {
21132f581560SJiří Techet /* If we encounter any other identifier immediately
21142f581560SJiří Techet * following an empty parameter list, this is almost
21152f581560SJiří Techet * certainly one of those Microsoft macro "thingies"
21162f581560SJiří Techet * that the automatic source code generation sticks
21172f581560SJiří Techet * in. Terminate the current statement.
21182f581560SJiří Techet */
21192f581560SJiří Techet restart = true;
21202f581560SJiří Techet end = true;
21212f581560SJiří Techet }
21222f581560SJiří Techet break;
21232f581560SJiří Techet }
21242f581560SJiří Techet }
21252f581560SJiří Techet }
21262f581560SJiří Techet if (! end)
21272f581560SJiří Techet {
21282f581560SJiří Techet c = skipToNonWhite ();
21292f581560SJiří Techet if (c == EOF)
21302f581560SJiří Techet end = true;
21312f581560SJiří Techet }
21322f581560SJiří Techet } while (! end);
21332f581560SJiří Techet
21342f581560SJiří Techet if (restart)
21352f581560SJiří Techet restartStatement (st);
21362f581560SJiří Techet else
21372f581560SJiří Techet setToken (st, TOKEN_NONE);
21382f581560SJiří Techet
21392f581560SJiří Techet return (bool) (c != EOF);
21402f581560SJiří Techet }
21412f581560SJiří Techet
skipJavaThrows(statementInfo * const st)21422f581560SJiří Techet static void skipJavaThrows (statementInfo *const st)
21432f581560SJiří Techet {
21442f581560SJiří Techet tokenInfo *const token = activeToken (st);
21452f581560SJiří Techet int c = skipToNonWhite ();
21462f581560SJiří Techet
21472f581560SJiří Techet if (cppIsident1 (c))
21482f581560SJiří Techet {
21492f581560SJiří Techet readIdentifier (token, c);
21502f581560SJiří Techet if (token->keyword == KEYWORD_THROWS)
21512f581560SJiří Techet {
21522f581560SJiří Techet do
21532f581560SJiří Techet {
21542f581560SJiří Techet c = skipToNonWhite ();
21552f581560SJiří Techet if (cppIsident1 (c))
21562f581560SJiří Techet {
21572f581560SJiří Techet readIdentifier (token, c);
21582f581560SJiří Techet c = skipToNonWhite ();
21592f581560SJiří Techet }
21602f581560SJiří Techet } while (c == '.' || c == ',');
21612f581560SJiří Techet }
21622f581560SJiří Techet }
21632f581560SJiří Techet cppUngetc (c);
21642f581560SJiří Techet setToken (st, TOKEN_NONE);
21652f581560SJiří Techet }
21662f581560SJiří Techet
analyzePostParens(statementInfo * const st,parenInfo * const info)21672f581560SJiří Techet static void analyzePostParens (statementInfo *const st, parenInfo *const info)
21682f581560SJiří Techet {
21692f581560SJiří Techet const unsigned long inputLineNumber = getInputLineNumber ();
21702f581560SJiří Techet int c = skipToNonWhite ();
21712f581560SJiří Techet
21722f581560SJiří Techet cppUngetc (c);
21732f581560SJiří Techet if (isOneOf (c, "{;,="))
21742f581560SJiří Techet ;
21752f581560SJiří Techet else if (isInputLanguage (Lang_java)) {
21762f581560SJiří Techet
21772f581560SJiří Techet if (!insideAnnotationBody(st)) {
21782f581560SJiří Techet skipJavaThrows (st);
21792f581560SJiří Techet }
21802f581560SJiří Techet } else {
21812f581560SJiří Techet if (! skipPostArgumentStuff (st, info))
21822f581560SJiří Techet {
21832f581560SJiří Techet verbose (
21842f581560SJiří Techet "%s: confusing argument declarations beginning at line %lu\n",
21852f581560SJiří Techet getInputFileName (), inputLineNumber);
21862f581560SJiří Techet longjmp (Exception, (int) ExceptionFormattingError);
21872f581560SJiří Techet }
21882f581560SJiří Techet }
21892f581560SJiří Techet }
21902f581560SJiří Techet
languageSupportsGenerics(void)21912f581560SJiří Techet static bool languageSupportsGenerics (void)
21922f581560SJiří Techet {
21936afc0c60SJiří Techet return (bool) (isInputLanguage (Lang_csharp) || isInputLanguage (Lang_java));
21942f581560SJiří Techet }
21952f581560SJiří Techet
processAngleBracket(void)21962f581560SJiří Techet static void processAngleBracket (void)
21972f581560SJiří Techet {
21982f581560SJiří Techet int c = cppGetc ();
21992f581560SJiří Techet if (c == '>') {
22002f581560SJiří Techet /* already found match for template */
22012f581560SJiří Techet } else if (languageSupportsGenerics () && c != '<' && c != '=') {
22022f581560SJiří Techet /* this is a template */
22032f581560SJiří Techet cppUngetc (c);
22042f581560SJiří Techet skipToMatch ("<>");
22052f581560SJiří Techet } else if (c == '<') {
22062f581560SJiří Techet /* skip "<<" or "<<=". */
22072f581560SJiří Techet c = cppGetc ();
22082f581560SJiří Techet if (c != '=') {
22092f581560SJiří Techet cppUngetc (c);
22102f581560SJiří Techet }
22112f581560SJiří Techet } else {
22122f581560SJiří Techet cppUngetc (c);
22132f581560SJiří Techet }
22142f581560SJiří Techet }
22152f581560SJiří Techet
parseJavaAnnotation(statementInfo * const st)22162f581560SJiří Techet static void parseJavaAnnotation (statementInfo *const st)
22172f581560SJiří Techet {
22182f581560SJiří Techet /*
22192f581560SJiří Techet * @Override
22202f581560SJiří Techet * @Target(ElementType.METHOD)
22212f581560SJiří Techet * @SuppressWarnings(value = "unchecked")
22222f581560SJiří Techet *
22232f581560SJiří Techet * But watch out for "@interface"!
22242f581560SJiří Techet */
22252f581560SJiří Techet tokenInfo *const token = activeToken (st);
22262f581560SJiří Techet
22272f581560SJiří Techet int c = skipToNonWhite ();
22282f581560SJiří Techet readIdentifier (token, c);
22292f581560SJiří Techet if (token->keyword == KEYWORD_INTERFACE)
22302f581560SJiří Techet {
22312f581560SJiří Techet /* Oops. This was actually "@interface" defining a new annotation. */
22322f581560SJiří Techet processAnnotation(st);
22332f581560SJiří Techet }
22342f581560SJiří Techet else
22352f581560SJiří Techet {
22362f581560SJiří Techet /* Bug #1691412: skip any annotation arguments. */
22372f581560SJiří Techet skipParens ();
22382f581560SJiří Techet }
22392f581560SJiří Techet }
22402f581560SJiří Techet
parseParens(statementInfo * const st,parenInfo * const info)22412f581560SJiří Techet static int parseParens (statementInfo *const st, parenInfo *const info)
22422f581560SJiří Techet {
22432f581560SJiří Techet tokenInfo *const token = activeToken (st);
22442f581560SJiří Techet unsigned int identifierCount = 0;
22452f581560SJiří Techet unsigned int depth = 1;
22462f581560SJiří Techet bool firstChar = true;
22472f581560SJiří Techet int nextChar = '\0';
22482f581560SJiří Techet
22492f581560SJiří Techet CollectingSignature = true;
22502f581560SJiří Techet vStringClear (Signature);
22512f581560SJiří Techet vStringPut (Signature, '(');
22522f581560SJiří Techet info->parameterCount = 1;
22532f581560SJiří Techet do
22542f581560SJiří Techet {
22552f581560SJiří Techet int c = skipToNonWhite ();
22562f581560SJiří Techet vStringPut (Signature, c);
22572f581560SJiří Techet
22582f581560SJiří Techet switch (c)
22592f581560SJiří Techet {
22602f581560SJiří Techet case '^':
22612f581560SJiří Techet break;
22622f581560SJiří Techet
22632f581560SJiří Techet case '&':
22642f581560SJiří Techet case '*':
22652f581560SJiří Techet info->isPointer = true;
22662f581560SJiří Techet if (identifierCount == 0)
22672f581560SJiří Techet info->isParamList = false;
22682f581560SJiří Techet initToken (token);
22692f581560SJiří Techet break;
22702f581560SJiří Techet
22712f581560SJiří Techet case ':':
22722f581560SJiří Techet break;
22732f581560SJiří Techet
22742f581560SJiří Techet case '.':
22752f581560SJiří Techet info->isNameCandidate = false;
22762f581560SJiří Techet c = cppGetc ();
22772f581560SJiří Techet if (c != '.')
22782f581560SJiří Techet cppUngetc (c);
22792f581560SJiří Techet else
22802f581560SJiří Techet {
22812f581560SJiří Techet c = cppGetc ();
22822f581560SJiří Techet if (c != '.')
22832f581560SJiří Techet cppUngetc (c);
22842f581560SJiří Techet else
22852f581560SJiří Techet vStringCatS (Signature, "..."); /* variable arg list */
22862f581560SJiří Techet }
22872f581560SJiří Techet break;
22882f581560SJiří Techet
22892f581560SJiří Techet case ',':
22902f581560SJiří Techet info->isNameCandidate = false;
22912f581560SJiří Techet break;
22922f581560SJiří Techet
22932f581560SJiří Techet case '=':
22942f581560SJiří Techet info->isNameCandidate = false;
22952f581560SJiří Techet if (firstChar)
22962f581560SJiří Techet {
22972f581560SJiří Techet info->isParamList = false;
22982f581560SJiří Techet depth = 0;
22992f581560SJiří Techet }
23002f581560SJiří Techet break;
23012f581560SJiří Techet
23022f581560SJiří Techet case '[':
23032f581560SJiří Techet skipToMatch ("[]");
23042f581560SJiří Techet break;
23052f581560SJiří Techet
23062f581560SJiří Techet case '<':
23072f581560SJiří Techet processAngleBracket ();
23082f581560SJiří Techet break;
23092f581560SJiří Techet
23102f581560SJiří Techet case ')':
23112f581560SJiří Techet if (firstChar)
23122f581560SJiří Techet info->parameterCount = 0;
23132f581560SJiří Techet --depth;
23142f581560SJiří Techet break;
23152f581560SJiří Techet
23162f581560SJiří Techet case '(':
23172f581560SJiří Techet if (firstChar)
23182f581560SJiří Techet {
23192f581560SJiří Techet info->isNameCandidate = false;
23202f581560SJiří Techet cppUngetc (c);
23212f581560SJiří Techet vStringClear (Signature);
23222f581560SJiří Techet depth = 0;
23232f581560SJiří Techet vStringChop (Signature);
23242f581560SJiří Techet }
23252f581560SJiří Techet else if (isType (token, TOKEN_PAREN_NAME))
23262f581560SJiří Techet {
23272f581560SJiří Techet c = skipToNonWhite ();
23282f581560SJiří Techet if (c == '*') /* check for function pointer */
23292f581560SJiří Techet {
23302f581560SJiří Techet skipToMatch ("()");
23312f581560SJiří Techet c = skipToNonWhite ();
23322f581560SJiří Techet if (c == '(')
23332f581560SJiří Techet skipToMatch ("()");
23342f581560SJiří Techet else
23352f581560SJiří Techet cppUngetc (c);
23362f581560SJiří Techet }
23372f581560SJiří Techet else
23382f581560SJiří Techet {
23392f581560SJiří Techet cppUngetc (c);
23402f581560SJiří Techet cppUngetc ('(');
23412f581560SJiří Techet info->nestedArgs = true;
23422f581560SJiří Techet }
23432f581560SJiří Techet }
23442f581560SJiří Techet else
23452f581560SJiří Techet ++depth;
23462f581560SJiří Techet break;
23472f581560SJiří Techet
23482f581560SJiří Techet default:
23492f581560SJiří Techet if (c == '@' && isInputLanguage (Lang_java))
23502f581560SJiří Techet {
23512f581560SJiří Techet parseJavaAnnotation(st);
23522f581560SJiří Techet }
23532f581560SJiří Techet else if (cppIsident1 (c))
23542f581560SJiří Techet {
23552f581560SJiří Techet readIdentifier (token, c);
23562f581560SJiří Techet if (isType (token, TOKEN_NAME) && info->isNameCandidate)
23572f581560SJiří Techet token->type = TOKEN_PAREN_NAME;
23582f581560SJiří Techet else if (isType (token, TOKEN_KEYWORD))
23592f581560SJiří Techet {
23602f581560SJiří Techet if (token->keyword != KEYWORD_CONST &&
23612f581560SJiří Techet token->keyword != KEYWORD_VOLATILE)
23622f581560SJiří Techet {
23632f581560SJiří Techet info->isNameCandidate = false;
23642f581560SJiří Techet }
23652f581560SJiří Techet }
23662f581560SJiří Techet }
23672f581560SJiří Techet else
23682f581560SJiří Techet {
23692f581560SJiří Techet info->isParamList = false;
23702f581560SJiří Techet info->isNameCandidate = false;
23712f581560SJiří Techet info->invalidContents = true;
23722f581560SJiří Techet }
23732f581560SJiří Techet break;
23742f581560SJiří Techet }
23752f581560SJiří Techet firstChar = false;
23766afc0c60SJiří Techet } while (! info->nestedArgs && depth > 0 && info->isNameCandidate);
23772f581560SJiří Techet
23782f581560SJiří Techet if (! info->nestedArgs) while (depth > 0)
23792f581560SJiří Techet {
23802f581560SJiří Techet skipToMatch ("()");
23812f581560SJiří Techet --depth;
23822f581560SJiří Techet }
23832f581560SJiří Techet
23842f581560SJiří Techet if (! info->isNameCandidate)
23852f581560SJiří Techet initToken (token);
23862f581560SJiří Techet
23872f581560SJiří Techet CollectingSignature = false;
23882f581560SJiří Techet return nextChar;
23892f581560SJiří Techet }
23902f581560SJiří Techet
initParenInfo(parenInfo * const info)23912f581560SJiří Techet static void initParenInfo (parenInfo *const info)
23922f581560SJiří Techet {
23932f581560SJiří Techet info->isPointer = false;
23942f581560SJiří Techet info->isParamList = true;
23952f581560SJiří Techet info->isNameCandidate = true;
23962f581560SJiří Techet info->invalidContents = false;
23972f581560SJiří Techet info->nestedArgs = false;
23982f581560SJiří Techet info->parameterCount = 0;
23992f581560SJiří Techet }
24002f581560SJiří Techet
analyzeParens(statementInfo * const st)24012f581560SJiří Techet static void analyzeParens (statementInfo *const st)
24022f581560SJiří Techet {
24032f581560SJiří Techet tokenInfo *const prev = prevToken (st, 1);
24042f581560SJiří Techet
24056afc0c60SJiří Techet if (st->inFunction && !st->assignment)
24062f581560SJiří Techet st->notVariable = true;
24072f581560SJiří Techet
24082f581560SJiří Techet if (! isType (prev, TOKEN_NONE)) /* in case of ignored enclosing macros */
24092f581560SJiří Techet {
24102f581560SJiří Techet tokenInfo *const token = activeToken (st);
24112f581560SJiří Techet parenInfo info;
24122f581560SJiří Techet int c;
24132f581560SJiří Techet
24142f581560SJiří Techet initParenInfo (&info);
24152f581560SJiří Techet parseParens (st, &info);
24162f581560SJiří Techet c = skipToNonWhite ();
24172f581560SJiří Techet cppUngetc (c);
24182f581560SJiří Techet if (info.invalidContents)
24192f581560SJiří Techet {
24202f581560SJiří Techet /* FIXME: This breaks parsing of variable instantiations that have
24212f581560SJiří Techet constants as parameters: Type var(0) or Type var("..."). */
24222f581560SJiří Techet reinitStatement (st, false);
24232f581560SJiří Techet }
24242f581560SJiří Techet else if (info.isNameCandidate && isType (token, TOKEN_PAREN_NAME) &&
24252f581560SJiří Techet ! st->gotParenName &&
24262f581560SJiří Techet (! info.isParamList || ! st->haveQualifyingName ||
24272f581560SJiří Techet c == '(' ||
24286afc0c60SJiří Techet (c == '=' && st->implementation != IMP_VIRTUAL) ||
24292f581560SJiří Techet (st->declaration == DECL_NONE && isOneOf (c, ",;"))))
24302f581560SJiří Techet {
24312f581560SJiří Techet token->type = TOKEN_NAME;
24322f581560SJiří Techet processName (st);
24332f581560SJiří Techet st->gotParenName = true;
24342f581560SJiří Techet if (! (c == '(' && info.nestedArgs))
24352f581560SJiří Techet st->isPointer = info.isPointer;
24362f581560SJiří Techet if (isInputLanguage(Lang_d) && c == '(' && isType (prev, TOKEN_NAME))
24372f581560SJiří Techet {
24382f581560SJiří Techet st->declaration = DECL_FUNCTION_TEMPLATE;
24392f581560SJiří Techet copyToken (st->blockName, prev);
24402f581560SJiří Techet }
24412f581560SJiří Techet }
24422f581560SJiří Techet else if (! st->gotArgs && info.isParamList)
24432f581560SJiří Techet {
24442f581560SJiří Techet st->gotArgs = true;
24452f581560SJiří Techet setToken (st, TOKEN_ARGS);
24462f581560SJiří Techet advanceToken (st);
24472f581560SJiří Techet if (st->scope != SCOPE_TYPEDEF)
24482f581560SJiří Techet analyzePostParens (st, &info);
24492f581560SJiří Techet }
24502f581560SJiří Techet else
24512f581560SJiří Techet setToken (st, TOKEN_NONE);
24522f581560SJiří Techet }
24532f581560SJiří Techet }
24542f581560SJiří Techet
24552f581560SJiří Techet /*
24562f581560SJiří Techet * Token parsing functions
24572f581560SJiří Techet */
24582f581560SJiří Techet
addContext(statementInfo * const st,const tokenInfo * const token)24592f581560SJiří Techet static void addContext (statementInfo *const st, const tokenInfo* const token)
24602f581560SJiří Techet {
24612f581560SJiří Techet if (isType (token, TOKEN_NAME))
24622f581560SJiří Techet {
24632f581560SJiří Techet if (vStringLength (st->context->name) > 0)
24642f581560SJiří Techet {
24652f581560SJiří Techet vStringPut (st->context->name, '.');
24662f581560SJiří Techet }
24672f581560SJiří Techet vStringCat (st->context->name, token->name);
24682f581560SJiří Techet st->context->type = TOKEN_NAME;
24692f581560SJiří Techet }
24702f581560SJiří Techet }
24712f581560SJiří Techet
inheritingDeclaration(declType decl)24722f581560SJiří Techet static bool inheritingDeclaration (declType decl)
24732f581560SJiří Techet {
24742f581560SJiří Techet /* enum base types */
24752f581560SJiří Techet if (decl == DECL_ENUM)
24762f581560SJiří Techet {
24776afc0c60SJiří Techet return (bool) (isInputLanguage (Lang_csharp) || isInputLanguage (Lang_d));
24782f581560SJiří Techet }
24792f581560SJiří Techet return (bool) (
24802f581560SJiří Techet decl == DECL_CLASS ||
24812f581560SJiří Techet decl == DECL_STRUCT ||
24822f581560SJiří Techet decl == DECL_INTERFACE);
24832f581560SJiří Techet }
24842f581560SJiří Techet
processColon(statementInfo * const st)24852f581560SJiří Techet static void processColon (statementInfo *const st)
24862f581560SJiří Techet {
24876afc0c60SJiří Techet int c = skipToNonWhite ();
24882f581560SJiří Techet const bool doubleColon = (bool) (c == ':');
24892f581560SJiří Techet
24902f581560SJiří Techet if (doubleColon)
24912f581560SJiří Techet {
24922f581560SJiří Techet setToken (st, TOKEN_DOUBLE_COLON);
24932f581560SJiří Techet st->haveQualifyingName = false;
24942f581560SJiří Techet }
24952f581560SJiří Techet else
24962f581560SJiří Techet {
24972f581560SJiří Techet cppUngetc (c);
24986afc0c60SJiří Techet if ((isInputLanguage (Lang_csharp) || isInputLanguage (Lang_d)) &&
24992f581560SJiří Techet inheritingDeclaration (st->declaration))
25002f581560SJiří Techet {
25012f581560SJiří Techet readParents (st, ':');
25022f581560SJiří Techet }
25032f581560SJiří Techet else if (parentDecl (st) == DECL_STRUCT)
25042f581560SJiří Techet {
25052f581560SJiří Techet c = skipToOneOf (",;");
25062f581560SJiří Techet if (c == ',')
25072f581560SJiří Techet setToken (st, TOKEN_COMMA);
25082f581560SJiří Techet else if (c == ';')
25092f581560SJiří Techet setToken (st, TOKEN_SEMICOLON);
25102f581560SJiří Techet }
25112f581560SJiří Techet else
25122f581560SJiří Techet {
25132f581560SJiří Techet const tokenInfo *const prev = prevToken (st, 1);
25142f581560SJiří Techet const tokenInfo *const prev2 = prevToken (st, 2);
25152f581560SJiří Techet if (prev->keyword == KEYWORD_DEFAULT ||
25162f581560SJiří Techet prev2->keyword == KEYWORD_CASE)
25172f581560SJiří Techet {
25182f581560SJiří Techet reinitStatement (st, false);
25192f581560SJiří Techet }
25202f581560SJiří Techet else if (st->parent != NULL)
25212f581560SJiří Techet {
25222f581560SJiří Techet if (prevToken (st->parent, 1)->keyword != KEYWORD_SWITCH)
25232f581560SJiří Techet makeTag (prev, st, false, TAG_LABEL);
25242f581560SJiří Techet reinitStatement (st, false);
25252f581560SJiří Techet }
25262f581560SJiří Techet }
25272f581560SJiří Techet }
25282f581560SJiří Techet }
25292f581560SJiří Techet
25302f581560SJiří Techet /* Skips over any initializing value which may follow an '=' character in a
25312f581560SJiří Techet * variable definition.
25322f581560SJiří Techet */
skipInitializer(statementInfo * const st)25332f581560SJiří Techet static int skipInitializer (statementInfo *const st)
25342f581560SJiří Techet {
25352f581560SJiří Techet bool done = false;
25362f581560SJiří Techet int c;
25372f581560SJiří Techet
25382f581560SJiří Techet while (! done)
25392f581560SJiří Techet {
25402f581560SJiří Techet c = skipToNonWhite ();
25412f581560SJiří Techet
25422f581560SJiří Techet if (c == EOF)
25432f581560SJiří Techet longjmp (Exception, (int) ExceptionFormattingError);
25442f581560SJiří Techet else switch (c)
25452f581560SJiří Techet {
25462f581560SJiří Techet case ',':
25472f581560SJiří Techet case ';': done = true; break;
25482f581560SJiří Techet
25492f581560SJiří Techet case '0':
25502f581560SJiří Techet if (st->implementation == IMP_VIRTUAL)
25512f581560SJiří Techet st->implementation = IMP_PURE_VIRTUAL;
25522f581560SJiří Techet break;
25532f581560SJiří Techet
25542f581560SJiří Techet case '[': skipToMatch ("[]"); break;
25552f581560SJiří Techet case '(': skipToMatch ("()"); break;
25562f581560SJiří Techet case '{': skipToMatch ("{}"); break;
25572f581560SJiří Techet case '<': processAngleBracket(); break;
25582f581560SJiří Techet
25592f581560SJiří Techet case '}':
25602f581560SJiří Techet if (insideEnumBody (st))
25612f581560SJiří Techet done = true;
25622f581560SJiří Techet else if (! cppIsBraceFormat ())
25632f581560SJiří Techet {
25642f581560SJiří Techet verbose ("%s: unexpected closing brace at line %lu\n",
25652f581560SJiří Techet getInputFileName (), getInputLineNumber ());
25662f581560SJiří Techet longjmp (Exception, (int) ExceptionBraceFormattingError);
25672f581560SJiří Techet }
25682f581560SJiří Techet break;
25692f581560SJiří Techet
25702f581560SJiří Techet default: break;
25712f581560SJiří Techet }
25722f581560SJiří Techet }
25732f581560SJiří Techet return c;
25742f581560SJiří Techet }
25752f581560SJiří Techet
processInitializer(statementInfo * const st)25762f581560SJiří Techet static void processInitializer (statementInfo *const st)
25772f581560SJiří Techet {
25782f581560SJiří Techet const bool inEnumBody = insideEnumBody (st);
25792f581560SJiří Techet int c = cppGetc ();
25802f581560SJiří Techet
25812f581560SJiří Techet if (c != '=')
25822f581560SJiří Techet {
25832f581560SJiří Techet cppUngetc (c);
25842f581560SJiří Techet c = skipInitializer (st);
25852f581560SJiří Techet st->assignment = true;
25862f581560SJiří Techet if (c == ';')
25872f581560SJiří Techet setToken (st, TOKEN_SEMICOLON);
25882f581560SJiří Techet else if (c == ',')
25892f581560SJiří Techet setToken (st, TOKEN_COMMA);
25902f581560SJiří Techet else if (c == '}' && inEnumBody)
25912f581560SJiří Techet {
25922f581560SJiří Techet cppUngetc (c);
25932f581560SJiří Techet setToken (st, TOKEN_COMMA);
25942f581560SJiří Techet }
25952f581560SJiří Techet if (st->scope == SCOPE_EXTERN)
25962f581560SJiří Techet st->scope = SCOPE_GLOBAL;
25972f581560SJiří Techet }
25982f581560SJiří Techet }
25992f581560SJiří Techet
parseIdentifier(statementInfo * const st,const int c)26002f581560SJiří Techet static void parseIdentifier (statementInfo *const st, const int c)
26012f581560SJiří Techet {
26022f581560SJiří Techet tokenInfo *const token = activeToken (st);
26032f581560SJiří Techet
26042f581560SJiří Techet readIdentifier (token, c);
26052f581560SJiří Techet if (! isType (token, TOKEN_NONE))
26062f581560SJiří Techet processToken (token, st);
26072f581560SJiří Techet }
26082f581560SJiří Techet
parseGeneralToken(statementInfo * const st,const int c)26092f581560SJiří Techet static void parseGeneralToken (statementInfo *const st, const int c)
26102f581560SJiří Techet {
26112f581560SJiří Techet const tokenInfo *const prev = prevToken (st, 1);
26122f581560SJiří Techet
26132f581560SJiří Techet if (cppIsident1 (c) || (isInputLanguage (Lang_java) && isHighChar (c)))
26142f581560SJiří Techet {
26152f581560SJiří Techet
26162f581560SJiří Techet parseIdentifier (st, c);
26172f581560SJiří Techet if (isType (st->context, TOKEN_NAME) &&
26182f581560SJiří Techet isType (activeToken (st), TOKEN_NAME) && isType (prev, TOKEN_NAME))
26192f581560SJiří Techet {
26202f581560SJiří Techet initToken (st->context);
26212f581560SJiří Techet }
26222f581560SJiří Techet }
26232f581560SJiří Techet else if (c == '.' || c == '-')
26242f581560SJiří Techet {
26252f581560SJiří Techet if (! st->assignment)
26262f581560SJiří Techet st->notVariable = true;
26272f581560SJiří Techet if (c == '-')
26282f581560SJiří Techet {
26292f581560SJiří Techet int c2 = cppGetc ();
26302f581560SJiří Techet if (c2 != '>')
26312f581560SJiří Techet cppUngetc (c2);
26322f581560SJiří Techet }
26332f581560SJiří Techet }
26342f581560SJiří Techet else if (c == '!' || c == '>')
26352f581560SJiří Techet {
26362f581560SJiří Techet int c2 = cppGetc ();
26372f581560SJiří Techet if (c2 != '=')
26382f581560SJiří Techet cppUngetc (c2);
26392f581560SJiří Techet }
26402f581560SJiří Techet else if (c == '@' && isInputLanguage (Lang_java))
26412f581560SJiří Techet {
26422f581560SJiří Techet parseJavaAnnotation (st);
26432f581560SJiří Techet }
26449f85e64cSJiří Techet else if (c == STRING_SYMBOL) {
26452f581560SJiří Techet setToken(st, TOKEN_NONE);
26462f581560SJiří Techet }
26472f581560SJiří Techet }
26482f581560SJiří Techet
26492f581560SJiří Techet /* Reads characters from the pre-processor and assembles tokens, setting
26502f581560SJiří Techet * the current statement state.
26512f581560SJiří Techet */
nextToken(statementInfo * const st)26522f581560SJiří Techet static void nextToken (statementInfo *const st)
26532f581560SJiří Techet {
26542f581560SJiří Techet tokenInfo *token;
26552f581560SJiří Techet do
26562f581560SJiří Techet {
26572f581560SJiří Techet int c = skipToNonWhite ();
26582f581560SJiří Techet switch (c)
26592f581560SJiří Techet {
26602f581560SJiří Techet case EOF: longjmp (Exception, (int) ExceptionEOF); break;
26612f581560SJiří Techet case '(': analyzeParens (st); break;
26622f581560SJiří Techet case '<': processAngleBracket (); break;
26632f581560SJiří Techet case '*': st->haveQualifyingName = false; break;
26642f581560SJiří Techet case ',': setToken (st, TOKEN_COMMA); break;
26652f581560SJiří Techet case ':': processColon (st); break;
26662f581560SJiří Techet case ';': setToken (st, TOKEN_SEMICOLON); break;
26672f581560SJiří Techet case '=': processInitializer (st); break;
26682f581560SJiří Techet case '[': skipToMatch ("[]"); break;
26692f581560SJiří Techet case '{': setToken (st, TOKEN_BRACE_OPEN); break;
26702f581560SJiří Techet case '}': setToken (st, TOKEN_BRACE_CLOSE); break;
26712f581560SJiří Techet default: parseGeneralToken (st, c); break;
26722f581560SJiří Techet }
26732f581560SJiří Techet token = activeToken (st);
26742f581560SJiří Techet } while (isType (token, TOKEN_NONE));
26752f581560SJiří Techet }
26762f581560SJiří Techet
26772f581560SJiří Techet /*
26782f581560SJiří Techet * Scanning support functions
26792f581560SJiří Techet */
26802f581560SJiří Techet
26812f581560SJiří Techet static statementInfo *CurrentStatement = NULL;
26822f581560SJiří Techet
newStatement(statementInfo * const parent)26832f581560SJiří Techet static statementInfo *newStatement (statementInfo *const parent)
26842f581560SJiří Techet {
26852f581560SJiří Techet statementInfo *const st = xMalloc (1, statementInfo);
26862f581560SJiří Techet unsigned int i;
26872f581560SJiří Techet
26882f581560SJiří Techet for (i = 0 ; i < (unsigned int) NumTokens ; ++i)
26892f581560SJiří Techet st->token [i] = newToken ();
26902f581560SJiří Techet
26912f581560SJiří Techet st->context = newToken ();
26922f581560SJiří Techet st->blockName = newToken ();
26932f581560SJiří Techet st->parentClasses = vStringNew ();
26942f581560SJiří Techet
26952f581560SJiří Techet initStatement (st, parent);
26962f581560SJiří Techet CurrentStatement = st;
26972f581560SJiří Techet
26982f581560SJiří Techet return st;
26992f581560SJiří Techet }
27002f581560SJiří Techet
deleteStatement(void)27012f581560SJiří Techet static void deleteStatement (void)
27022f581560SJiří Techet {
27032f581560SJiří Techet statementInfo *const st = CurrentStatement;
27042f581560SJiří Techet statementInfo *const parent = st->parent;
27052f581560SJiří Techet unsigned int i;
27062f581560SJiří Techet
27072f581560SJiří Techet for (i = 0 ; i < (unsigned int) NumTokens ; ++i)
27082f581560SJiří Techet {
27092f581560SJiří Techet deleteToken (st->token [i]); st->token [i] = NULL;
27102f581560SJiří Techet }
27112f581560SJiří Techet deleteToken (st->blockName); st->blockName = NULL;
27122f581560SJiří Techet deleteToken (st->context); st->context = NULL;
27132f581560SJiří Techet vStringDelete (st->parentClasses); st->parentClasses = NULL;
27142f581560SJiří Techet eFree (st);
27152f581560SJiří Techet CurrentStatement = parent;
27162f581560SJiří Techet }
27172f581560SJiří Techet
deleteAllStatements(void)27182f581560SJiří Techet static void deleteAllStatements (void)
27192f581560SJiří Techet {
27202f581560SJiří Techet while (CurrentStatement != NULL)
27212f581560SJiří Techet deleteStatement ();
27222f581560SJiří Techet }
27232f581560SJiří Techet
isStatementEnd(const statementInfo * const st)27242f581560SJiří Techet static bool isStatementEnd (const statementInfo *const st)
27252f581560SJiří Techet {
27262f581560SJiří Techet const tokenInfo *const token = activeToken (st);
27272f581560SJiří Techet bool isEnd;
27282f581560SJiří Techet
27292f581560SJiří Techet if (isType (token, TOKEN_SEMICOLON))
27302f581560SJiří Techet isEnd = true;
27312f581560SJiří Techet else if (isType (token, TOKEN_BRACE_CLOSE))
2732*3db09da3SJiří Techet /* Java, C# and D do not require semicolons to end a block.
27332f581560SJiří Techet */
2734*3db09da3SJiří Techet isEnd = true;
27352f581560SJiří Techet else
27362f581560SJiří Techet isEnd = false;
27372f581560SJiří Techet
27382f581560SJiří Techet return isEnd;
27392f581560SJiří Techet }
27402f581560SJiří Techet
checkStatementEnd(statementInfo * const st,int corkIndex)27412f581560SJiří Techet static void checkStatementEnd (statementInfo *const st, int corkIndex)
27422f581560SJiří Techet {
27432f581560SJiří Techet const tokenInfo *const token = activeToken (st);
27442f581560SJiří Techet
27452f581560SJiří Techet tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
27462f581560SJiří Techet if (e)
27472f581560SJiří Techet e->extensionFields.endLine = token->lineNumber;
27482f581560SJiří Techet
27492f581560SJiří Techet if (isType (token, TOKEN_COMMA))
27502f581560SJiří Techet reinitStatement (st, true);
27512f581560SJiří Techet else if (isStatementEnd (st))
27522f581560SJiří Techet {
27532f581560SJiří Techet DebugStatement ( if (debug (DEBUG_PARSE)) printf ("<ES>"); )
27542f581560SJiří Techet reinitStatement (st, false);
27552f581560SJiří Techet cppEndStatement ();
27562f581560SJiří Techet }
27572f581560SJiří Techet else
27582f581560SJiří Techet {
27592f581560SJiří Techet cppBeginStatement ();
27602f581560SJiří Techet advanceToken (st);
27612f581560SJiří Techet }
27622f581560SJiří Techet }
27632f581560SJiří Techet
nest(statementInfo * const st,const unsigned int nestLevel)27642f581560SJiří Techet static void nest (statementInfo *const st, const unsigned int nestLevel)
27652f581560SJiří Techet {
27662f581560SJiří Techet switch (st->declaration)
27672f581560SJiří Techet {
27682f581560SJiří Techet case DECL_TEMPLATE:
27692f581560SJiří Techet case DECL_VERSION:
27702f581560SJiří Techet st->inFunction = false;
27712f581560SJiří Techet case DECL_CLASS:
27722f581560SJiří Techet case DECL_ENUM:
27732f581560SJiří Techet case DECL_INTERFACE:
27742f581560SJiří Techet case DECL_NAMESPACE:
27752f581560SJiří Techet case DECL_PRIVATE:
27762f581560SJiří Techet case DECL_PROTECTED:
27772f581560SJiří Techet case DECL_PUBLIC:
27782f581560SJiří Techet case DECL_STRUCT:
27792f581560SJiří Techet case DECL_UNION:
27802f581560SJiří Techet case DECL_ANNOTATION:
27812f581560SJiří Techet createTags (nestLevel, st);
27822f581560SJiří Techet break;
27832f581560SJiří Techet
27842f581560SJiří Techet case DECL_FUNCTION:
27852f581560SJiří Techet st->inFunction = true;
27862f581560SJiří Techet /* fall through */
27872f581560SJiří Techet default:
27882f581560SJiří Techet if (includeTag (TAG_LOCAL, false) || includeTag (TAG_LABEL, false))
27892f581560SJiří Techet createTags (nestLevel, st);
27902f581560SJiří Techet else
27912f581560SJiří Techet skipToMatch ("{}");
27922f581560SJiří Techet break;
27932f581560SJiří Techet }
27942f581560SJiří Techet advanceToken (st);
27952f581560SJiří Techet setToken (st, TOKEN_BRACE_CLOSE);
27962f581560SJiří Techet }
27972f581560SJiří Techet
tagCheck(statementInfo * const st)27982f581560SJiří Techet static int tagCheck (statementInfo *const st)
27992f581560SJiří Techet {
28002f581560SJiří Techet const tokenInfo *const token = activeToken (st);
28012f581560SJiří Techet const tokenInfo *const prev = prevToken (st, 1);
28022f581560SJiří Techet const tokenInfo *const prev2 = prevToken (st, 2);
28032f581560SJiří Techet int corkIndex = CORK_NIL;
28042f581560SJiří Techet
28052f581560SJiří Techet switch (token->type)
28062f581560SJiří Techet {
28072f581560SJiří Techet case TOKEN_NAME:
28082f581560SJiří Techet if (insideEnumBody (st))
28092f581560SJiří Techet corkIndex = qualifyEnumeratorTag (st, token);
28102f581560SJiří Techet if (st->declaration == DECL_MIXIN)
28112f581560SJiří Techet corkIndex = makeTag (token, st, false, TAG_MIXIN);
28122f581560SJiří Techet break;
28132f581560SJiří Techet #if 0
28142f581560SJiří Techet case TOKEN_PACKAGE:
28152f581560SJiří Techet if (st->haveQualifyingName)
28162f581560SJiří Techet corkIndex = makeTag (token, st, false, TAG_PACKAGE);
28172f581560SJiří Techet break;
28182f581560SJiří Techet #endif
28192f581560SJiří Techet case TOKEN_BRACE_OPEN:
28202f581560SJiří Techet if (isType (prev, TOKEN_ARGS))
28212f581560SJiří Techet {
28222f581560SJiří Techet if (st->declaration == DECL_TEMPLATE)
28232f581560SJiří Techet corkIndex = qualifyBlockTag (st, prev2);
28242f581560SJiří Techet else if (st->declaration == DECL_FUNCTION_TEMPLATE) {
28252f581560SJiří Techet corkIndex = qualifyFunctionTag (st, st->blockName);
28262f581560SJiří Techet }
28272f581560SJiří Techet else if (st->haveQualifyingName)
28282f581560SJiří Techet {
28292f581560SJiří Techet if (isType (prev2, TOKEN_NAME))
28302f581560SJiří Techet copyToken (st->blockName, prev2);
28312f581560SJiří Techet
28322f581560SJiří Techet /* D declaration templates */
28332f581560SJiří Techet if (isInputLanguage (Lang_d) &&
28342f581560SJiří Techet (st->declaration == DECL_CLASS || st->declaration == DECL_STRUCT ||
28352f581560SJiří Techet st->declaration == DECL_INTERFACE || st->declaration == DECL_UNION))
28362f581560SJiří Techet corkIndex = qualifyBlockTag (st, prev2);
28372f581560SJiří Techet else
28382f581560SJiří Techet {
28392f581560SJiří Techet st->declaration = DECL_FUNCTION;
28402f581560SJiří Techet corkIndex = qualifyFunctionTag (st, prev2);
28412f581560SJiří Techet }
28422f581560SJiří Techet }
28432f581560SJiří Techet }
28442f581560SJiří Techet else if (isContextualStatement (st) ||
28456d30e5b1SJiří Techet st->declaration == DECL_VERSION)
28462f581560SJiří Techet {
28472f581560SJiří Techet const tokenInfo *name_token = prev;
28482f581560SJiří Techet
28492f581560SJiří Techet if (isType (name_token, TOKEN_NAME))
28502f581560SJiří Techet copyToken (st->blockName, name_token);
28512f581560SJiří Techet else
28522f581560SJiří Techet {
28532f581560SJiří Techet /* For an anonymous struct or union we use a unique ID
28542f581560SJiří Techet * a number, so that the members can be found.
28552f581560SJiří Techet */
28562f581560SJiří Techet char buf [20]; /* length of "_anon" + digits + null */
28572f581560SJiří Techet sprintf (buf, "__anon%d", ++AnonymousID);
28582f581560SJiří Techet vStringCopyS (st->blockName->name, buf);
28592f581560SJiří Techet st->blockName->type = TOKEN_NAME;
28602f581560SJiří Techet st->blockName->keyword = KEYWORD_NONE;
28612f581560SJiří Techet }
28622f581560SJiří Techet corkIndex = qualifyBlockTag (st, name_token);
28632f581560SJiří Techet }
28642f581560SJiří Techet else if (isInputLanguage (Lang_csharp))
28652f581560SJiří Techet corkIndex = makeTag (prev, st, false, TAG_PROPERTY);
28662f581560SJiří Techet break;
28672f581560SJiří Techet
28682f581560SJiří Techet case TOKEN_KEYWORD:
28692f581560SJiří Techet
28702f581560SJiří Techet if (token->keyword == KEYWORD_DEFAULT && isType(prev, TOKEN_ARGS) && insideAnnotationBody(st)) {
28712f581560SJiří Techet corkIndex = qualifyFunctionDeclTag(st, prev2);
28722f581560SJiří Techet }
28732f581560SJiří Techet break;
28742f581560SJiří Techet
28752f581560SJiří Techet case TOKEN_SEMICOLON:
28762f581560SJiří Techet case TOKEN_COMMA:
28772f581560SJiří Techet if (insideEnumBody (st))
28782f581560SJiří Techet ;
28792f581560SJiří Techet else if (isType (prev, TOKEN_NAME))
28802f581560SJiří Techet {
28812f581560SJiří Techet if (isContextualKeyword (prev2))
28822f581560SJiří Techet corkIndex = makeTag (prev, st, true, TAG_EXTERN_VAR);
28832f581560SJiří Techet else
28842f581560SJiří Techet corkIndex = qualifyVariableTag (st, prev);
28852f581560SJiří Techet }
28862f581560SJiří Techet else if (isType (prev, TOKEN_ARGS) && isType (prev2, TOKEN_NAME))
28872f581560SJiří Techet {
28882f581560SJiří Techet if (st->isPointer || st->inFunction)
28892f581560SJiří Techet {
28902f581560SJiří Techet /* If it looks like a pointer or we are in a function body then
28912f581560SJiří Techet it's far more likely to be a variable. */
28922f581560SJiří Techet corkIndex = qualifyVariableTag (st, prev2);
28932f581560SJiří Techet }
28942f581560SJiří Techet else
28952f581560SJiří Techet corkIndex = qualifyFunctionDeclTag (st, prev2);
28962f581560SJiří Techet }
28972f581560SJiří Techet if (isInputLanguage (Lang_java) && token->type == TOKEN_SEMICOLON && insideEnumBody (st))
28982f581560SJiří Techet {
28992f581560SJiří Techet /* In Java, after an initial enum-like part,
29002f581560SJiří Techet * a semicolon introduces a class-like part.
29012f581560SJiří Techet * See Bug #1730485 for the full rationale. */
29022f581560SJiří Techet st->parent->declaration = DECL_CLASS;
29032f581560SJiří Techet }
29042f581560SJiří Techet break;
29052f581560SJiří Techet
29062f581560SJiří Techet default: break;
29072f581560SJiří Techet }
29082f581560SJiří Techet
29092f581560SJiří Techet return corkIndex;
29102f581560SJiří Techet }
29112f581560SJiří Techet
29122f581560SJiří Techet /* Parses the current file and decides whether to write out and tags that
29132f581560SJiří Techet * are discovered.
29142f581560SJiří Techet */
createTags(const unsigned int nestLevel,statementInfo * const parent)29152f581560SJiří Techet static void createTags (const unsigned int nestLevel,
29162f581560SJiří Techet statementInfo *const parent)
29172f581560SJiří Techet {
29182f581560SJiří Techet statementInfo *const st = newStatement (parent);
29192f581560SJiří Techet
29202f581560SJiří Techet DebugStatement ( if (nestLevel > 0) debugParseNest (true, nestLevel); )
29212f581560SJiří Techet while (true)
29222f581560SJiří Techet {
29232f581560SJiří Techet tokenInfo *token;
29242f581560SJiří Techet
29252f581560SJiří Techet nextToken (st);
29262f581560SJiří Techet token = activeToken (st);
29272f581560SJiří Techet if (isType (token, TOKEN_BRACE_CLOSE))
29282f581560SJiří Techet {
29292f581560SJiří Techet if (nestLevel > 0)
29302f581560SJiří Techet break;
29312f581560SJiří Techet else
29322f581560SJiří Techet {
29332f581560SJiří Techet verbose ("%s: unexpected closing brace at line %lu\n",
29342f581560SJiří Techet getInputFileName (), getInputLineNumber ());
29352f581560SJiří Techet longjmp (Exception, (int) ExceptionBraceFormattingError);
29362f581560SJiří Techet }
29372f581560SJiří Techet }
29382f581560SJiří Techet else if (isType (token, TOKEN_DOUBLE_COLON))
29392f581560SJiří Techet {
29402f581560SJiří Techet addContext (st, prevToken (st, 1));
29412f581560SJiří Techet advanceToken (st);
29422f581560SJiří Techet }
29432f581560SJiří Techet else
29442f581560SJiří Techet {
29452f581560SJiří Techet int corkIndex = tagCheck (st);
29462f581560SJiří Techet if (isType (token, TOKEN_BRACE_OPEN))
29472f581560SJiří Techet nest (st, nestLevel + 1);
29482f581560SJiří Techet checkStatementEnd (st, corkIndex);
29492f581560SJiří Techet }
29502f581560SJiří Techet }
29512f581560SJiří Techet deleteStatement ();
29522f581560SJiří Techet DebugStatement ( if (nestLevel > 0) debugParseNest (false, nestLevel - 1); )
29532f581560SJiří Techet }
29542f581560SJiří Techet
findCTags(const unsigned int passCount)29552f581560SJiří Techet static rescanReason findCTags (const unsigned int passCount)
29562f581560SJiří Techet {
29572f581560SJiří Techet exception_t exception;
29582f581560SJiří Techet rescanReason rescan;
29592f581560SJiří Techet int kind_for_define = KIND_GHOST_INDEX;
29602f581560SJiří Techet int kind_for_header = KIND_GHOST_INDEX;
29612f581560SJiří Techet int kind_for_param = KIND_GHOST_INDEX;
29622f581560SJiří Techet int role_for_macro_undef = ROLE_DEFINITION_INDEX;
29632f581560SJiří Techet int role_for_macro_condition = ROLE_DEFINITION_INDEX;
29642f581560SJiří Techet int role_for_header_system = ROLE_DEFINITION_INDEX;
29652f581560SJiří Techet int role_for_header_local = ROLE_DEFINITION_INDEX;
29662f581560SJiří Techet
29672f581560SJiří Techet Assert (passCount < 3);
29682f581560SJiří Techet
29692f581560SJiří Techet AnonymousID = 0;
29702f581560SJiří Techet
29716afc0c60SJiří Techet cppInit ((bool) (passCount > 1), isInputLanguage (Lang_csharp), false,
29721f8ea58bSJiří Techet false,
29732f581560SJiří Techet kind_for_define, role_for_macro_undef, role_for_macro_condition, kind_for_param,
29742f581560SJiří Techet kind_for_header, role_for_header_system, role_for_header_local,
29752f581560SJiří Techet FIELD_UNKNOWN);
29762f581560SJiří Techet
29772f581560SJiří Techet Signature = vStringNew ();
29782f581560SJiří Techet
29792f581560SJiří Techet exception = (exception_t) setjmp (Exception);
29802f581560SJiří Techet rescan = RESCAN_NONE;
29812f581560SJiří Techet if (exception == ExceptionNone)
29822f581560SJiří Techet createTags (0, NULL);
29832f581560SJiří Techet else
29842f581560SJiří Techet {
29852f581560SJiří Techet deleteAllStatements ();
29862f581560SJiří Techet if (exception == ExceptionBraceFormattingError && passCount == 1)
29872f581560SJiří Techet {
29882f581560SJiří Techet rescan = RESCAN_FAILED;
29892f581560SJiří Techet verbose ("%s: retrying file with fallback brace matching algorithm\n",
29902f581560SJiří Techet getInputFileName ());
29912f581560SJiří Techet }
29922f581560SJiří Techet }
29932f581560SJiří Techet vStringDelete (Signature);
29942f581560SJiří Techet cppTerminate ();
29952f581560SJiří Techet return rescan;
29962f581560SJiří Techet }
29972f581560SJiří Techet
buildKeywordHash(const langType language,unsigned int idx)29982f581560SJiří Techet static void buildKeywordHash (const langType language, unsigned int idx)
29992f581560SJiří Techet {
30002f581560SJiří Techet const size_t count = ARRAY_SIZE (KeywordTable);
30012f581560SJiří Techet size_t i;
30022f581560SJiří Techet for (i = 0 ; i < count ; ++i)
30032f581560SJiří Techet {
30042f581560SJiří Techet const keywordDesc* const p = &KeywordTable [i];
30052f581560SJiří Techet if (p->isValid [idx])
30062f581560SJiří Techet addKeyword (p->name, language, (int) p->id);
30072f581560SJiří Techet }
30082f581560SJiří Techet }
30092f581560SJiří Techet
initializeCsharpParser(const langType language)30102f581560SJiří Techet static void initializeCsharpParser (const langType language)
30112f581560SJiří Techet {
30122f581560SJiří Techet Lang_csharp = language;
30136afc0c60SJiří Techet buildKeywordHash (language, 0);
30142f581560SJiří Techet }
30152f581560SJiří Techet
initializeDParser(const langType language)30162f581560SJiří Techet static void initializeDParser (const langType language)
30172f581560SJiří Techet {
30182f581560SJiří Techet Lang_d = language;
30196afc0c60SJiří Techet buildKeywordHash (language, 1);
30202f581560SJiří Techet }
30212f581560SJiří Techet
30222f581560SJiří Techet
initializeJavaParser(const langType language)30232f581560SJiří Techet static void initializeJavaParser (const langType language)
30242f581560SJiří Techet {
30252f581560SJiří Techet Lang_java = language;
30266afc0c60SJiří Techet buildKeywordHash (language, 2);
30272f581560SJiří Techet }
30282f581560SJiří Techet
DParser(void)30292f581560SJiří Techet extern parserDefinition* DParser (void)
30302f581560SJiří Techet {
30312f581560SJiří Techet static const char *const extensions [] = { "d", "di", NULL };
30322f581560SJiří Techet parserDefinition* def = parserNew ("D");
30332f581560SJiří Techet def->kindTable = DKinds;
30342f581560SJiří Techet def->kindCount = ARRAY_SIZE (DKinds);
30352f581560SJiří Techet def->extensions = extensions;
30362f581560SJiří Techet def->parser2 = findCTags;
30372f581560SJiří Techet def->initialize = initializeDParser;
30382f581560SJiří Techet // end: field is not tested.
30392f581560SJiří Techet
30402f581560SJiří Techet /* cpreprocessor wants corkQueue. */
30412f581560SJiří Techet def->useCork = CORK_QUEUE;
30422f581560SJiří Techet return def;
30432f581560SJiří Techet }
30442f581560SJiří Techet
CsharpParser(void)30452f581560SJiří Techet extern parserDefinition* CsharpParser (void)
30462f581560SJiří Techet {
30472f581560SJiří Techet static const char *const extensions [] = { "cs", NULL };
30482f581560SJiří Techet static const char *const aliases [] = { "csharp", NULL };
30492f581560SJiří Techet parserDefinition* def = parserNew ("C#");
30502f581560SJiří Techet def->kindTable = CsharpKinds;
30512f581560SJiří Techet def->kindCount = ARRAY_SIZE (CsharpKinds);
30522f581560SJiří Techet def->extensions = extensions;
30532f581560SJiří Techet def->aliases = aliases;
30542f581560SJiří Techet def->parser2 = findCTags;
30552f581560SJiří Techet def->initialize = initializeCsharpParser;
30562f581560SJiří Techet // end: field is not tested.
30572f581560SJiří Techet
30582f581560SJiří Techet /* cpreprocessor wants corkQueue. */
30592f581560SJiří Techet def->useCork = CORK_QUEUE;
30602f581560SJiří Techet return def;
30612f581560SJiří Techet }
30622f581560SJiří Techet
JavaParser(void)30632f581560SJiří Techet extern parserDefinition* JavaParser (void)
30642f581560SJiří Techet {
30652f581560SJiří Techet static const char *const extensions [] = { "java", NULL };
30662f581560SJiří Techet parserDefinition* def = parserNew ("Java");
30672f581560SJiří Techet def->kindTable = JavaKinds;
30682f581560SJiří Techet def->kindCount = ARRAY_SIZE (JavaKinds);
30692f581560SJiří Techet def->extensions = extensions;
30702f581560SJiří Techet def->parser2 = findCTags;
30712f581560SJiří Techet def->initialize = initializeJavaParser;
30722f581560SJiří Techet def->useCork = CORK_QUEUE;
30732f581560SJiří Techet return def;
30742f581560SJiří Techet }
3075