xref: /Universal-ctags/parsers/c-based.c (revision e6886497b0ba938416ea6fb895dfce1aa22c1940)
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