3 * Copyright (c) 1996-2001, Darren Hiebert
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License.
8 * This module contains functions for parsing and scanning C, C++, D and Java
15 #include "general.h" /* must always come first */
32 #define activeToken(st) ((st)->token [(int) (st)->tokenIndex])
33 #define parentDecl(st) ((st)->parent == NULL ? \
34 DECL_NONE : (st)->parent->declaration)
35 #define isType(token,t) (boolean) ((token)->type == (t))
36 #define insideEnumBody(st) (boolean) ((st)->parent == NULL ? FALSE : \
37 ((st)->parent->declaration == DECL_ENUM))
38 #define isExternCDecl(st,c) (boolean) ((c) == STRING_SYMBOL && \
39 ! (st)->haveQualifyingName && \
40 (st)->scope == SCOPE_EXTERN)
42 #define isOneOf(c,s) (boolean) (strchr ((s), (c)) != NULL)
48 enum { NumTokens
= 12 };
50 typedef enum eException
52 ExceptionNone
, ExceptionEOF
, ExceptionFormattingError
,
53 ExceptionBraceFormattingError
56 /* Used to specify type of keyword.
58 typedef enum eKeywordId
61 KEYWORD_ATTRIBUTE
, KEYWORD_ABSTRACT
, KEYWORD_ALIAS
,
62 KEYWORD_BOOLEAN
, KEYWORD_BYTE
, KEYWORD_BAD_STATE
, KEYWORD_BAD_TRANS
,
63 KEYWORD_BIND
, KEYWORD_BIND_VAR
, KEYWORD_BIT
, KEYWORD_BODY
,
64 KEYWORD_CASE
, KEYWORD_CATCH
, KEYWORD_CHAR
, KEYWORD_CLASS
, KEYWORD_CONST
,
65 KEYWORD_CONSTRAINT
, KEYWORD_COVERAGE_BLOCK
, KEYWORD_COVERAGE_DEF
,
66 KEYWORD_DEFAULT
, KEYWORD_DELEGATE
, KEYWORD_DELETE
, KEYWORD_DO
,
68 KEYWORD_ELSE
, KEYWORD_ENUM
, KEYWORD_EXPLICIT
, KEYWORD_EXTERN
,
69 KEYWORD_EXTENDS
, KEYWORD_EVENT
,
70 KEYWORD_FINAL
, KEYWORD_FINALLY
, KEYWORD_FLOAT
, KEYWORD_FOR
, KEYWORD_FRIEND
, KEYWORD_FUNCTION
,
71 KEYWORD_GET
, KEYWORD_GOTO
,
72 KEYWORD_IF
, KEYWORD_IMPLEMENTS
, KEYWORD_IMPORT
, KEYWORD_IN
, KEYWORD_INLINE
, KEYWORD_INT
,
73 KEYWORD_INOUT
, KEYWORD_INPUT
, KEYWORD_INTEGER
, KEYWORD_INTERFACE
,
75 KEYWORD_LOCAL
, KEYWORD_LONG
,
76 KEYWORD_M_BAD_STATE
, KEYWORD_M_BAD_TRANS
, KEYWORD_M_STATE
, KEYWORD_M_TRANS
,
77 KEYWORD_MODULE
, KEYWORD_MUTABLE
,
78 KEYWORD_NAMESPACE
, KEYWORD_NEW
, KEYWORD_NEWCOV
, KEYWORD_NATIVE
,
79 KEYWORD_OPERATOR
, KEYWORD_OUT
, KEYWORD_OUTPUT
, KEYWORD_OVERLOAD
, KEYWORD_OVERRIDE
,
80 KEYWORD_PACKED
, KEYWORD_PORT
, KEYWORD_PACKAGE
, KEYWORD_PRIVATE
,
81 KEYWORD_PROGRAM
, KEYWORD_PROTECTED
, KEYWORD_PUBLIC
,
82 KEYWORD_REF
, KEYWORD_REGISTER
, KEYWORD_RETURN
,
83 KEYWORD_SHADOW
, KEYWORD_STATE
,
84 KEYWORD_SET
, KEYWORD_SHORT
, KEYWORD_SIGNAL
, KEYWORD_SIGNED
, KEYWORD_SIZE_T
, KEYWORD_STATIC
, KEYWORD_STRING
,
85 KEYWORD_STRUCT
, KEYWORD_SWITCH
, KEYWORD_SYNCHRONIZED
,
86 KEYWORD_TASK
, KEYWORD_TEMPLATE
, KEYWORD_THIS
, KEYWORD_THROW
,
87 KEYWORD_THROWS
, KEYWORD_TRANSIENT
, KEYWORD_TRANS
, KEYWORD_TRANSITION
,
88 KEYWORD_TRY
, KEYWORD_TYPEDEF
, KEYWORD_TYPENAME
,
89 KEYWORD_UINT
, KEYWORD_ULONG
, KEYWORD_UNION
, KEYWORD_UNSIGNED
, KEYWORD_USHORT
,
91 KEYWORD_VIRTUAL
, KEYWORD_VOID
, KEYWORD_VOLATILE
,
92 KEYWORD_WCHAR_T
, KEYWORD_WEAK
, KEYWORD_WHILE
95 /* Used to determine whether keyword is valid for the current language and
98 typedef struct sKeywordDesc
102 short isValid
[7]; /* indicates languages for which kw is valid */
105 /* Used for reporting the type of object parsed by nextToken ().
107 typedef enum eTokenType
109 TOKEN_NONE
, /* none */
110 TOKEN_ARGS
, /* a parenthetical pair and its contents */
113 TOKEN_COMMA
, /* the comma character */
114 TOKEN_DOUBLE_COLON
, /* double colon indicates nested-name-specifier */
116 TOKEN_NAME
, /* an unknown name */
117 TOKEN_PACKAGE
, /* a Java package name */
118 TOKEN_PAREN_NAME
, /* a single name in parentheses */
119 TOKEN_SEMICOLON
, /* the semicolon character */
120 TOKEN_SPEC
, /* a storage class specifier, qualifier, type, etc. */
121 TOKEN_STAR
, /* pointer detection */
122 TOKEN_ARRAY
, /* array detection */
126 /* This describes the scoping of the current statement.
128 typedef enum eTagScope
130 SCOPE_GLOBAL
, /* no storage class specified */
131 SCOPE_STATIC
, /* static storage class */
132 SCOPE_EXTERN
, /* external storage class */
133 SCOPE_FRIEND
, /* declares access only */
134 SCOPE_TYPEDEF
, /* scoping depends upon context */
138 typedef enum eDeclaration
141 DECL_BASE
, /* base type (default) */
147 DECL_IGNORE
, /* non-taggable "declaration" */
151 DECL_NOMANGLE
, /* C++ name demangling block */
158 typedef enum eVisibilityType
164 ACCESS_DEFAULT
, /* Java-specific */
168 /* Information about the parent class of a member (if any).
170 typedef struct sMemberInfo
172 accessType access
; /* access of current statement */
173 accessType accessDefault
; /* access default for current statement */
176 typedef struct sTokenInfo
180 vString
* name
; /* the name of the token */
181 unsigned long lineNumber
; /* line number of tag */
182 fpos_t filePosition
; /* file position of line containing name */
183 int bufferPosition
; /* buffer position of line containing name */
186 typedef enum eImplementation
195 /* Describes the statement currently undergoing analysis.
197 typedef struct sStatementInfo
200 declType declaration
; /* specifier associated with TOKEN_SPEC */
201 boolean gotName
; /* was a name parsed yet? */
202 boolean haveQualifyingName
; /* do we have a name we are considering? */
203 boolean gotParenName
; /* was a name inside parentheses parsed yet? */
204 boolean gotArgs
; /* was a list of parameters parsed yet? */
205 impType implementation
; /* abstract or concrete implementation? */
206 unsigned int tokenIndex
; /* currently active token */
207 tokenInfo
* token
[((int) NumTokens
)];
208 tokenInfo
* context
; /* accumulated scope of current statement */
209 tokenInfo
* blockName
; /* name of current block */
210 memberInfo member
; /* information regarding parent class/struct */
211 vString
* parentClasses
; /* parent classes */
212 struct sStatementInfo
*parent
; /* statement we are nested within */
213 long argEndPosition
; /* Position where argument list ended */
214 tokenInfo
* firstToken
; /* First token in the statement */
217 /* Describes the type of tag being generated.
219 typedef enum eTagType
222 TAG_CLASS
, /* class name */
223 TAG_ENUM
, /* enumeration name */
224 TAG_ENUMERATOR
, /* enumerator (enumeration value) */
225 TAG_FIELD
, /* field (Java) */
226 TAG_FUNCTION
, /* function definition */
227 TAG_INTERFACE
, /* interface declaration */
228 TAG_MEMBER
, /* structure, class or interface member */
229 TAG_METHOD
, /* method declaration */
230 TAG_NAMESPACE
, /* namespace name */
231 TAG_PACKAGE
, /* package name */
232 TAG_PROTOTYPE
, /* function prototype or declaration */
233 TAG_STRUCT
, /* structure name */
234 TAG_TYPEDEF
, /* typedef name */
235 TAG_UNION
, /* union name */
236 TAG_VARIABLE
, /* variable definition */
237 TAG_EXTERN_VAR
, /* external variable declaration */
238 TAG_MACRO
, /* #define s */
239 TAG_EVENT
, /* event */
240 TAG_SIGNAL
, /* signal */
241 TAG_LOCAL
, /* local variable definition */
242 TAG_PROPERTY
, /* property name */
243 TAG_COUNT
/* must be last */
246 typedef struct sParenInfo
249 boolean isKnrParamList
;
250 boolean isNameCandidate
;
251 boolean invalidContents
;
253 unsigned int parameterCount
;
260 static jmp_buf Exception
;
262 static langType Lang_c
;
263 static langType Lang_cpp
;
264 static langType Lang_csharp
;
265 static langType Lang_java
;
266 static langType Lang_d
;
267 static langType Lang_glsl
;
268 static langType Lang_ferite
;
269 static langType Lang_vala
;
271 /* Used to index into the CKinds table. */
275 CK_CLASS
, CK_DEFINE
, CK_ENUMERATOR
, CK_FUNCTION
,
276 CK_ENUMERATION
, CK_MEMBER
, CK_NAMESPACE
, CK_PROTOTYPE
,
277 CK_STRUCT
, CK_TYPEDEF
, CK_UNION
, CK_VARIABLE
,
281 static kindOption CKinds
[] = {
282 { TRUE
, 'c', "class", "classes"},
283 { TRUE
, 'd', "macro", "macro definitions"},
284 { TRUE
, 'e', "enumerator", "enumerators (values inside an enumeration)"},
285 { TRUE
, 'f', "function", "function definitions"},
286 { TRUE
, 'g', "enum", "enumeration names"},
287 { TRUE
, 'm', "member", "class, struct, and union members"},
288 { TRUE
, 'n', "namespace", "namespaces"},
289 { FALSE
, 'p', "prototype", "function prototypes"},
290 { TRUE
, 's', "struct", "structure names"},
291 { TRUE
, 't', "typedef", "typedefs"},
292 { TRUE
, 'u', "union", "union names"},
293 { TRUE
, 'v', "variable", "variable definitions"},
294 { FALSE
, 'x', "externvar", "external variable declarations"},
297 /* Used to index into the DKinds table. */
301 DK_CLASS
, DK_ENUMERATOR
, DK_FUNCTION
,
302 DK_ENUMERATION
, DK_INTERFACE
, DK_MEMBER
, DK_NAMESPACE
, DK_PROTOTYPE
,
303 DK_STRUCT
, DK_TYPEDEF
, DK_UNION
, DK_VARIABLE
,
307 static kindOption DKinds
[] = {
308 { TRUE
, 'c', "class", "classes"},
309 { TRUE
, 'e', "enumerator", "enumerators (values inside an enumeration)"},
310 { TRUE
, 'f', "function", "function definitions"},
311 { TRUE
, 'g', "enum", "enumeration names"},
312 { TRUE
, 'i', "interface", "interfaces"},
313 { TRUE
, 'm', "member", "class, struct, and union members"},
314 { TRUE
, 'n', "namespace", "namespaces"},
315 { FALSE
, 'p', "prototype", "function prototypes"},
316 { TRUE
, 's', "struct", "structure names"},
317 { TRUE
, 't', "typedef", "typedefs"},
318 { TRUE
, 'u', "union", "union names"},
319 { TRUE
, 'v', "variable", "variable definitions"},
320 { FALSE
, 'x', "externvar", "external variable declarations"},
323 /* Used to index into the JavaKinds table. */
327 JK_CLASS
, JK_FIELD
, JK_INTERFACE
, JK_METHOD
,
331 static kindOption JavaKinds
[] = {
332 { TRUE
, 'c', "class", "classes"},
333 { TRUE
, 'f', "field", "fields"},
334 { TRUE
, 'i', "interface", "interfaces"},
335 { TRUE
, 'm', "method", "methods"},
336 { TRUE
, 'p', "package", "packages"},
342 CSK_CLASS
, CSK_DEFINE
, CSK_ENUMERATOR
, CSK_EVENT
, CSK_FIELD
,
343 CSK_ENUMERATION
, CSK_INTERFACE
, CSK_LOCAL
, CSK_METHOD
,
344 CSK_NAMESPACE
, CSK_PROPERTY
, CSK_STRUCT
, CSK_TYPEDEF
347 static kindOption CsharpKinds
[] = {
348 { TRUE
, 'c', "class", "classes"},
349 { TRUE
, 'd', "macro", "macro definitions"},
350 { TRUE
, 'e', "enumerator", "enumerators (values inside an enumeration)"},
351 { TRUE
, 'E', "event", "events"},
352 { TRUE
, 'f', "field", "fields"},
353 { TRUE
, 'g', "enum", "enumeration names"},
354 { TRUE
, 'i', "interface", "interfaces"},
355 { FALSE
, 'l', "local", "local variables"},
356 { TRUE
, 'm', "method", "methods"},
357 { TRUE
, 'n', "namespace", "namespaces"},
358 { TRUE
, 'p', "property", "properties"},
359 { TRUE
, 's', "struct", "structure names"},
360 { TRUE
, 't', "typedef", "typedefs"},
365 VK_CLASS
, VK_DEFINE
, VK_ENUMERATOR
, VK_FIELD
,
366 VK_ENUMERATION
, VK_INTERFACE
, VK_LOCAL
, VK_METHOD
,
367 VK_NAMESPACE
, VK_PROPERTY
, VK_SIGNAL
, VK_STRUCT
370 static kindOption ValaKinds
[] = {
371 { TRUE
, 'c', "class", "classes"},
372 { TRUE
, 'd', "macro", "macro definitions"},
373 { TRUE
, 'e', "enumerator", "enumerators (values inside an enumeration)"},
374 { TRUE
, 'f', "field", "fields"},
375 { TRUE
, 'g', "enum", "enumeration names"},
376 { TRUE
, 'i', "interface", "interfaces"},
377 { FALSE
, 'l', "local", "local variables"},
378 { TRUE
, 'm', "method", "methods"},
379 { TRUE
, 'n', "namespace", "namespaces"},
380 { TRUE
, 'p', "property", "properties"},
381 { TRUE
, 'S', "signal", "signals"},
382 { TRUE
, 's', "struct", "structure names"},
385 static const keywordDesc KeywordTable
[] = {
387 /* ANSI C | C# Java */
391 /* keyword keyword ID | | | | | | | */
392 { "__attribute__", KEYWORD_ATTRIBUTE
, { 1, 1, 1, 0, 0, 0, 1 } },
393 { "abstract", KEYWORD_ABSTRACT
, { 0, 0, 1, 1, 0, 1, 1 } },
394 { "alias", KEYWORD_TYPEDEF
, { 0, 0, 0, 0, 0, 0, 1 } }, /* handle like typedef */
395 { "bad_state", KEYWORD_BAD_STATE
, { 0, 0, 0, 0, 1, 0, 0 } },
396 { "bad_trans", KEYWORD_BAD_TRANS
, { 0, 0, 0, 0, 1, 0, 0 } },
397 { "bind", KEYWORD_BIND
, { 0, 0, 0, 0, 1, 0, 0 } },
398 { "bind_var", KEYWORD_BIND_VAR
, { 0, 0, 0, 0, 1, 0, 0 } },
399 { "bit", KEYWORD_BIT
, { 0, 0, 0, 0, 1, 0, 0 } },
400 { "body", KEYWORD_BODY
, { 0, 0, 0, 0, 0, 0, 1 } },
401 { "boolean", KEYWORD_BOOLEAN
, { 0, 0, 0, 1, 0, 0, 0 } },
402 { "byte", KEYWORD_BYTE
, { 0, 0, 0, 1, 0, 0, 1 } },
403 { "case", KEYWORD_CASE
, { 1, 1, 1, 1, 0, 1, 1 } },
404 { "catch", KEYWORD_CATCH
, { 0, 1, 1, 0, 0, 1, 1 } },
405 { "char", KEYWORD_CHAR
, { 1, 1, 1, 1, 0, 1, 1 } },
406 { "class", KEYWORD_CLASS
, { 0, 1, 1, 1, 1, 1, 1 } },
407 { "const", KEYWORD_CONST
, { 1, 1, 1, 1, 0, 1, 1 } },
408 { "constraint", KEYWORD_CONSTRAINT
, { 0, 0, 0, 0, 1, 0, 0 } },
409 { "coverage_block", KEYWORD_COVERAGE_BLOCK
, { 0, 0, 0, 0, 1, 0, 0 } },
410 { "coverage_def", KEYWORD_COVERAGE_DEF
, { 0, 0, 0, 0, 1, 0, 0 } },
411 { "do", KEYWORD_DO
, { 1, 1, 1, 1, 0, 1, 1 } },
412 { "default", KEYWORD_DEFAULT
, { 1, 1, 1, 1, 0, 1, 1 } },
413 { "delegate", KEYWORD_DELEGATE
, { 0, 0, 1, 0, 0, 1, 1 } },
414 { "delete", KEYWORD_DELETE
, { 0, 1, 0, 0, 0, 1, 1 } },
415 { "double", KEYWORD_DOUBLE
, { 1, 1, 1, 1, 0, 1, 1 } },
416 { "else", KEYWORD_ELSE
, { 1, 1, 0, 1, 0, 1, 1 } },
417 { "enum", KEYWORD_ENUM
, { 1, 1, 1, 1, 1, 1, 1 } },
418 { "errordomain", KEYWORD_ENUM
, { 0, 0, 0, 0, 0, 1, 0 } }, /* errordomain behaves like enum */
419 { "event", KEYWORD_EVENT
, { 0, 0, 1, 0, 1, 0, 0 } },
420 { "explicit", KEYWORD_EXPLICIT
, { 0, 1, 1, 0, 0, 0, 1 } },
421 { "extends", KEYWORD_EXTENDS
, { 0, 0, 0, 1, 1, 0, 0 } },
422 { "extern", KEYWORD_EXTERN
, { 1, 1, 1, 0, 1, 1, 0 } },
423 { "extern", KEYWORD_NAMESPACE
, { 0, 0, 0, 0, 0, 0, 1 } }, /* hack to ignore extern */
424 { "final", KEYWORD_FINAL
, { 0, 0, 0, 1, 0, 0, 1 } },
425 { "finally", KEYWORD_FINALLY
, { 0, 0, 0, 0, 0, 1, 1 } },
426 { "float", KEYWORD_FLOAT
, { 1, 1, 1, 1, 0, 1, 1 } },
427 { "for", KEYWORD_FOR
, { 1, 1, 1, 1, 0, 1, 1 } },
428 { "friend", KEYWORD_FRIEND
, { 0, 1, 0, 0, 0, 0, 0 } },
429 { "function", KEYWORD_FUNCTION
, { 0, 0, 0, 0, 1, 0, 1 } },
430 { "get", KEYWORD_GET
, { 0, 0, 0, 0, 0, 1, 0 } },
431 { "goto", KEYWORD_GOTO
, { 1, 1, 1, 1, 0, 1, 1 } },
432 { "if", KEYWORD_IF
, { 1, 1, 1, 1, 0, 1, 1 } },
433 { "implements", KEYWORD_IMPLEMENTS
, { 0, 0, 0, 1, 0, 0, 0 } },
434 { "import", KEYWORD_IMPORT
, { 0, 0, 0, 1, 0, 0, 1 } },
435 { "inline", KEYWORD_INLINE
, { 0, 1, 0, 0, 0, 1, 0 } },
436 { "in", KEYWORD_IN
, { 0, 0, 0, 0, 0, 0, 1 } },
437 { "inout", KEYWORD_INOUT
, { 0, 0, 0, 0, 1, 0, 1 } },
438 { "input", KEYWORD_INPUT
, { 0, 0, 0, 0, 1, 0, 0 } },
439 { "int", KEYWORD_INT
, { 1, 1, 1, 1, 0, 1, 1 } },
440 { "integer", KEYWORD_INTEGER
, { 0, 0, 0, 0, 1, 0, 0 } },
441 { "interface", KEYWORD_INTERFACE
, { 0, 0, 1, 1, 1, 1, 1 } },
442 { "internal", KEYWORD_INTERNAL
, { 0, 0, 1, 0, 0, 0, 0 } },
443 { "local", KEYWORD_LOCAL
, { 0, 0, 0, 0, 1, 0, 0 } },
444 { "long", KEYWORD_LONG
, { 1, 1, 1, 1, 0, 1, 1 } },
445 { "m_bad_state", KEYWORD_M_BAD_STATE
, { 0, 0, 0, 0, 1, 0, 0 } },
446 { "m_bad_trans", KEYWORD_M_BAD_TRANS
, { 0, 0, 0, 0, 1, 0, 0 } },
447 { "m_state", KEYWORD_M_STATE
, { 0, 0, 0, 0, 1, 0, 0 } },
448 { "m_trans", KEYWORD_M_TRANS
, { 0, 0, 0, 0, 1, 0, 0 } },
449 { "mutable", KEYWORD_MUTABLE
, { 0, 1, 0, 0, 0, 0, 0 } },
450 { "module", KEYWORD_MODULE
, { 0, 0, 0, 0, 0, 0, 1 } },
451 { "namespace", KEYWORD_NAMESPACE
, { 0, 1, 1, 0, 0, 1, 0 } },
452 { "native", KEYWORD_NATIVE
, { 0, 0, 0, 1, 0, 0, 0 } },
453 { "new", KEYWORD_NEW
, { 0, 1, 1, 1, 0, 1, 1 } },
454 { "newcov", KEYWORD_NEWCOV
, { 0, 0, 0, 0, 1, 0, 0 } },
455 { "operator", KEYWORD_OPERATOR
, { 0, 1, 1, 0, 0, 0, 0 } },
456 { "out", KEYWORD_OUT
, { 0, 0, 0, 0, 0, 1, 1 } },
457 { "output", KEYWORD_OUTPUT
, { 0, 0, 0, 0, 1, 0, 0 } },
458 { "overload", KEYWORD_OVERLOAD
, { 0, 1, 0, 0, 0, 0, 0 } },
459 { "override", KEYWORD_OVERRIDE
, { 0, 0, 1, 0, 0, 1, 1 } },
460 { "package", KEYWORD_PACKAGE
, { 0, 0, 0, 1, 0, 0, 1 } },
461 { "packed", KEYWORD_PACKED
, { 0, 0, 0, 0, 1, 0, 0 } },
462 { "port", KEYWORD_PORT
, { 0, 0, 0, 0, 1, 0, 0 } },
463 { "private", KEYWORD_PRIVATE
, { 0, 1, 1, 1, 0, 1, 1 } },
464 { "program", KEYWORD_PROGRAM
, { 0, 0, 0, 0, 1, 0, 0 } },
465 { "protected", KEYWORD_PROTECTED
, { 0, 1, 1, 1, 1, 1, 1 } },
466 { "public", KEYWORD_PUBLIC
, { 0, 1, 1, 1, 1, 1, 1 } },
467 { "ref", KEYWORD_REF
, { 0, 0, 0, 0, 0, 1, 1 } },
468 { "register", KEYWORD_REGISTER
, { 1, 1, 0, 0, 0, 0, 0 } },
469 { "return", KEYWORD_RETURN
, { 1, 1, 1, 1, 0, 1, 1 } },
470 { "set", KEYWORD_SET
, { 0, 0, 0, 0, 0, 1, 0 } },
471 { "shadow", KEYWORD_SHADOW
, { 0, 0, 0, 0, 1, 0, 0 } },
472 { "short", KEYWORD_SHORT
, { 1, 1, 1, 1, 0, 1, 1 } },
473 { "signal", KEYWORD_SIGNAL
, { 0, 0, 0, 0, 0, 1, 0 } },
474 { "signed", KEYWORD_SIGNED
, { 1, 1, 0, 0, 0, 0, 0 } },
475 { "size_t", KEYWORD_SIZE_T
, { 1, 1, 0, 0, 0, 1, 1 } },
476 { "state", KEYWORD_STATE
, { 0, 0, 0, 0, 1, 0, 0 } },
477 { "static", KEYWORD_STATIC
, { 1, 1, 1, 1, 1, 1, 1 } },
478 { "string", KEYWORD_STRING
, { 0, 0, 1, 0, 1, 1, 0 } },
479 { "struct", KEYWORD_STRUCT
, { 1, 1, 1, 0, 0, 1, 1 } },
480 { "switch", KEYWORD_SWITCH
, { 1, 1, 1, 1, 0, 1, 1 } },
481 { "synchronized", KEYWORD_SYNCHRONIZED
, { 0, 0, 0, 1, 0, 0, 1 } },
482 { "task", KEYWORD_TASK
, { 0, 0, 0, 0, 1, 0, 0 } },
483 { "template", KEYWORD_TEMPLATE
, { 0, 1, 0, 0, 0, 0, 1 } },
484 { "this", KEYWORD_THIS
, { 0, 0, 1, 1, 0, 1, 0 } }, /* 0 to allow D ctor tags */
485 { "throw", KEYWORD_THROW
, { 0, 1, 1, 1, 0, 1, 1 } },
486 { "throws", KEYWORD_THROWS
, { 0, 0, 0, 1, 0, 1, 0 } },
487 { "trans", KEYWORD_TRANS
, { 0, 0, 0, 0, 1, 0, 0 } },
488 { "transition", KEYWORD_TRANSITION
, { 0, 0, 0, 0, 1, 0, 0 } },
489 { "transient", KEYWORD_TRANSIENT
, { 0, 0, 0, 1, 0, 0, 0 } },
490 { "try", KEYWORD_TRY
, { 0, 1, 1, 0, 0, 1, 1 } },
491 { "typedef", KEYWORD_TYPEDEF
, { 1, 1, 1, 0, 1, 0, 1 } },
492 { "typename", KEYWORD_TYPENAME
, { 0, 1, 0, 0, 0, 0, 0 } },
493 { "uint", KEYWORD_UINT
, { 0, 0, 1, 0, 0, 1, 1 } },
494 { "ulong", KEYWORD_ULONG
, { 0, 0, 1, 0, 0, 1, 1 } },
495 { "union", KEYWORD_UNION
, { 1, 1, 0, 0, 0, 0, 1 } },
496 { "unsigned", KEYWORD_UNSIGNED
, { 1, 1, 1, 0, 0, 0, 1 } },
497 { "ushort", KEYWORD_USHORT
, { 0, 0, 1, 0, 0, 1, 1 } },
498 { "using", KEYWORD_USING
, { 0, 1, 1, 0, 0, 1, 0 } },
499 { "version", KEYWORD_NAMESPACE
, { 0, 0, 0, 0, 0, 0, 1 } }, /* hack to ignore version */
500 { "virtual", KEYWORD_VIRTUAL
, { 0, 1, 1, 0, 1, 1, 0 } },
501 { "void", KEYWORD_VOID
, { 1, 1, 1, 1, 1, 1, 1 } },
502 { "volatile", KEYWORD_VOLATILE
, { 1, 1, 1, 1, 0, 0, 1 } },
503 { "wchar_t", KEYWORD_WCHAR_T
, { 1, 1, 1, 0, 0, 0, 1 } },
504 { "weak", KEYWORD_WEAK
, { 0, 0, 0, 0, 0, 1, 0 } },
505 { "while", KEYWORD_WHILE
, { 1, 1, 1, 1, 0, 1, 1 } }
510 * FUNCTION PROTOTYPES
512 static void createTags (const unsigned int nestLevel
, statementInfo
*const parent
);
513 static void copyToken (tokenInfo
*const dest
, const tokenInfo
*const src
);
514 static const char *getVarType (const statementInfo
*const st
);
517 * FUNCTION DEFINITIONS
520 /* Debugging functions added by Biswa */
521 #if defined(DEBUG_C) && DEBUG_C
522 static char *tokenTypeName
[] = {
523 "none", "args", "'}'", "'{'", "','", "'::'", "keyword", "name",
524 "package", "paren-name", "';'", "spec", "*", "[]", "count"
527 static char *tagScopeNames
[] = {
528 "global", "static", "extern", "friend", "typedef", "count"};
530 static char *declTypeNames
[] = {
531 "none", "base", "class", "enum", "function", "ignore", "interface",
532 "namespace", "nomangle", "package", "struct", "union", "count"};
534 static char *impTypeNames
[] = {
535 "default", "abstract", "virtual", "pure-virtual", "count"};
537 void printToken(const tokenInfo
*const token
)
539 fprintf(stderr
, "Type: %s, Keyword: %d, name: %s\n", tokenTypeName
[token
->type
],
540 token
->keyword
, vStringValue(token
->name
));
543 void printTagEntry(const tagEntryInfo
*tag
)
545 fprintf(stderr
, "Tag: %s (%s) [ impl: %s, scope: %s, type: %s\n", tag
->name
,
546 tag
->kindName
, tag
->extensionFields
.implementation
, tag
->extensionFields
.scope
[1],
547 tag
->extensionFields
.varType
);
550 void printStatement(const statementInfo
*const statement
)
553 statementInfo
*st
= (statementInfo
*) statement
;
556 fprintf(stderr
, "Statement Info:\n------------------------\n");
557 fprintf(stderr
, "scope: %s, decl: %s, impl: %s\n", tagScopeNames
[st
->scope
],
558 declTypeNames
[st
->declaration
], impTypeNames
[st
->implementation
]);
559 for (i
=0; i
< NumTokens
; ++i
)
561 fprintf(stderr
, "Token %d %s: ", i
, (i
== st
->tokenIndex
)?"(current)":"");
562 printToken(st
->token
[i
]);
564 fprintf(stderr
, "Context: ");
565 printToken(st
->context
);
566 fprintf(stderr
, "Block: ");
567 printToken(st
->blockName
);
568 fprintf(stderr
, "Parent classes: %s\n", vStringValue(st
->parentClasses
));
569 fprintf(stderr
, "First token: ");
570 printToken(st
->firstToken
);
571 if (NULL
!= st
->parent
)
572 fprintf(stderr
, "Printing Parent:\n");
575 fprintf(stderr
, "-----------------------------------------------\n");
579 extern boolean
includingDefineTags (void)
581 if (isLanguage(Lang_c
) ||
582 isLanguage(Lang_cpp
) ||
583 isLanguage(Lang_csharp
) ||
584 isLanguage(Lang_ferite
) ||
585 isLanguage(Lang_glsl
) ||
586 isLanguage(Lang_vala
))
587 return CKinds
[CK_DEFINE
].enabled
;
596 static void initToken (tokenInfo
* const token
)
598 token
->type
= TOKEN_NONE
;
599 token
->keyword
= KEYWORD_NONE
;
600 token
->lineNumber
= getSourceLineNumber();
602 token
->filePosition
= getInputFilePosition();
604 token
->bufferPosition
= getInputBufferPosition();
605 vStringClear(token
->name
);
608 static void advanceToken (statementInfo
* const st
)
610 if (st
->tokenIndex
>= (unsigned int) NumTokens
- 1)
614 initToken(st
->token
[st
->tokenIndex
]);
617 static tokenInfo
*prevToken (const statementInfo
*const st
, unsigned int n
)
619 unsigned int tokenIndex
;
620 unsigned int num
= (unsigned int) NumTokens
;
622 tokenIndex
= (st
->tokenIndex
+ num
- n
) % num
;
624 return st
->token
[tokenIndex
];
627 static void setToken (statementInfo
*const st
, const tokenType type
)
630 token
= activeToken (st
);
635 static void retardToken (statementInfo
*const st
)
637 if (st
->tokenIndex
== 0)
638 st
->tokenIndex
= (unsigned int) NumTokens
- 1;
641 setToken(st
, TOKEN_NONE
);
644 static tokenInfo
*newToken (void)
646 tokenInfo
*const token
= xMalloc (1, tokenInfo
);
647 token
->name
= vStringNew();
652 static void deleteToken (tokenInfo
*const token
)
656 vStringDelete(token
->name
);
661 static const char *accessString (const accessType laccess
)
663 static const char *const names
[] ={
664 "?", "private", "protected", "public", "default"
666 Assert (sizeof (names
) / sizeof (names
[0]) == ACCESS_COUNT
);
667 Assert ((int) laccess
< ACCESS_COUNT
);
668 return names
[(int) laccess
];
671 static const char *implementationString (const impType imp
)
673 static const char *const names
[] ={
674 "?", "abstract", "virtual", "pure virtual"
676 Assert (sizeof (names
) / sizeof (names
[0]) == IMP_COUNT
);
677 Assert ((int) imp
< IMP_COUNT
);
678 return names
[(int) imp
];
682 * Debugging functions
687 #define boolString(c) ((c) ? "TRUE" : "FALSE")
689 static const char *tokenString (const tokenType type
)
691 static const char *const names
[] = {
692 "none", "args", "}", "{", "comma", "double colon", "keyword", "name",
693 "package", "paren-name", "semicolon", "specifier", "*", "[]", "count"
695 Assert (sizeof (names
) / sizeof (names
[0]) == TOKEN_COUNT
);
696 Assert ((int) type
< TOKEN_COUNT
);
697 return names
[(int) type
];
700 static const char *scopeString (const tagScope scope
)
702 static const char *const names
[] = {
703 "global", "static", "extern", "friend", "typedef"
705 Assert (sizeof (names
) / sizeof (names
[0]) == SCOPE_COUNT
);
706 Assert ((int) scope
< SCOPE_COUNT
);
707 return names
[(int) scope
];
710 static const char *declString (const declType declaration
)
712 static const char *const names
[] = {
713 "?", "base", "class", "enum", "function", "ignore", "interface",
714 "namespace", "no mangle", "package", "struct", "union",
716 Assert (sizeof (names
) / sizeof (names
[0]) == DECL_COUNT
);
717 Assert ((int) declaration
< DECL_COUNT
);
718 return names
[(int) declaration
];
721 static const char *keywordString (const keywordId keyword
)
723 const size_t count
= sizeof (KeywordTable
) / sizeof (KeywordTable
[0]);
724 const char *name
= "none";
726 for (i
= 0 ; i
< count
; ++i
)
728 const keywordDesc
*p
= &KeywordTable
[i
];
730 if (p
->id
== keyword
)
739 static void __unused__
pt (tokenInfo
*const token
)
741 if (isType (token
, TOKEN_NAME
))
742 printf("type: %-12s: %-13s line: %lu\n",
743 tokenString (token
->type
), vStringValue (token
->name
),
745 else if (isType (token
, TOKEN_KEYWORD
))
746 printf("type: %-12s: %-13s line: %lu\n",
747 tokenString (token
->type
), keywordString (token
->keyword
),
750 printf("type: %-12s line: %lu\n",
751 tokenString (token
->type
), token
->lineNumber
);
754 static void __unused__
ps (statementInfo
*const st
)
757 printf("scope: %s decl: %s gotName: %s gotParenName: %s\n",
758 scopeString (st
->scope
), declString (st
->declaration
),
759 boolString (st
->gotName
), boolString (st
->gotParenName
));
760 printf("haveQualifyingName: %s\n", boolString (st
->haveQualifyingName
));
761 printf("access: %s default: %s\n", accessString (st
->member
.access
),
762 accessString (st
->member
.accessDefault
));
764 pt(activeToken (st
));
765 for (i
= 1 ; i
< (unsigned int) NumTokens
; ++i
)
767 printf("prev %u : ", i
);
768 pt(prevToken (st
, i
));
777 * Statement management
780 static boolean
isDataTypeKeyword (const tokenInfo
*const token
)
782 switch (token
->keyword
)
784 case KEYWORD_BOOLEAN
:
793 case KEYWORD_WCHAR_T
:
802 static boolean
isVariableKeyword (const tokenInfo
*const token
)
804 switch (token
->keyword
)
808 case KEYWORD_REGISTER
:
810 case KEYWORD_VIRTUAL
:
812 case KEYWORD_UNSIGNED
:
820 static boolean
isContextualKeyword (const tokenInfo
*const token
)
823 switch (token
->keyword
)
827 case KEYWORD_INTERFACE
:
828 case KEYWORD_NAMESPACE
:
845 static boolean
isContextualStatement (const statementInfo
*const st
)
847 boolean result
= FALSE
;
851 if (isLanguage (Lang_vala
))
853 /* All can be a contextual statment as properties can be of any type */
858 switch (st
->declaration
)
882 static boolean
isMember (const statementInfo
*const st
)
885 if (isType (st
->context
, TOKEN_NAME
))
888 result
= isContextualStatement (st
->parent
);
892 static void initMemberInfo (statementInfo
*const st
)
894 accessType accessDefault
= ACCESS_UNDEFINED
;
896 if (st
->parent
!= NULL
) switch (st
->parent
->declaration
)
901 accessDefault
= ACCESS_UNDEFINED
;
906 if (isLanguage (Lang_java
))
907 accessDefault
= ACCESS_DEFAULT
;
909 accessDefault
= ACCESS_PRIVATE
;
916 accessDefault
= ACCESS_PUBLIC
;
922 st
->member
.accessDefault
= accessDefault
;
923 st
->member
.access
= accessDefault
;
926 static void reinitStatement (statementInfo
*const st
, const boolean partial
)
932 st
->scope
= SCOPE_GLOBAL
;
933 if (isContextualStatement (st
->parent
))
934 st
->declaration
= DECL_BASE
;
936 st
->declaration
= DECL_NONE
;
938 st
->gotParenName
= FALSE
;
939 st
->implementation
= IMP_DEFAULT
;
942 st
->haveQualifyingName
= FALSE
;
943 st
->argEndPosition
= 0;
946 for (i
= 0 ; i
< (unsigned int) NumTokens
; ++i
)
948 initToken (st
->token
[i
]);
951 initToken (st
->context
);
952 initToken (st
->blockName
);
953 vStringClear (st
->parentClasses
);
958 st
->member
.access
= st
->member
.accessDefault
;
960 /* Init first token */
962 initToken(st
->firstToken
);
965 static void reinitStatementWithToken (statementInfo
*const st
,
966 tokenInfo
*token
, const boolean partial
)
968 tokenInfo
*const save
= newToken ();
969 /* given token can be part of reinit statementInfo */
970 copyToken (save
, token
);
971 reinitStatement (st
, partial
);
972 token
= activeToken (st
);
973 copyToken (token
, save
);
975 ++st
->tokenIndex
; /* this is quite save becouse current tokenIndex = 0 */
978 static void initStatement (statementInfo
*const st
, statementInfo
*const parent
)
982 reinitStatement (st
, FALSE
);
985 const tokenInfo
*const src
= activeToken (parent
);
986 tokenInfo
*const dst
= activeToken (st
);
987 copyToken (dst
, src
);
993 * Tag generation functions
995 static cKind
cTagKind (const tagType type
)
997 cKind result
= CK_UNDEFINED
;
1000 case TAG_CLASS
: result
= CK_CLASS
; break;
1001 case TAG_ENUM
: result
= CK_ENUMERATION
; break;
1002 case TAG_ENUMERATOR
: result
= CK_ENUMERATOR
; break;
1003 case TAG_FUNCTION
: result
= CK_FUNCTION
; break;
1004 case TAG_MEMBER
: result
= CK_MEMBER
; break;
1005 case TAG_NAMESPACE
: result
= CK_NAMESPACE
; break;
1006 case TAG_PROTOTYPE
: result
= CK_PROTOTYPE
; break;
1007 case TAG_STRUCT
: result
= CK_STRUCT
; break;
1008 case TAG_TYPEDEF
: result
= CK_TYPEDEF
; break;
1009 case TAG_UNION
: result
= CK_UNION
; break;
1010 case TAG_VARIABLE
: result
= CK_VARIABLE
; break;
1011 case TAG_EXTERN_VAR
: result
= CK_EXTERN_VARIABLE
; break;
1013 default: Assert ("Bad C tag type" == NULL
); break;
1018 static csharpKind
csharpTagKind (const tagType type
)
1020 csharpKind result
= CSK_UNDEFINED
;
1023 case TAG_CLASS
: result
= CSK_CLASS
; break;
1024 case TAG_ENUM
: result
= CSK_ENUMERATION
; break;
1025 case TAG_ENUMERATOR
: result
= CSK_ENUMERATOR
; break;
1026 case TAG_EVENT
: result
= CSK_EVENT
; break;
1027 case TAG_FIELD
: result
= CSK_FIELD
; break;
1028 case TAG_INTERFACE
: result
= CSK_INTERFACE
; break;
1029 case TAG_LOCAL
: result
= CSK_LOCAL
; break;
1030 case TAG_METHOD
: result
= CSK_METHOD
; break;
1031 case TAG_NAMESPACE
: result
= CSK_NAMESPACE
; break;
1032 case TAG_PROPERTY
: result
= CSK_PROPERTY
; break;
1033 case TAG_STRUCT
: result
= CSK_STRUCT
; break;
1034 case TAG_TYPEDEF
: result
= CSK_TYPEDEF
; break;
1036 default: Assert ("Bad C# tag type" == NULL
); break;
1041 static dKind
dTagKind (const tagType type
)
1043 dKind result
= DK_UNDEFINED
;
1046 case TAG_CLASS
: result
= DK_CLASS
; break;
1047 case TAG_ENUM
: result
= DK_ENUMERATION
; break;
1048 case TAG_ENUMERATOR
: result
= DK_ENUMERATOR
; break;
1049 case TAG_FUNCTION
: result
= DK_FUNCTION
; break;
1050 case TAG_INTERFACE
: result
= DK_INTERFACE
; break;
1051 case TAG_MEMBER
: result
= DK_MEMBER
; break;
1052 case TAG_NAMESPACE
: result
= DK_NAMESPACE
; break;
1053 case TAG_PROTOTYPE
: result
= DK_PROTOTYPE
; break;
1054 case TAG_STRUCT
: result
= DK_STRUCT
; break;
1055 case TAG_TYPEDEF
: result
= DK_TYPEDEF
; break;
1056 case TAG_UNION
: result
= DK_UNION
; break;
1057 case TAG_VARIABLE
: result
= DK_VARIABLE
; break;
1058 case TAG_EXTERN_VAR
: result
= DK_EXTERN_VARIABLE
; break;
1060 default: Assert ("Bad D tag type" == NULL
); break;
1065 static valaKind
valaTagKind (const tagType type
)
1067 valaKind result
= VK_UNDEFINED
;
1070 case TAG_CLASS
: result
= VK_CLASS
; break;
1071 case TAG_ENUM
: result
= VK_ENUMERATION
; break;
1072 case TAG_ENUMERATOR
: result
= VK_ENUMERATOR
; break;
1073 case TAG_SIGNAL
: result
= VK_SIGNAL
; break;
1074 case TAG_FIELD
: result
= VK_FIELD
; break;
1075 case TAG_INTERFACE
: result
= VK_INTERFACE
; break;
1076 case TAG_LOCAL
: result
= VK_LOCAL
; break;
1077 case TAG_METHOD
: result
= VK_METHOD
; break;
1078 case TAG_NAMESPACE
: result
= VK_NAMESPACE
; break;
1079 case TAG_PROPERTY
: result
= VK_PROPERTY
; break;
1080 case TAG_STRUCT
: result
= VK_STRUCT
; break;
1082 default: Assert ("Bad Vala tag type" == NULL
); break;
1087 static javaKind
javaTagKind (const tagType type
)
1089 javaKind result
= JK_UNDEFINED
;
1092 case TAG_CLASS
: result
= JK_CLASS
; break;
1093 case TAG_FIELD
: result
= JK_FIELD
; break;
1094 case TAG_INTERFACE
: result
= JK_INTERFACE
; break;
1095 case TAG_METHOD
: result
= JK_METHOD
; break;
1096 case TAG_PACKAGE
: result
= JK_PACKAGE
; break;
1098 default: Assert ("Bad Java tag type" == NULL
); break;
1103 static const char *tagName (const tagType type
)
1106 if (isLanguage (Lang_java
))
1107 result
= JavaKinds
[javaTagKind (type
)].name
;
1108 else if (isLanguage (Lang_csharp
))
1109 result
= CsharpKinds
[csharpTagKind (type
)].name
;
1110 else if (isLanguage (Lang_d
))
1111 result
= DKinds
[dTagKind (type
)].name
;
1112 else if (isLanguage (Lang_vala
))
1113 result
= ValaKinds
[valaTagKind (type
)].name
;
1115 result
= CKinds
[cTagKind (type
)].name
;
1119 static int tagLetter (const tagType type
)
1122 if (isLanguage (Lang_csharp
))
1123 result
= CsharpKinds
[csharpTagKind (type
)].letter
;
1124 else if (isLanguage (Lang_d
))
1125 result
= DKinds
[dTagKind (type
)].letter
;
1126 else if (isLanguage (Lang_java
))
1127 result
= JavaKinds
[javaTagKind (type
)].letter
;
1128 else if (isLanguage (Lang_vala
))
1129 result
= ValaKinds
[valaTagKind (type
)].letter
;
1131 result
= CKinds
[cTagKind (type
)].letter
;
1136 static boolean includeTag (const tagType type, const boolean isFileScope)
1139 if (isFileScope && ! Option.include.fileScope)
1141 else if (isLanguage (Lang_java))
1142 result = JavaKinds [javaTagKind (type)].enabled;
1144 result = CKinds [cTagKind (type)].enabled;
1149 static tagType
declToTagType (const declType declaration
)
1151 tagType type
= TAG_UNDEFINED
;
1153 switch (declaration
)
1155 case DECL_CLASS
: type
= TAG_CLASS
; break;
1156 case DECL_ENUM
: type
= TAG_ENUM
; break;
1157 case DECL_FUNCTION
: type
= TAG_FUNCTION
; break;
1158 case DECL_INTERFACE
:type
= TAG_INTERFACE
; break;
1159 case DECL_NAMESPACE
:type
= TAG_NAMESPACE
; break;
1160 case DECL_STRUCT
: type
= TAG_STRUCT
; break;
1161 case DECL_UNION
: type
= TAG_UNION
; break;
1163 default: Assert ("Unexpected declaration" == NULL
); break;
1168 static const char* accessField (const statementInfo
*const st
)
1170 const char* result
= NULL
;
1172 if ((isLanguage (Lang_cpp
) || isLanguage (Lang_d
) || isLanguage (Lang_ferite
)) &&
1173 st
->scope
== SCOPE_FRIEND
)
1175 else if (st
->member
.access
!= ACCESS_UNDEFINED
)
1176 result
= accessString (st
->member
.access
);
1180 static void addOtherFields (tagEntryInfo
* const tag
, const tagType type
,
1181 const statementInfo
*const st
, vString
*const scope
)
1183 /* For selected tag types, append an extension flag designating the
1184 * parent object in which the tag is defined.
1192 case TAG_ENUMERATOR
:
1203 if (vStringLength (scope
) > 0 &&
1204 (isMember (st
) || st
->parent
->declaration
== DECL_NAMESPACE
))
1206 if (isType (st
->context
, TOKEN_NAME
))
1207 tag
->extensionFields
.scope
[0] = tagName (TAG_CLASS
);
1209 tag
->extensionFields
.scope
[0] =
1210 tagName (declToTagType (parentDecl (st
)));
1211 tag
->extensionFields
.scope
[1] = vStringValue (scope
);
1213 if ((type
== TAG_CLASS
|| type
== TAG_INTERFACE
||
1214 type
== TAG_STRUCT
) && vStringLength (st
->parentClasses
) > 0)
1217 tag
->extensionFields
.inheritance
=
1218 vStringValue (st
->parentClasses
);
1220 if (st
->implementation
!= IMP_DEFAULT
&&
1221 (isLanguage (Lang_cpp
) || isLanguage (Lang_csharp
) || isLanguage (Lang_vala
) ||
1222 isLanguage (Lang_java
) || isLanguage (Lang_d
) || isLanguage (Lang_ferite
)))
1224 tag
->extensionFields
.implementation
=
1225 implementationString (st
->implementation
);
1229 tag
->extensionFields
.access
= accessField (st
);
1231 if ((TRUE
== st
->gotArgs
) && (TRUE
== Option
.extensionFields
.argList
) &&
1232 ((TAG_FUNCTION
== type
) || (TAG_METHOD
== type
) || (TAG_PROTOTYPE
== type
)))
1236 tag
->extensionFields
.arglist
= getArglistFromFilePos(
1237 tag
->filePosition
, tag
->name
);
1241 tag
->extensionFields
.arglist
= getArglistFromBufferPos(
1242 tag
->bufferPosition
, tag
->name
);
1249 if ((TAG_FIELD
== tag
->type
) || (TAG_MEMBER
== tag
->type
) ||
1250 (TAG_EXTERN_VAR
== tag
->type
) || (TAG_TYPEDEF
== tag
->type
) ||
1251 (TAG_VARIABLE
== tag
->type
) || (TAG_METHOD
== tag
->type
) ||
1252 (TAG_PROTOTYPE
== tag
->type
) || (TAG_FUNCTION
== tag
->type
))
1254 if (((TOKEN_NAME
== st
->firstToken
->type
) || isDataTypeKeyword(st
->firstToken
))
1255 && (0 != strcmp(vStringValue(st
->firstToken
->name
), tag
->name
)))
1257 tag
->extensionFields
.varType
= getVarType(st
);
1262 static const char *getVarType (const statementInfo
*const st
)
1264 static vString
*vt
= NULL
;
1268 return vStringValue(st
->firstToken
->name
); /* ignore non-functions */
1275 for (i
= 0; i
< st
->tokenIndex
; i
++)
1277 tokenInfo
*t
= st
->token
[i
];
1281 case TOKEN_NAME
: /* user typename */
1282 if (strcmp(vStringValue(t
->name
), vStringValue(st
->firstToken
->name
)) != 0)
1286 if (t
->keyword
!= KEYWORD_EXTERN
&& t
->keyword
!= KEYWORD_STATIC
) /* uninteresting keywords */
1289 case TOKEN_STAR
: vStringCatS(vt
, " *"); continue;
1290 case TOKEN_ARRAY
: vStringCatS(vt
, "[]"); continue;
1293 if (vStringLength(vt
) > 0)
1294 if (isalpha(vStringValue(vt
)[vStringLength(vt
) - 1]))
1295 vStringPut(vt
, ' ');
1296 vStringCat(vt
, t
->name
);
1298 vStringTerminate(vt
);
1299 return vStringValue(vt
);
1302 static void addContextSeparator (vString
*const scope
)
1304 if (isLanguage (Lang_c
) || isLanguage (Lang_cpp
))
1305 vStringCatS (scope
, "::");
1306 else if (isLanguage (Lang_java
) || isLanguage (Lang_d
) || isLanguage (Lang_ferite
) ||
1307 isLanguage (Lang_csharp
) || isLanguage (Lang_vala
))
1308 vStringCatS (scope
, ".");
1311 static void findScopeHierarchy (vString
*const string
,
1312 const statementInfo
*const st
)
1314 const char* const anon
= "<anonymous>";
1315 boolean nonAnonPresent
= FALSE
;
1317 vStringClear (string
);
1318 if (isType (st
->context
, TOKEN_NAME
))
1320 vStringCopy (string
, st
->context
->name
);
1321 nonAnonPresent
= TRUE
;
1323 if (st
->parent
!= NULL
)
1325 vString
*temp
= vStringNew ();
1326 const statementInfo
*s
;
1328 for (s
= st
->parent
; s
!= NULL
; s
= s
->parent
)
1330 if (isContextualStatement (s
) ||
1331 s
->declaration
== DECL_NAMESPACE
)
1333 vStringCopy (temp
, string
);
1334 vStringClear (string
);
1335 if (isType (s
->blockName
, TOKEN_NAME
))
1337 if (isType (s
->context
, TOKEN_NAME
) &&
1338 vStringLength (s
->context
->name
) > 0)
1340 vStringCat (string
, s
->context
->name
);
1341 addContextSeparator (string
);
1343 vStringCat (string
, s
->blockName
->name
);
1344 nonAnonPresent
= TRUE
;
1347 vStringCopyS (string
, anon
);
1348 if (vStringLength (temp
) > 0)
1349 addContextSeparator (string
);
1350 vStringCat (string
, temp
);
1353 vStringDelete (temp
);
1355 if (! nonAnonPresent
)
1356 vStringClear (string
);
1360 static void makeExtraTagEntry (const tagType type
, tagEntryInfo
*const e
,
1361 vString
*const scope
)
1363 if (Option
.include
.qualifiedTags
&&
1364 scope
!= NULL
&& vStringLength (scope
) > 0)
1366 vString
*const scopedName
= vStringNew ();
1368 if (type
!= TAG_ENUMERATOR
)
1369 vStringCopy (scopedName
, scope
);
1372 /* remove last component (i.e. enumeration name) from scope */
1373 const char* const sc
= vStringValue (scope
);
1374 const char* colon
= strrchr (sc
, ':');
1377 while (*colon
== ':' && colon
> sc
)
1379 vStringNCopy (scopedName
, scope
, colon
+ 1 - sc
);
1382 if (vStringLength (scopedName
) > 0)
1384 addContextSeparator (scopedName
);
1385 vStringCatS (scopedName
, e
->name
);
1386 e
->name
= vStringValue (scopedName
);
1389 vStringDelete (scopedName
);
1393 static void makeTag (const tokenInfo
*const token
,
1394 const statementInfo
*const st
,
1395 boolean isFileScope
, const tagType type
)
1399 fprintf(stderr
, "<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>\n");
1402 /* Nothing is really of file scope when it appears in a header file.
1404 isFileScope
= (boolean
) (isFileScope
&& ! isHeaderFile ());
1406 if (isType (token
, TOKEN_NAME
) && vStringLength (token
->name
) > 0 /* &&
1407 includeTag (type, isFileScope) */)
1409 vString
*scope
= vStringNew ();
1412 /* take only functions which are introduced by "function ..." */
1413 if (type
== TAG_FUNCTION
&& isLanguage (Lang_ferite
) &&
1414 strncmp("function", st
->firstToken
->name
->buffer
, 8) != 0)
1419 initTagEntry (&e
, vStringValue (token
->name
));
1421 e
.lineNumber
= token
->lineNumber
;
1423 e
.filePosition
= token
->filePosition
;
1425 e
.bufferPosition
= token
->bufferPosition
;
1426 e
.isFileScope
= isFileScope
;
1427 e
.kindName
= tagName (type
);
1428 e
.kind
= tagLetter (type
);
1431 findScopeHierarchy (scope
, st
);
1432 addOtherFields (&e
, type
, st
, scope
);
1438 if (NULL
!= TagEntryFunction
)
1439 makeExtraTagEntry (type
, &e
, scope
);
1440 vStringDelete (scope
);
1441 if (NULL
!= e
.extensionFields
.arglist
)
1442 free((char *) e
.extensionFields
.arglist
);
1446 static boolean
isValidTypeSpecifier (const declType declaration
)
1449 switch (declaration
)
1466 static void qualifyEnumeratorTag (const statementInfo
*const st
,
1467 const tokenInfo
*const nameToken
)
1469 if (isType (nameToken
, TOKEN_NAME
))
1470 makeTag (nameToken
, st
, TRUE
, TAG_ENUMERATOR
);
1473 static void qualifyFunctionTag (const statementInfo
*const st
,
1474 const tokenInfo
*const nameToken
)
1476 if (isType (nameToken
, TOKEN_NAME
))
1478 const tagType type
= (isLanguage (Lang_java
) || isLanguage (Lang_csharp
) || isLanguage (Lang_vala
))
1479 ? TAG_METHOD
: TAG_FUNCTION
;
1480 const boolean isFileScope
=
1481 (boolean
) (st
->member
.access
== ACCESS_PRIVATE
||
1482 (!isMember (st
) && st
->scope
== SCOPE_STATIC
));
1484 makeTag (nameToken
, st
, isFileScope
, type
);
1488 static void qualifyFunctionDeclTag (const statementInfo
*const st
,
1489 const tokenInfo
*const nameToken
)
1491 if (! isType (nameToken
, TOKEN_NAME
))
1493 else if (isLanguage (Lang_java
) || isLanguage (Lang_csharp
) || isLanguage (Lang_vala
))
1494 qualifyFunctionTag (st
, nameToken
);
1495 else if (st
->scope
== SCOPE_TYPEDEF
)
1496 makeTag (nameToken
, st
, TRUE
, TAG_TYPEDEF
);
1497 else if (isValidTypeSpecifier (st
->declaration
) &&
1498 ! (isLanguage (Lang_csharp
) || isLanguage (Lang_vala
)))
1499 makeTag (nameToken
, st
, TRUE
, TAG_PROTOTYPE
);
1502 static void qualifyCompoundTag (const statementInfo
*const st
,
1503 const tokenInfo
*const nameToken
)
1505 if (isType (nameToken
, TOKEN_NAME
))
1507 const tagType type
= declToTagType (st
->declaration
);
1509 if (type
!= TAG_UNDEFINED
)
1510 makeTag (nameToken
, st
, (boolean
) (! isLanguage (Lang_java
) &&
1511 ! isLanguage (Lang_csharp
) &&
1512 ! isLanguage (Lang_vala
)), type
);
1516 static void qualifyBlockTag (statementInfo
*const st
,
1517 const tokenInfo
*const nameToken
)
1519 switch (st
->declaration
)
1523 case DECL_INTERFACE
:
1524 case DECL_NAMESPACE
:
1527 qualifyCompoundTag (st
, nameToken
);
1533 static void qualifyVariableTag (const statementInfo
*const st
,
1534 const tokenInfo
*const nameToken
)
1536 /* We have to watch that we do not interpret a declaration of the
1537 * form "struct tag;" as a variable definition. In such a case, the
1538 * token preceding the name will be a keyword.
1540 if (! isType (nameToken
, TOKEN_NAME
))
1542 else if (st
->declaration
== DECL_IGNORE
)
1544 else if (st
->scope
== SCOPE_TYPEDEF
)
1545 makeTag (nameToken
, st
, TRUE
, TAG_TYPEDEF
);
1546 else if (st
->declaration
== DECL_PACKAGE
)
1547 makeTag (nameToken
, st
, FALSE
, TAG_PACKAGE
);
1548 else if (st
->declaration
== DECL_MODULE
) /* handle modules in D as namespaces */
1549 makeTag (nameToken
, st
, FALSE
, TAG_NAMESPACE
);
1550 else if (isValidTypeSpecifier (st
->declaration
))
1554 if (isLanguage (Lang_java
) || isLanguage (Lang_csharp
) || isLanguage (Lang_vala
))
1555 makeTag (nameToken
, st
, (boolean
) (st
->member
.access
== ACCESS_PRIVATE
), TAG_FIELD
);
1556 else if (st
->scope
== SCOPE_GLOBAL
|| st
->scope
== SCOPE_STATIC
)
1557 makeTag (nameToken
, st
, TRUE
, TAG_MEMBER
);
1559 else if (isLanguage (Lang_java
) || isLanguage (Lang_csharp
) || isLanguage (Lang_vala
));
1562 if (st
->scope
== SCOPE_EXTERN
|| ! st
->haveQualifyingName
)
1563 makeTag (nameToken
, st
, FALSE
, TAG_EXTERN_VAR
);
1565 makeTag (nameToken
, st
, (boolean
) (st
->scope
== SCOPE_STATIC
), TAG_VARIABLE
);
1574 static int skipToOneOf (const char *const chars
)
1579 while (c
!= EOF
&& c
!= '\0' && strchr (chars
, c
) == NULL
);
1584 /* Skip to the next non-white character.
1586 static int skipToNonWhite (void)
1594 while (isspace (c
));
1599 /* Skips to the next brace in column 1. This is intended for cases where
1600 * preprocessor constructs result in unbalanced braces.
1602 static void skipToFormattedBraceMatch (void)
1608 while (c
!= EOF
&& (c
!= '\n' || next
!= '}'))
1615 /* Skip to the matching character indicated by the pair string. If skipping
1616 * to a matching brace and any brace is found within a different level of a
1617 * #if conditional statement while brace formatting is in effect, we skip to
1618 * the brace matched by its formatting. It is assumed that we have already
1619 * read the character which starts the group (i.e. the first character of
1622 static void skipToMatch (const char *const pair
)
1624 const boolean braceMatching
= (boolean
) (strcmp ("{}", pair
) == 0);
1625 const boolean braceFormatting
= (boolean
) (isBraceFormat () && braceMatching
);
1626 const unsigned int initialLevel
= getDirectiveNestLevel ();
1627 const int begin
= pair
[0], end
= pair
[1];
1628 const unsigned long inputLineNumber
= getInputLineNumber ();
1631 while (matchLevel
> 0 && (c
= cppGetc ()) != EOF
)
1636 if (braceFormatting
&& getDirectiveNestLevel () != initialLevel
)
1638 skipToFormattedBraceMatch ();
1645 if (braceFormatting
&& getDirectiveNestLevel () != initialLevel
)
1647 skipToFormattedBraceMatch ();
1654 verbose ("%s: failed to find match for '%c' at line %lu\n",
1655 getInputFileName (), begin
, inputLineNumber
);
1657 longjmp (Exception
, (int) ExceptionBraceFormattingError
);
1659 longjmp (Exception
, (int) ExceptionFormattingError
);
1663 static void skipParens (void)
1665 const int c
= skipToNonWhite ();
1673 static void skipBraces (void)
1675 const int c
= skipToNonWhite ();
1683 static keywordId
analyzeKeyword (const char *const name
)
1685 const keywordId id
= (keywordId
) lookupKeyword (name
, getSourceLanguage ());
1689 static void analyzeIdentifier (tokenInfo
*const token
)
1691 char *const name
= vStringValue (token
->name
);
1692 const char *replacement
= NULL
;
1693 boolean parensToo
= FALSE
;
1695 if (isLanguage (Lang_java
) ||
1696 ! isIgnoreToken (name
, &parensToo
, &replacement
))
1698 if (replacement
!= NULL
)
1699 token
->keyword
= analyzeKeyword (replacement
);
1701 token
->keyword
= analyzeKeyword (vStringValue (token
->name
));
1703 if (token
->keyword
== KEYWORD_NONE
)
1704 token
->type
= TOKEN_NAME
;
1706 token
->type
= TOKEN_KEYWORD
;
1713 int c
= skipToNonWhite ();
1721 static void readIdentifier (tokenInfo
*const token
, const int firstChar
)
1723 vString
*const name
= token
->name
;
1728 /* Bug #1585745 (CTags): strangely, C++ destructors allow whitespace between
1729 * the ~ and the class name. */
1730 if (isLanguage (Lang_cpp
) && firstChar
== '~')
1732 vStringPut (name
, c
);
1733 c
= skipToNonWhite ();
1738 vStringPut (name
, c
);
1740 } while (isident (c
) || (isLanguage (Lang_vala
) && '.' == c
));
1741 vStringTerminate (name
);
1742 cppUngetc (c
); /* unget non-identifier character */
1744 /* Vala supports '?' at end of a type (with or without whitspace before) for nullable types */
1745 if (isLanguage (Lang_vala
))
1747 c
= skipToNonWhite ();
1749 vStringPut (name
, c
);
1754 analyzeIdentifier (token
);
1757 static void readPackageName (tokenInfo
*const token
, const int firstChar
)
1759 vString
*const name
= token
->name
;
1764 while (isident (c
) || c
== '.')
1766 vStringPut (name
, c
);
1769 vStringTerminate (name
);
1770 cppUngetc (c
); /* unget non-package character */
1773 static void readPackageOrNamespace (statementInfo
*const st
, const declType declaration
)
1775 st
->declaration
= declaration
;
1777 if (declaration
== DECL_NAMESPACE
&& !(isLanguage (Lang_csharp
) || isLanguage (Lang_vala
)))
1779 /* In C++ a namespace is specified one level at a time. */
1784 /* In C#, a namespace can also be specified like a Java package name. */
1785 tokenInfo
*const token
= activeToken (st
);
1786 Assert (isType (token
, TOKEN_KEYWORD
));
1787 readPackageName (token
, skipToNonWhite ());
1788 token
->type
= TOKEN_NAME
;
1790 st
->haveQualifyingName
= TRUE
;
1794 static void readPackage (statementInfo
*const st
)
1796 tokenInfo
*const token
= activeToken (st
);
1797 Assert (isType (token
, TOKEN_KEYWORD
));
1798 readPackageName (token
, skipToNonWhite ());
1799 token
->type
= TOKEN_NAME
;
1800 if (isLanguage (Lang_d
))
1801 st
->declaration
= DECL_MODULE
;
1803 st
->declaration
= DECL_PACKAGE
;
1805 st
->haveQualifyingName
= TRUE
;
1808 static void processName (statementInfo
*const st
)
1810 Assert (isType (activeToken (st
), TOKEN_NAME
));
1811 if (st
->gotName
&& st
->declaration
== DECL_NONE
)
1812 st
->declaration
= DECL_BASE
;
1814 st
->haveQualifyingName
= TRUE
;
1817 static void readOperator (statementInfo
*const st
)
1819 const char *const acceptable
= "+-*/%^&|~!=<>,[]";
1820 const tokenInfo
* const prev
= prevToken (st
,1);
1821 tokenInfo
*const token
= activeToken (st
);
1822 vString
*const name
= token
->name
;
1823 int c
= skipToNonWhite ();
1825 /* When we arrive here, we have the keyword "operator" in 'name'.
1827 if (isType (prev
, TOKEN_KEYWORD
) && (prev
->keyword
== KEYWORD_ENUM
||
1828 prev
->keyword
== KEYWORD_STRUCT
|| prev
->keyword
== KEYWORD_UNION
))
1829 ; /* ignore "operator" keyword if preceded by these keywords */
1832 /* Verify whether this is a valid function call (i.e. "()") operator.
1834 if (cppGetc () == ')')
1836 vStringPut (name
, ' '); /* always separate operator from keyword */
1837 c
= skipToNonWhite ();
1839 vStringCatS (name
, "()");
1847 else if (isident1 (c
))
1849 /* Handle "new" and "delete" operators, and conversion functions
1850 * (per 13.3.1.1.2 [2] of the C++ spec).
1852 boolean whiteSpace
= TRUE
; /* default causes insertion of space */
1861 vStringPut (name
, ' ');
1864 vStringPut (name
, c
);
1867 } while (! isOneOf (c
, "(;") && c
!= EOF
);
1868 vStringTerminate (name
);
1870 else if (isOneOf (c
, acceptable
))
1872 vStringPut (name
, ' '); /* always separate operator from keyword */
1875 vStringPut (name
, c
);
1877 } while (isOneOf (c
, acceptable
));
1878 vStringTerminate (name
);
1883 token
->type
= TOKEN_NAME
;
1884 token
->keyword
= KEYWORD_NONE
;
1888 static void copyToken (tokenInfo
*const dest
, const tokenInfo
*const src
)
1890 dest
->type
= src
->type
;
1891 dest
->keyword
= src
->keyword
;
1893 dest
->filePosition
= src
->filePosition
;
1895 dest
->bufferPosition
= src
->bufferPosition
;
1896 dest
->lineNumber
= src
->lineNumber
;
1897 vStringCopy (dest
->name
, src
->name
);
1900 static void setAccess (statementInfo
*const st
, const accessType laccess
)
1904 if (isLanguage (Lang_cpp
) || isLanguage (Lang_d
) || isLanguage (Lang_ferite
))
1906 int c
= skipToNonWhite ();
1909 reinitStatementWithToken (st
, prevToken (st
, 1), FALSE
);
1913 st
->member
.accessDefault
= laccess
;
1915 st
->member
.access
= laccess
;
1919 static void discardTypeList (tokenInfo
*const token
)
1921 int c
= skipToNonWhite ();
1922 while (isident1 (c
))
1924 readIdentifier (token
, c
);
1925 c
= skipToNonWhite ();
1926 if (c
== '.' || c
== ',')
1927 c
= skipToNonWhite ();
1932 static void addParentClass (statementInfo
*const st
, tokenInfo
*const token
)
1934 if (vStringLength (token
->name
) > 0 &&
1935 vStringLength (st
->parentClasses
) > 0)
1937 vStringPut (st
->parentClasses
, ',');
1939 vStringCat (st
->parentClasses
, token
->name
);
1942 static void readParents (statementInfo
*const st
, const int qualifier
)
1944 tokenInfo
*const token
= newToken ();
1945 tokenInfo
*const parent
= newToken ();
1950 c
= skipToNonWhite ();
1953 readIdentifier (token
, c
);
1954 if (isType (token
, TOKEN_NAME
))
1955 vStringCat (parent
->name
, token
->name
);
1958 addParentClass (st
, parent
);
1962 else if (c
== qualifier
)
1963 vStringPut (parent
->name
, c
);
1966 else if (isType (token
, TOKEN_NAME
))
1968 addParentClass (st
, parent
);
1971 } while (c
!= '{' && c
!= EOF
);
1973 deleteToken (parent
);
1974 deleteToken (token
);
1977 static void processToken (tokenInfo
*const token
, statementInfo
*const st
)
1979 switch (token
->keyword
) /* is it a reserved word? */
1983 case KEYWORD_NONE
: processName (st
); break;
1984 case KEYWORD_ABSTRACT
: st
->implementation
= IMP_ABSTRACT
; break;
1985 case KEYWORD_ATTRIBUTE
: skipParens (); initToken (token
); break;
1986 case KEYWORD_CATCH
: skipParens (); skipBraces (); break;
1987 case KEYWORD_CHAR
: st
->declaration
= DECL_BASE
; break;
1988 case KEYWORD_CLASS
: st
->declaration
= DECL_CLASS
; break;
1989 case KEYWORD_CONST
: st
->declaration
= DECL_BASE
; break;
1990 case KEYWORD_DOUBLE
: st
->declaration
= DECL_BASE
; break;
1991 case KEYWORD_ENUM
: st
->declaration
= DECL_ENUM
; break;
1992 case KEYWORD_EXTENDS
: readParents (st
, '.');
1993 setToken (st
, TOKEN_NONE
); break;
1994 case KEYWORD_FLOAT
: st
->declaration
= DECL_BASE
; break;
1995 case KEYWORD_FRIEND
: st
->scope
= SCOPE_FRIEND
; break;
1996 case KEYWORD_IMPLEMENTS
:readParents (st
, '.');
1997 setToken (st
, TOKEN_NONE
); break;
1998 case KEYWORD_IMPORT
: st
->declaration
= DECL_IGNORE
; break;
1999 case KEYWORD_INT
: st
->declaration
= DECL_BASE
; break;
2000 case KEYWORD_BOOLEAN
: st
->declaration
= DECL_BASE
; break;
2001 case KEYWORD_WCHAR_T
: st
->declaration
= DECL_BASE
; break;
2002 case KEYWORD_SIZE_T
: st
->declaration
= DECL_BASE
; break;
2003 case KEYWORD_INTERFACE
: st
->declaration
= DECL_INTERFACE
; break;
2004 case KEYWORD_LONG
: st
->declaration
= DECL_BASE
; break;
2005 case KEYWORD_OPERATOR
: readOperator (st
); break;
2006 case KEYWORD_MODULE
: readPackage (st
); break;
2007 case KEYWORD_PRIVATE
: setAccess (st
, ACCESS_PRIVATE
); break;
2008 case KEYWORD_PROTECTED
: setAccess (st
, ACCESS_PROTECTED
); break;
2009 case KEYWORD_PUBLIC
: setAccess (st
, ACCESS_PUBLIC
); break;
2010 case KEYWORD_SHORT
: st
->declaration
= DECL_BASE
; break;
2011 case KEYWORD_SIGNED
: st
->declaration
= DECL_BASE
; break;
2012 case KEYWORD_STRUCT
: st
->declaration
= DECL_STRUCT
; break;
2013 case KEYWORD_THROWS
: discardTypeList (token
); break;
2014 case KEYWORD_TYPEDEF
: st
->scope
= SCOPE_TYPEDEF
; break;
2015 case KEYWORD_UNION
: st
->declaration
= DECL_UNION
; break;
2016 case KEYWORD_UNSIGNED
: st
->declaration
= DECL_BASE
; break;
2017 case KEYWORD_USING
: st
->declaration
= DECL_IGNORE
; break;
2018 case KEYWORD_VOID
: st
->declaration
= DECL_BASE
; break;
2019 case KEYWORD_VOLATILE
: st
->declaration
= DECL_BASE
; break;
2020 case KEYWORD_VIRTUAL
: st
->implementation
= IMP_VIRTUAL
; break;
2022 case KEYWORD_NAMESPACE
: readPackageOrNamespace (st
, DECL_NAMESPACE
); break;
2023 case KEYWORD_PACKAGE
: readPackageOrNamespace (st
, DECL_PACKAGE
); break;
2026 if (isLanguage (Lang_csharp
))
2027 st
->declaration
= DECL_EVENT
;
2030 case KEYWORD_SIGNAL
:
2032 if (isLanguage (Lang_vala
))
2033 st
->declaration
= DECL_SIGNAL
;
2036 case KEYWORD_EXTERN
:
2038 if (! isLanguage (Lang_csharp
) || !st
->gotName
)
2040 /*reinitStatement (st, FALSE);*/
2041 st
->scope
= SCOPE_EXTERN
;
2042 st
->declaration
= DECL_BASE
;
2046 case KEYWORD_STATIC
:
2048 if (! isLanguage (Lang_java
) && ! isLanguage (Lang_csharp
) && ! isLanguage (Lang_vala
))
2050 /*reinitStatement (st, FALSE);*/
2051 st
->scope
= SCOPE_STATIC
;
2052 st
->declaration
= DECL_BASE
;
2060 * Parenthesis handling functions
2063 static void restartStatement (statementInfo
*const st
)
2065 tokenInfo
*const save
= newToken ();
2066 tokenInfo
*token
= activeToken (st
);
2068 copyToken (save
, token
);
2069 DebugStatement ( if (debug (DEBUG_PARSE
)) printf ("<ES>");)
2070 reinitStatement (st
, FALSE
);
2071 token
= activeToken (st
);
2072 copyToken (token
, save
);
2074 processToken (token
, st
);
2077 /* Skips over a the mem-initializer-list of a ctor-initializer, defined as:
2079 * mem-initializer-list:
2080 * mem-initializer, mem-initializer-list
2083 * [::] [nested-name-spec] class-name (...)
2086 static void skipMemIntializerList (tokenInfo
*const token
)
2092 c
= skipToNonWhite ();
2093 while (isident1 (c
) || c
== ':')
2096 readIdentifier (token
, c
);
2097 c
= skipToNonWhite ();
2102 c
= skipToNonWhite ();
2107 c
= skipToNonWhite ();
2113 static void skipMacro (statementInfo
*const st
)
2115 tokenInfo
*const prev2
= prevToken (st
, 2);
2117 if (isType (prev2
, TOKEN_NAME
))
2122 /* Skips over characters following the parameter list. This will be either
2123 * non-ANSI style function declarations or C++ stuff. Our choices:
2127 * int func (one, two) int one; float two; {...}
2129 * int func (int one, float two);
2130 * int func (int one, float two) {...}
2132 * int foo (...) [const|volatile] [throw (...)];
2133 * int foo (...) [const|volatile] [throw (...)] [ctor-initializer] {...}
2134 * int foo (...) [const|volatile] [throw (...)] try [ctor-initializer] {...}
2137 static boolean
skipPostArgumentStuff (statementInfo
*const st
,
2138 parenInfo
*const info
)
2140 tokenInfo
*const token
= activeToken (st
);
2141 unsigned int parameters
= info
->parameterCount
;
2142 unsigned int elementCount
= 0;
2143 boolean restart
= FALSE
;
2144 boolean end
= FALSE
;
2145 int c
= skipToNonWhite ();
2152 case ':': skipMemIntializerList (token
);break; /* ctor-initializer */
2153 case '[': skipToMatch ("[]"); break;
2154 case '=': cppUngetc (c
); end
= TRUE
; break;
2155 case '{': cppUngetc (c
); end
= TRUE
; break;
2156 case '}': cppUngetc (c
); end
= TRUE
; break;
2160 if (elementCount
> 0)
2168 if (parameters
== 0 || elementCount
< 2)
2173 else if (--parameters
== 0)
2182 readIdentifier (token
, c
);
2183 if (isLanguage(Lang_d
))
2184 { /* parse D contracts */
2185 switch (token
->keyword
)
2190 token
->keyword
= KEYWORD_CONST
;
2195 switch (token
->keyword
)
2197 case KEYWORD_ATTRIBUTE
: skipParens (); break;
2198 case KEYWORD_THROW
: skipParens (); break;
2199 case KEYWORD_CONST
: break;
2200 case KEYWORD_TRY
: break;
2201 case KEYWORD_VOLATILE
: break;
2203 case KEYWORD_CATCH
: case KEYWORD_CLASS
:
2204 case KEYWORD_EXPLICIT
: case KEYWORD_EXTERN
:
2205 case KEYWORD_FRIEND
: case KEYWORD_INLINE
:
2206 case KEYWORD_MUTABLE
: case KEYWORD_NAMESPACE
:
2207 case KEYWORD_NEW
: case KEYWORD_OPERATOR
:
2208 case KEYWORD_OVERLOAD
: case KEYWORD_PRIVATE
:
2209 case KEYWORD_PROTECTED
: case KEYWORD_PUBLIC
:
2210 case KEYWORD_STATIC
: case KEYWORD_TEMPLATE
:
2211 case KEYWORD_TYPEDEF
: case KEYWORD_TYPENAME
:
2212 case KEYWORD_USING
: case KEYWORD_VIRTUAL
:
2213 /* Never allowed within parameter declarations.
2220 if (isType (token
, TOKEN_NONE
))
2222 else if (info
->isKnrParamList
&& info
->parameterCount
> 0)
2226 /* If we encounter any other identifier immediately
2227 * following an empty parameter list, this is almost
2228 * certainly one of those Microsoft macro "thingies"
2229 * that the automatic source code generation sticks
2230 * in. Terminate the current statement.
2242 c
= skipToNonWhite ();
2249 restartStatement (st
);
2251 setToken (st
, TOKEN_NONE
);
2252 return (boolean
) (c
!= EOF
);
2255 static void skipJavaThrows (statementInfo
*const st
)
2257 tokenInfo
*const token
= activeToken (st
);
2258 int c
= skipToNonWhite ();
2262 readIdentifier (token
, c
);
2263 if (token
->keyword
== KEYWORD_THROWS
)
2267 c
= skipToNonWhite ();
2270 readIdentifier (token
, c
);
2271 c
= skipToNonWhite ();
2273 } while (c
== '.' || c
== ',');
2277 setToken (st
, TOKEN_NONE
);
2280 static void analyzePostParens (statementInfo
*const st
, parenInfo
*const info
)
2282 const unsigned long inputLineNumber
= getInputLineNumber ();
2283 int c
= skipToNonWhite ();
2286 if (isOneOf (c
, "{;,="))
2288 else if (isLanguage (Lang_java
) || isLanguage (Lang_vala
))
2289 skipJavaThrows (st
);
2292 if (! skipPostArgumentStuff (st
, info
))
2295 "%s: confusing argument declarations beginning at line %lu\n",
2296 getInputFileName (), inputLineNumber
);
2297 longjmp (Exception
, (int) ExceptionFormattingError
);
2302 static int parseParens (statementInfo
*const st
, parenInfo
*const info
)
2304 tokenInfo
*const token
= activeToken (st
);
2305 unsigned int identifierCount
= 0;
2306 unsigned int depth
= 1;
2307 boolean firstChar
= TRUE
;
2308 int nextChar
= '\0';
2310 info
->parameterCount
= 1;
2313 int c
= skipToNonWhite ();
2320 /* DEBUG_PRINT("parseParens, po++\n"); */
2321 info
->isKnrParamList
= FALSE
;
2322 if (identifierCount
== 0)
2323 info
->isParamList
= FALSE
;
2329 info
->isKnrParamList
= FALSE
;
2334 info
->isNameCandidate
= FALSE
;
2335 info
->isKnrParamList
= FALSE
;
2340 info
->isNameCandidate
= FALSE
;
2341 if (info
->isKnrParamList
)
2343 ++info
->parameterCount
;
2344 identifierCount
= 0;
2350 info
->isKnrParamList
= FALSE
;
2351 info
->isNameCandidate
= FALSE
;
2354 info
->isParamList
= FALSE
;
2362 info
->isKnrParamList
= FALSE
;
2368 info
->isKnrParamList
= FALSE
;
2375 info
->parameterCount
= 0;
2381 info
->isKnrParamList
= FALSE
;
2384 info
->isNameCandidate
= FALSE
;
2389 else if (isType (token
, TOKEN_PAREN_NAME
))
2391 c
= skipToNonWhite ();
2392 if (c
== '*') /* check for function pointer */
2395 c
= skipToNonWhite ();
2403 info
->nestedArgs
= TRUE
;
2415 if (++identifierCount
> 1)
2416 info
->isKnrParamList
= FALSE
;
2417 readIdentifier (token
, c
);
2418 if (isType (token
, TOKEN_NAME
) && info
->isNameCandidate
)
2419 token
->type
= TOKEN_PAREN_NAME
;
2420 else if (isType (token
, TOKEN_KEYWORD
))
2422 info
->isKnrParamList
= FALSE
;
2423 info
->isNameCandidate
= FALSE
;
2428 info
->isParamList
= FALSE
;
2429 info
->isKnrParamList
= FALSE
;
2430 info
->isNameCandidate
= FALSE
;
2431 info
->invalidContents
= TRUE
;
2437 } while (! info
->nestedArgs
&& depth
> 0 &&
2438 (info
->isKnrParamList
|| info
->isNameCandidate
));
2440 if (! info
->nestedArgs
) while (depth
> 0)
2445 if (st
->argEndPosition
== 0)
2448 st
->argEndPosition
= ftell(File
.fp
);
2450 /* FIXME File.fpBufferPosition is wrong here, this breaks function signatures and
2451 * so Geany's calltips */
2452 st
->argEndPosition
= File
.fpBufferPosition
;
2455 if (! info
->isNameCandidate
)
2461 static void initParenInfo (parenInfo
*const info
)
2463 info
->isParamList
= TRUE
;
2464 info
->isKnrParamList
= TRUE
;
2465 info
->isNameCandidate
= TRUE
;
2466 info
->invalidContents
= FALSE
;
2467 info
->nestedArgs
= FALSE
;
2468 info
->parameterCount
= 0;
2471 static void analyzeParens (statementInfo
*const st
)
2473 tokenInfo
*const prev
= prevToken (st
, 1);
2475 if (! isType (prev
, TOKEN_NONE
)) /* in case of ignored enclosing macros */
2477 tokenInfo
*const token
= activeToken (st
);
2481 initParenInfo (&info
);
2482 parseParens (st
, &info
);
2484 c
= skipToNonWhite ();
2487 if (info
.invalidContents
)
2489 reinitStatement (st
, FALSE
);
2491 else if (info
.isNameCandidate
&& isType (token
, TOKEN_PAREN_NAME
) &&
2492 ! st
->gotParenName
&&
2493 (! info
.isParamList
|| ! st
->haveQualifyingName
||
2495 (c
== '=' && st
->implementation
!= IMP_VIRTUAL
) ||
2496 (st
->declaration
== DECL_NONE
&& isOneOf (c
, ",;"))))
2498 token
->type
= TOKEN_NAME
;
2500 st
->gotParenName
= TRUE
;
2502 else if (! st
->gotArgs
&& info
.isParamList
)
2505 setToken (st
, TOKEN_ARGS
);
2507 analyzePostParens (st
, &info
);
2511 setToken (st
, TOKEN_NONE
);
2517 * Token parsing functions
2520 static void addContext (statementInfo
*const st
, const tokenInfo
* const token
)
2522 if (isType (token
, TOKEN_NAME
))
2524 if (vStringLength (st
->context
->name
) > 0)
2526 if (isLanguage (Lang_c
) || isLanguage (Lang_cpp
))
2527 vStringCatS (st
->context
->name
, "::");
2528 else if (isLanguage (Lang_java
) ||
2529 isLanguage (Lang_d
) || isLanguage (Lang_ferite
) ||
2530 isLanguage (Lang_csharp
) || isLanguage (Lang_vala
))
2531 vStringCatS (st
->context
->name
, ".");
2533 vStringCat (st
->context
->name
, token
->name
);
2534 st
->context
->type
= TOKEN_NAME
;
2538 static boolean
inheritingDeclaration (declType decl
)
2540 return (boolean
) (decl
== DECL_CLASS
||
2541 decl
== DECL_STRUCT
||
2542 decl
== DECL_INTERFACE
);
2545 static void processColon (statementInfo
*const st
)
2547 int c
= skipToNonWhite ();
2548 const boolean doubleColon
= (boolean
) (c
== ':');
2552 setToken (st
, TOKEN_DOUBLE_COLON
);
2553 st
->haveQualifyingName
= FALSE
;
2558 if (((isLanguage (Lang_cpp
) || isLanguage (Lang_csharp
) || isLanguage (Lang_vala
)) &&
2559 inheritingDeclaration (st
->declaration
)) ||
2560 isLanguage (Lang_d
))
2562 readParents (st
, ':');
2564 else if (parentDecl (st
) == DECL_STRUCT
)
2566 c
= skipToOneOf (",;");
2568 setToken (st
, TOKEN_COMMA
);
2570 setToken (st
, TOKEN_SEMICOLON
);
2574 const tokenInfo
*const prev
= prevToken (st
, 1);
2575 const tokenInfo
*const prev2
= prevToken (st
, 2);
2576 if (prev
->keyword
== KEYWORD_DEFAULT
||
2577 prev2
->keyword
== KEYWORD_CASE
||
2580 reinitStatement (st
, FALSE
);
2586 /* Skips over any initializing value which may follow an '=' character in a
2587 * variable definition.
2589 static int skipInitializer (statementInfo
*const st
)
2591 boolean done
= FALSE
;
2596 c
= skipToNonWhite ();
2599 longjmp (Exception
, (int) ExceptionFormattingError
);
2603 case ';': done
= TRUE
; break;
2606 if (st
->implementation
== IMP_VIRTUAL
)
2607 st
->implementation
= IMP_PURE_VIRTUAL
;
2610 case '[': skipToMatch ("[]"); break;
2611 case '(': skipToMatch ("()"); break;
2612 case '{': skipToMatch ("{}"); break;
2615 if (insideEnumBody (st
))
2617 else if (! isBraceFormat ())
2619 verbose ("%s: unexpected closing brace at line %lu\n",
2620 getInputFileName (), getInputLineNumber ());
2621 longjmp (Exception
, (int) ExceptionBraceFormattingError
);
2631 static void processInitializer (statementInfo
*const st
)
2633 const boolean inEnumBody
= insideEnumBody (st
);
2634 const int c
= skipInitializer (st
);
2637 setToken (st
, TOKEN_SEMICOLON
);
2639 setToken (st
, TOKEN_COMMA
);
2640 else if (c
== '}' && inEnumBody
)
2643 setToken (st
, TOKEN_COMMA
);
2645 if (st
->scope
== SCOPE_EXTERN
)
2646 st
->scope
= SCOPE_GLOBAL
;
2649 static void parseIdentifier (statementInfo
*const st
, const int c
)
2651 tokenInfo
*const token
= activeToken (st
);
2653 readIdentifier (token
, c
);
2654 if (! isType (token
, TOKEN_NONE
))
2655 processToken (token
, st
);
2658 static void parseGeneralToken (statementInfo
*const st
, const int c
)
2660 const tokenInfo
*const prev
= prevToken (st
, 1);
2664 parseIdentifier (st
, c
);
2665 if (isType (st
->context
, TOKEN_NAME
) &&
2666 isType (activeToken (st
), TOKEN_NAME
) && isType (prev
, TOKEN_NAME
))
2668 initToken (st
->context
);
2671 else if (isExternCDecl (st
, c
))
2673 st
->declaration
= DECL_NOMANGLE
;
2674 st
->scope
= SCOPE_GLOBAL
;
2678 /* Reads characters from the pre-processor and assembles tokens, setting
2679 * the current statement state.
2681 static void nextToken (statementInfo
*const st
)
2684 tokenInfo
*token
= activeToken (st
);
2687 c
= skipToNonWhite();
2690 case EOF
: longjmp (Exception
, (int) ExceptionEOF
); break;
2691 case '(': analyzeParens (st
); token
= activeToken (st
); break;
2692 case '*': setToken (st
, TOKEN_STAR
); break;
2693 case ',': setToken (st
, TOKEN_COMMA
); break;
2694 case ':': processColon (st
); break;
2695 case ';': setToken (st
, TOKEN_SEMICOLON
); break;
2696 case '<': skipToMatch ("<>"); break;
2697 case '=': processInitializer (st
); break;
2699 /* Hack for Vala: [..] can be a function attribute.
2700 * Seems not to have bad side effects, but have to test it more. */
2701 if (!isLanguage (Lang_vala
))
2702 setToken (st
, TOKEN_ARRAY
);
2705 case '{': setToken (st
, TOKEN_BRACE_OPEN
); break;
2706 case '}': setToken (st
, TOKEN_BRACE_CLOSE
); break;
2707 default: parseGeneralToken (st
, c
); break;
2709 } while (isType (token
, TOKEN_NONE
));
2711 /* We want to know about non-keyword variable types */
2712 if (TOKEN_NONE
== st
->firstToken
->type
)
2714 if ((TOKEN_NAME
== token
->type
) || isDataTypeKeyword(token
))
2715 copyToken(st
->firstToken
, token
);
2720 * Scanning support functions
2722 static unsigned int contextual_fake_count
= 0;
2723 static statementInfo
*CurrentStatement
= NULL
;
2725 static statementInfo
*newStatement (statementInfo
*const parent
)
2727 statementInfo
*const st
= xMalloc (1, statementInfo
);
2730 for (i
= 0 ; i
< (unsigned int) NumTokens
; ++i
)
2731 st
->token
[i
] = newToken ();
2733 st
->context
= newToken ();
2734 st
->blockName
= newToken ();
2735 st
->parentClasses
= vStringNew ();
2736 st
->firstToken
= newToken();
2738 initStatement (st
, parent
);
2739 CurrentStatement
= st
;
2744 static void deleteStatement (void)
2746 statementInfo
*const st
= CurrentStatement
;
2747 statementInfo
*const parent
= st
->parent
;
2750 for (i
= 0 ; i
< (unsigned int) NumTokens
; ++i
)
2752 deleteToken(st
->token
[i
]); st
->token
[i
] = NULL
;
2754 deleteToken(st
->blockName
); st
->blockName
= NULL
;
2755 deleteToken(st
->context
); st
->context
= NULL
;
2756 vStringDelete(st
->parentClasses
); st
->parentClasses
= NULL
;
2757 deleteToken(st
->firstToken
);
2759 CurrentStatement
= parent
;
2762 static void deleteAllStatements (void)
2764 while (CurrentStatement
!= NULL
)
2768 static boolean
isStatementEnd (const statementInfo
*const st
)
2770 const tokenInfo
*const token
= activeToken (st
);
2773 if (isType (token
, TOKEN_SEMICOLON
))
2775 else if (isType (token
, TOKEN_BRACE_CLOSE
))
2776 /* Java, D, C#, Vala do not require semicolons to end a block. Neither do
2777 * C++ namespaces. All other blocks require a semicolon to terminate them.
2779 isEnd
= (boolean
) (isLanguage (Lang_java
) || isLanguage (Lang_d
) ||
2780 isLanguage (Lang_csharp
) || isLanguage (Lang_vala
) ||
2781 ! isContextualStatement (st
));
2788 static void checkStatementEnd (statementInfo
*const st
)
2790 const tokenInfo
*const token
= activeToken (st
);
2791 boolean comma
= isType (token
, TOKEN_COMMA
);
2793 if (comma
|| isStatementEnd (st
))
2795 reinitStatementWithToken (st
, activeToken (st
), comma
);
2797 DebugStatement ( if (debug (DEBUG_PARSE
)) printf ("<ES>"); )
2802 cppBeginStatement ();
2807 static void nest (statementInfo
*const st
, const unsigned int nestLevel
)
2809 switch (st
->declaration
)
2813 case DECL_INTERFACE
:
2814 case DECL_NAMESPACE
:
2818 createTags (nestLevel
, st
);
2825 setToken (st
, TOKEN_BRACE_CLOSE
);
2828 static void tagCheck (statementInfo
*const st
)
2830 const tokenInfo
*const token
= activeToken (st
);
2831 const tokenInfo
*const prev
= prevToken (st
, 1);
2832 const tokenInfo
*const prev2
= prevToken (st
, 2);
2834 switch (token
->type
)
2838 if (insideEnumBody (st
))
2839 qualifyEnumeratorTag (st
, token
);
2845 if (st
->haveQualifyingName
)
2846 makeTag (token
, st
, FALSE
, TAG_PACKAGE
);
2850 case TOKEN_BRACE_OPEN
:
2852 if (isType (prev
, TOKEN_ARGS
))
2854 if (st
->haveQualifyingName
)
2856 st
->declaration
= DECL_FUNCTION
;
2857 if (isType (prev2
, TOKEN_NAME
))
2858 copyToken (st
->blockName
, prev2
);
2859 qualifyFunctionTag (st
, prev2
);
2862 else if (isContextualStatement (st
))
2864 tokenInfo
*name_token
= (tokenInfo
*)prev
;
2866 if (isType (name_token
, TOKEN_NAME
))
2868 if (!isLanguage (Lang_vala
))
2869 copyToken (st
->blockName
, name_token
);
2872 switch (st
->declaration
)
2876 case DECL_INTERFACE
:
2877 case DECL_NAMESPACE
:
2879 copyToken (st
->blockName
, name_token
);
2882 /* anything else can be a property */
2884 /* makeTag (prev, st, FALSE, TAG_PROPERTY); */
2885 /* FIXME: temporary hack to get properties shown */
2886 makeTag (prev
, st
, FALSE
, TAG_FIELD
);
2891 else if (isLanguage (Lang_csharp
))
2892 makeTag (prev
, st
, FALSE
, TAG_PROPERTY
);
2895 tokenInfo
*contextual_token
= (tokenInfo
*)prev
;
2896 if(isContextualKeyword (contextual_token
))
2900 name_token
= newToken ();
2901 copyToken (name_token
, contextual_token
);
2903 sprintf(buffer
, "anon_%s_%d", name_token
->name
->buffer
, contextual_fake_count
++);
2904 vStringClear(name_token
->name
);
2905 vStringCatS(name_token
->name
, buffer
);
2907 name_token
->type
= TOKEN_NAME
;
2908 name_token
->keyword
= KEYWORD_NONE
;
2911 contextual_token
= activeToken (st
);
2912 copyToken (contextual_token
, token
);
2913 copyToken ((tokenInfo
*const)token
, name_token
);
2914 copyToken (st
->blockName
, name_token
);
2915 copyToken (st
->firstToken
, name_token
);
2918 qualifyBlockTag (st
, name_token
);
2923 case TOKEN_SEMICOLON
:
2926 if (insideEnumBody (st
))
2928 else if (isType (prev
, TOKEN_NAME
))
2930 if (isContextualKeyword (prev2
))
2931 makeTag (prev
, st
, TRUE
, TAG_EXTERN_VAR
);
2933 qualifyVariableTag (st
, prev
);
2935 else if (isType (prev
, TOKEN_ARGS
) && isType (prev2
, TOKEN_NAME
))
2937 qualifyFunctionDeclTag (st
, prev2
);
2946 /* Parses the current file and decides whether to write out and tags that
2949 static void createTags (const unsigned int nestLevel
,
2950 statementInfo
*const parent
)
2952 statementInfo
*const st
= newStatement (parent
);
2954 DebugStatement ( if (nestLevel
> 0) debugParseNest (TRUE
, nestLevel
); )
2961 token
= activeToken (st
);
2963 if (isType (token
, TOKEN_BRACE_CLOSE
))
2969 verbose ("%s: unexpected closing brace at line %lu\n",
2970 getInputFileName (), getInputLineNumber ());
2971 longjmp (Exception
, (int) ExceptionBraceFormattingError
);
2974 else if (isType (token
, TOKEN_DOUBLE_COLON
))
2976 addContext (st
, prevToken (st
, 1));
2981 tagCheck (st
);/* this can add new token */
2982 if (isType (activeToken (st
), TOKEN_BRACE_OPEN
))
2983 nest (st
, nestLevel
+ 1);
2984 checkStatementEnd (st
);
2988 DebugStatement ( if (nestLevel
> 0) debugParseNest (FALSE
, nestLevel
- 1); )
2991 static boolean
findCTags (const unsigned int passCount
)
2993 exception_t exception
;
2996 Assert (passCount
< 3);
2997 cppInit ((boolean
) (passCount
> 1), isLanguage (Lang_csharp
));
2999 exception
= (exception_t
) setjmp (Exception
);
3002 if (exception
== ExceptionNone
)
3004 createTags (0, NULL
);
3008 deleteAllStatements ();
3009 if (exception
== ExceptionBraceFormattingError
&& passCount
== 1)
3012 verbose ("%s: retrying file with fallback brace matching algorithm\n",
3013 getInputFileName ());
3020 static void buildKeywordHash (const langType language
, unsigned int idx
)
3022 const size_t count
= sizeof (KeywordTable
) / sizeof (KeywordTable
[0]);
3024 for (i
= 0 ; i
< count
; ++i
)
3026 const keywordDesc
* const p
= &KeywordTable
[i
];
3027 if (p
->isValid
[idx
])
3028 addKeyword (p
->name
, language
, (int) p
->id
);
3032 static void initializeCParser (const langType language
)
3034 contextual_fake_count
= 0;
3036 buildKeywordHash (language
, 0);
3039 static void initializeCppParser (const langType language
)
3041 contextual_fake_count
= 0;
3042 Lang_cpp
= language
;
3043 buildKeywordHash (language
, 1);
3046 static void initializeJavaParser (const langType language
)
3048 contextual_fake_count
= 0;
3049 Lang_java
= language
;
3050 buildKeywordHash (language
, 3);
3053 static void initializeDParser (const langType language
)
3055 contextual_fake_count
= 0;
3057 buildKeywordHash (language
, 6);
3060 static void initializeGLSLParser (const langType language
)
3062 contextual_fake_count
= 0;
3063 Lang_glsl
= language
;
3064 buildKeywordHash (language
, 0); /* C keywords */
3067 static void initializeFeriteParser (const langType language
)
3069 contextual_fake_count
= 0;
3070 Lang_ferite
= language
;
3071 buildKeywordHash (language
, 1); /* C++ keywords */
3074 static void initializeCsharpParser (const langType language
)
3076 contextual_fake_count
= 0;
3077 Lang_csharp
= language
;
3078 buildKeywordHash (language
, 2);
3081 static void initializeValaParser (const langType language
)
3083 contextual_fake_count
= 0;
3084 Lang_vala
= language
;
3085 buildKeywordHash (language
, 5);
3088 extern parserDefinition
* CParser (void)
3090 static const char *const extensions
[] = { "c", "pc", "sc", NULL
};
3091 parserDefinition
* def
= parserNew ("C");
3092 def
->kinds
= CKinds
;
3093 def
->kindCount
= KIND_COUNT (CKinds
);
3094 def
->extensions
= extensions
;
3095 def
->parser2
= findCTags
;
3096 def
->initialize
= initializeCParser
;
3100 extern parserDefinition
* CppParser (void)
3102 static const char *const extensions
[] = {
3103 "c++", "cc", "cp", "cpp", "cxx", "h", "h++", "hh", "hp", "hpp", "hxx",
3105 #ifndef CASE_INSENSITIVE_FILENAMES
3110 parserDefinition
* def
= parserNew ("C++");
3111 def
->kinds
= CKinds
;
3112 def
->kindCount
= KIND_COUNT (CKinds
);
3113 def
->extensions
= extensions
;
3114 def
->parser2
= findCTags
;
3115 def
->initialize
= initializeCppParser
;
3119 extern parserDefinition
* JavaParser (void)
3121 static const char *const extensions
[] = { "java", NULL
};
3122 parserDefinition
* def
= parserNew ("Java");
3123 def
->kinds
= JavaKinds
;
3124 def
->kindCount
= KIND_COUNT (JavaKinds
);
3125 def
->extensions
= extensions
;
3126 def
->parser2
= findCTags
;
3127 def
->initialize
= initializeJavaParser
;
3131 extern parserDefinition
* DParser (void)
3133 static const char *const extensions
[] = { "d", "di", NULL
};
3134 parserDefinition
* def
= parserNew ("D");
3135 def
->kinds
= DKinds
;
3136 def
->kindCount
= KIND_COUNT (DKinds
);
3137 def
->extensions
= extensions
;
3138 def
->parser2
= findCTags
;
3139 def
->initialize
= initializeDParser
;
3143 extern parserDefinition
* GLSLParser (void)
3145 static const char *const extensions
[] = { "glsl", "frag", "vert", NULL
};
3146 parserDefinition
* def
= parserNew ("GLSL");
3147 def
->kinds
= CKinds
;
3148 def
->kindCount
= KIND_COUNT (CKinds
);
3149 def
->extensions
= extensions
;
3150 def
->parser2
= findCTags
;
3151 def
->initialize
= initializeGLSLParser
;
3155 extern parserDefinition
* FeriteParser (void)
3157 static const char *const extensions
[] = { "fe", NULL
};
3158 parserDefinition
* def
= parserNew ("Ferite");
3159 def
->kinds
= CKinds
;
3160 def
->kindCount
= KIND_COUNT (CKinds
);
3161 def
->extensions
= extensions
;
3162 def
->parser2
= findCTags
;
3163 def
->initialize
= initializeFeriteParser
;
3167 extern parserDefinition
* CsharpParser (void)
3169 static const char *const extensions
[] = { "cs", NULL
};
3170 parserDefinition
* def
= parserNew ("C#");
3171 def
->kinds
= CsharpKinds
;
3172 def
->kindCount
= KIND_COUNT (CsharpKinds
);
3173 def
->extensions
= extensions
;
3174 def
->parser2
= findCTags
;
3175 def
->initialize
= initializeCsharpParser
;
3179 extern parserDefinition
* ValaParser (void)
3181 static const char *const extensions
[] = { "vala", NULL
};
3182 parserDefinition
* def
= parserNew ("Vala");
3183 def
->kinds
= ValaKinds
;
3184 def
->kindCount
= KIND_COUNT (ValaKinds
);
3185 def
->extensions
= extensions
;
3186 def
->parser2
= findCTags
;
3187 def
->initialize
= initializeValaParser
;
3190 /* vi:set tabstop=8 shiftwidth=4: */