12683f446SJiří Techet /*
22683f446SJiří Techet * Copyright (c) 1996-2003, Darren Hiebert
32683f446SJiří Techet *
42683f446SJiří Techet * This source code is released for free distribution under the terms of the
52683f446SJiří Techet * GNU General Public License version 2 or (at your option) any later version.
62683f446SJiří Techet *
701dc7f65SJiří Techet * This module contains functions for parsing and scanning Vera
82683f446SJiří Techet * source files.
92683f446SJiří Techet */
102683f446SJiří Techet
112683f446SJiří Techet /*
122683f446SJiří Techet * INCLUDE FILES
132683f446SJiří Techet */
142683f446SJiří Techet #include "general.h" /* must always come first */
152683f446SJiří Techet
162683f446SJiří Techet #include <string.h>
172683f446SJiří Techet #include <setjmp.h>
182683f446SJiří Techet
192683f446SJiří Techet #include "debug.h"
202683f446SJiří Techet #include "entry.h"
212683f446SJiří Techet #include "cpreprocessor.h"
222683f446SJiří Techet #include "keyword.h"
232683f446SJiří Techet #include "options.h"
242683f446SJiří Techet #include "parse.h"
252683f446SJiří Techet #include "read.h"
262683f446SJiří Techet #include "routines.h"
272683f446SJiří Techet #include "selectors.h"
282683f446SJiří Techet #include "xtag.h"
292683f446SJiří Techet
302683f446SJiří Techet /*
312683f446SJiří Techet * MACROS
322683f446SJiří Techet */
332683f446SJiří Techet
342683f446SJiří Techet #define activeToken(st) ((st)->token [(int) (st)->tokenIndex])
352683f446SJiří Techet #define parentDecl(st) ((st)->parent == NULL ? \
362683f446SJiří Techet DECL_NONE : (st)->parent->declaration)
372683f446SJiří Techet #define isType(token,t) (bool) ((token)->type == (t))
382683f446SJiří Techet #define insideEnumBody(st) ((st)->parent == NULL ? false : \
392683f446SJiří Techet (bool) ((st)->parent->declaration == DECL_ENUM))
402683f446SJiří Techet #define insideInterfaceBody(st) ((st)->parent == NULL ? false : \
412683f446SJiří Techet (bool) ((st)->parent->declaration == DECL_INTERFACE))
422683f446SJiří Techet #define isSignalDirection(token) (bool)(( (token)->keyword == KEYWORD_INPUT ) ||\
432683f446SJiří Techet ( (token)->keyword == KEYWORD_OUTPUT ) ||\
442683f446SJiří Techet ( (token)->keyword == KEYWORD_INOUT ) )
452683f446SJiří Techet
462683f446SJiří Techet #define isOneOf(c,s) (bool) (strchr ((s), (c)) != NULL)
472683f446SJiří Techet
482683f446SJiří Techet
492683f446SJiří Techet /*
502683f446SJiří Techet * DATA DECLARATIONS
512683f446SJiří Techet */
522683f446SJiří Techet
532683f446SJiří Techet enum { NumTokens = 3 };
542683f446SJiří Techet
552683f446SJiří Techet typedef enum eException {
562683f446SJiří Techet ExceptionNone, ExceptionEOF, ExceptionFormattingError,
572683f446SJiří Techet ExceptionBraceFormattingError
582683f446SJiří Techet } exception_t;
592683f446SJiří Techet
602683f446SJiří Techet /* Used to specify type of keyword.
612683f446SJiří Techet */
622683f446SJiří Techet enum eKeywordId {
637bdd792eSJiří Techet KEYWORD_BAD_STATE, KEYWORD_BAD_TRANS,
642683f446SJiří Techet KEYWORD_BIND, KEYWORD_BIND_VAR, KEYWORD_BIT,
657bdd792eSJiří Techet KEYWORD_CLASS, KEYWORD_CLOCK,
662683f446SJiří Techet KEYWORD_CONSTRAINT, KEYWORD_COVERAGE_BLOCK, KEYWORD_COVERAGE_DEF,
677bdd792eSJiří Techet KEYWORD_ENUM, KEYWORD_EXTERN,
682683f446SJiří Techet KEYWORD_EXTENDS, KEYWORD_EVENT,
697bdd792eSJiří Techet KEYWORD_FUNCTION,
702683f446SJiří Techet KEYWORD_HDL_NODE,
712683f446SJiří Techet KEYWORD_INOUT, KEYWORD_INPUT, KEYWORD_INTEGER, KEYWORD_INTERFACE,
727bdd792eSJiří Techet KEYWORD_LOCAL,
732683f446SJiří Techet KEYWORD_M_BAD_STATE, KEYWORD_M_BAD_TRANS, KEYWORD_M_STATE, KEYWORD_M_TRANS,
747bdd792eSJiří Techet KEYWORD_NEWCOV,
752683f446SJiří Techet KEYWORD_NHOLD, KEYWORD_NSAMPLE,
767bdd792eSJiří Techet KEYWORD_OUTPUT,
777bdd792eSJiří Techet KEYWORD_PACKED, KEYWORD_PORT, KEYWORD_PHOLD,
782683f446SJiří Techet KEYWORD_PROGRAM, KEYWORD_PROTECTED, KEYWORD_PSAMPLE, KEYWORD_PUBLIC,
792683f446SJiří Techet KEYWORD_SHADOW, KEYWORD_STATE,
807bdd792eSJiří Techet KEYWORD_STATIC, KEYWORD_STRING,
817bdd792eSJiří Techet KEYWORD_TASK,
827bdd792eSJiří Techet KEYWORD_TRANS, KEYWORD_TRANSITION,
837bdd792eSJiří Techet KEYWORD_TYPEDEF,
847bdd792eSJiří Techet KEYWORD_VIRTUAL, KEYWORD_VOID
852683f446SJiří Techet };
862683f446SJiří Techet typedef int keywordId; /* to allow KEYWORD_NONE */
872683f446SJiří Techet
882683f446SJiří Techet /* Used to determine whether keyword is valid for the current language and
892683f446SJiří Techet * what its ID is.
902683f446SJiří Techet */
912683f446SJiří Techet typedef struct sKeywordDesc {
922683f446SJiří Techet const char *name;
932683f446SJiří Techet keywordId id;
942683f446SJiří Techet } keywordDesc;
952683f446SJiří Techet
962683f446SJiří Techet /* Used for reporting the type of object parsed by nextToken ().
972683f446SJiří Techet */
982683f446SJiří Techet typedef enum eTokenType {
992683f446SJiří Techet TOKEN_NONE, /* none */
1002683f446SJiří Techet TOKEN_ARGS, /* a parenthetical pair and its contents */
1012683f446SJiří Techet TOKEN_BRACE_CLOSE,
1022683f446SJiří Techet TOKEN_BRACE_OPEN,
1032683f446SJiří Techet TOKEN_COLON, /* the colon character */
1042683f446SJiří Techet TOKEN_COMMA, /* the comma character */
1052683f446SJiří Techet TOKEN_DOUBLE_COLON, /* double colon indicates nested-name-specifier */
1062683f446SJiří Techet TOKEN_KEYWORD,
1072683f446SJiří Techet TOKEN_NAME, /* an unknown name */
1082683f446SJiří Techet TOKEN_PAREN_NAME, /* a single name in parentheses */
1092683f446SJiří Techet TOKEN_SEMICOLON, /* the semicolon character */
1102683f446SJiří Techet TOKEN_COUNT
1112683f446SJiří Techet } tokenType;
1122683f446SJiří Techet
1132683f446SJiří Techet /* This describes the scoping of the current statement.
1142683f446SJiří Techet */
1152683f446SJiří Techet typedef enum eTagScope {
1162683f446SJiří Techet SCOPE_GLOBAL, /* no storage class specified */
1172683f446SJiří Techet SCOPE_STATIC, /* static storage class */
1182683f446SJiří Techet SCOPE_EXTERN, /* external storage class */
1192683f446SJiří Techet SCOPE_TYPEDEF, /* scoping depends upon context */
1202683f446SJiří Techet SCOPE_COUNT
1212683f446SJiří Techet } tagScope;
1222683f446SJiří Techet
1232683f446SJiří Techet typedef enum eDeclaration {
1242683f446SJiří Techet DECL_NONE,
1252683f446SJiří Techet DECL_BASE, /* base type (default) */
1262683f446SJiří Techet DECL_CLASS,
1272683f446SJiří Techet DECL_ENUM,
1282683f446SJiří Techet DECL_EVENT,
1292683f446SJiří Techet DECL_FUNCTION,
1302683f446SJiří Techet DECL_INTERFACE,
13101dc7f65SJiří Techet DECL_PROGRAM,
13201dc7f65SJiří Techet DECL_TASK,
1332683f446SJiří Techet DECL_COUNT
1342683f446SJiří Techet } declType;
1352683f446SJiří Techet
1362683f446SJiří Techet typedef enum eVisibilityType {
1372683f446SJiří Techet ACCESS_UNDEFINED,
1382683f446SJiří Techet ACCESS_LOCAL,
1392683f446SJiří Techet ACCESS_PRIVATE,
1402683f446SJiří Techet ACCESS_PROTECTED,
1412683f446SJiří Techet ACCESS_PUBLIC,
1422683f446SJiří Techet ACCESS_COUNT
1432683f446SJiří Techet } accessType;
1442683f446SJiří Techet
1452683f446SJiří Techet /* Information about the parent class of a member (if any).
1462683f446SJiří Techet */
1472683f446SJiří Techet typedef struct sMemberInfo {
1482683f446SJiří Techet accessType access; /* access of current statement */
1492683f446SJiří Techet accessType accessDefault; /* access default for current statement */
1502683f446SJiří Techet } memberInfo;
1512683f446SJiří Techet
1522683f446SJiří Techet typedef struct sTokenInfo {
1532683f446SJiří Techet tokenType type;
1542683f446SJiří Techet keywordId keyword;
1552683f446SJiří Techet vString* name; /* the name of the token */
1562683f446SJiří Techet unsigned long lineNumber; /* line number of tag */
1572683f446SJiří Techet MIOPos filePosition; /* file position of line containing name */
1582683f446SJiří Techet } tokenInfo;
1592683f446SJiří Techet
1602683f446SJiří Techet typedef enum eImplementation {
1612683f446SJiří Techet IMP_DEFAULT,
1622683f446SJiří Techet IMP_VIRTUAL,
1632683f446SJiří Techet IMP_PURE_VIRTUAL,
1642683f446SJiří Techet IMP_COUNT
1652683f446SJiří Techet } impType;
1662683f446SJiří Techet
1672683f446SJiří Techet /* Describes the statement currently undergoing analysis.
1682683f446SJiří Techet */
1692683f446SJiří Techet typedef struct sStatementInfo {
1702683f446SJiří Techet tagScope scope;
1712683f446SJiří Techet declType declaration; /* specifier associated with TOKEN_SPEC */
1722683f446SJiří Techet bool gotName; /* was a name parsed yet? */
1732683f446SJiří Techet bool haveQualifyingName; /* do we have a name we are considering? */
1742683f446SJiří Techet bool gotParenName; /* was a name inside parentheses parsed yet? */
1752683f446SJiří Techet bool gotArgs; /* was a list of parameters parsed yet? */
1762683f446SJiří Techet bool isPointer; /* is 'name' a pointer? */
1772683f446SJiří Techet bool inFunction; /* are we inside of a function? */
1782683f446SJiří Techet bool assignment; /* have we handled an '='? */
1792683f446SJiří Techet bool notVariable; /* has a variable declaration been disqualified ? */
1802683f446SJiří Techet impType implementation; /* abstract or concrete implementation? */
1812683f446SJiří Techet unsigned int tokenIndex; /* currently active token */
1822683f446SJiří Techet tokenInfo* token [(int) NumTokens];
1832683f446SJiří Techet tokenInfo* context; /* accumulated scope of current statement */
1842683f446SJiří Techet tokenInfo* blockName; /* name of current block */
1852683f446SJiří Techet memberInfo member; /* information regarding parent class/struct */
1862683f446SJiří Techet vString* parentClasses; /* parent classes */
1872683f446SJiří Techet struct sStatementInfo *parent; /* statement we are nested within */
1882683f446SJiří Techet } statementInfo;
1892683f446SJiří Techet
1902683f446SJiří Techet /* Describes the type of tag being generated.
1912683f446SJiří Techet */
1922683f446SJiří Techet typedef enum eTagType {
1932683f446SJiří Techet TAG_UNDEFINED,
1942683f446SJiří Techet TAG_CLASS, /* class name */
1952683f446SJiří Techet TAG_ENUM, /* enumeration name */
1962683f446SJiří Techet TAG_ENUMERATOR, /* enumerator (enumeration value) */
1972683f446SJiří Techet TAG_EVENT, /* event */
1982683f446SJiří Techet TAG_FUNCTION, /* function definition */
1992683f446SJiří Techet TAG_INTERFACE, /* interface declaration */
2002683f446SJiří Techet TAG_LOCAL, /* local variable definition */
2012683f446SJiří Techet TAG_MEMBER, /* structure, class or interface member */
2022683f446SJiří Techet TAG_PROGRAM, /* program name */
2032683f446SJiří Techet TAG_PROTOTYPE, /* function prototype or declaration */
204b9c6970bSJiří Techet TAG_SIGNAL, /* signal name */
2052683f446SJiří Techet TAG_TASK, /* task name */
2062683f446SJiří Techet TAG_TYPEDEF, /* typedef name / D alias name */
2072683f446SJiří Techet TAG_VARIABLE, /* variable definition */
2082683f446SJiří Techet TAG_EXTERN_VAR, /* external variable declaration */
2092683f446SJiří Techet TAG_LABEL, /* goto label */
2102683f446SJiří Techet TAG_COUNT /* must be last */
2112683f446SJiří Techet } tagType;
2122683f446SJiří Techet
2132683f446SJiří Techet typedef struct sParenInfo {
2142683f446SJiří Techet bool isPointer;
2152683f446SJiří Techet bool isParamList;
2162683f446SJiří Techet bool isNameCandidate;
2172683f446SJiří Techet bool invalidContents;
2182683f446SJiří Techet bool nestedArgs;
2192683f446SJiří Techet unsigned int parameterCount;
2202683f446SJiří Techet } parenInfo;
2212683f446SJiří Techet
2222683f446SJiří Techet /*
2232683f446SJiří Techet * DATA DEFINITIONS
2242683f446SJiří Techet */
2252683f446SJiří Techet
2262683f446SJiří Techet static jmp_buf Exception;
2272683f446SJiří Techet
2282683f446SJiří Techet static langType Lang_vera;
2292683f446SJiří Techet static vString *Signature;
2302683f446SJiří Techet static bool CollectingSignature;
2312683f446SJiří Techet
2322683f446SJiří Techet /* Number used to uniquely identify anonymous structs and unions. */
2332683f446SJiří Techet static int AnonymousID = 0;
2342683f446SJiří Techet
2352683f446SJiří Techet #define COMMONK_UNDEFINED -1
2362683f446SJiří Techet
2372683f446SJiří Techet
2382683f446SJiří Techet /* Used to index into the VeraKinds table. */
2392683f446SJiří Techet typedef enum {
2402683f446SJiří Techet VR_MACRO_UNDEF,
2412683f446SJiří Techet VR_MACRO_CONDITION,
2422683f446SJiří Techet } veraMacroRole;
2432683f446SJiří Techet
2442683f446SJiří Techet static roleDefinition VeraMacroRoles [] = {
2452683f446SJiří Techet RoleTemplateUndef,
2462683f446SJiří Techet RoleTemplateCondition,
2472683f446SJiří Techet };
2482683f446SJiří Techet
2492683f446SJiří Techet
2502683f446SJiří Techet typedef enum {
2512683f446SJiří Techet VR_HEADER_SYSTEM,
2522683f446SJiří Techet VR_HEADER_LOCAL,
2532683f446SJiří Techet } veraHeaderRole;
2542683f446SJiří Techet
2552683f446SJiří Techet static roleDefinition VeraHeaderRoles [] = {
2562683f446SJiří Techet RoleTemplateSystem,
2572683f446SJiří Techet RoleTemplateLocal,
2582683f446SJiří Techet };
2592683f446SJiří Techet
2602683f446SJiří Techet typedef enum {
2612683f446SJiří Techet VK_UNDEFINED = COMMONK_UNDEFINED,
2622683f446SJiří Techet VK_CLASS, VK_DEFINE, VK_ENUMERATOR, VK_FUNCTION,
2632683f446SJiří Techet VK_ENUMERATION, VK_INTERFACE, VK_LOCAL, VK_MEMBER, VK_PROGRAM, VK_PROTOTYPE,
2642683f446SJiří Techet VK_SIGNAL, VK_TASK, VK_TYPEDEF, VK_VARIABLE,
2652683f446SJiří Techet VK_EXTERN_VARIABLE, VK_HEADER, VK_MACRO_PARAM,
2662683f446SJiří Techet } veraKind;
2672683f446SJiří Techet
2682683f446SJiří Techet static kindDefinition VeraKinds [] = {
2692683f446SJiří Techet { true, 'c', "class", "classes"},
2702683f446SJiří Techet { true, 'd', "macro", "macro definitions",
2712683f446SJiří Techet .referenceOnly = false, ATTACH_ROLES(VeraMacroRoles)},
2722683f446SJiří Techet { true, 'e', "enumerator", "enumerators (values inside an enumeration)"},
2732683f446SJiří Techet { true, 'f', "function", "function definitions"},
2742683f446SJiří Techet { true, 'g', "enum", "enumeration names"},
2752683f446SJiří Techet { true, 'i', "interface", "interfaces"},
2762683f446SJiří Techet { false, 'l', "local", "local variables"},
2772683f446SJiří Techet { true, 'm', "member", "class, struct, and union members"},
2782683f446SJiří Techet { true, 'p', "program", "programs"},
2792683f446SJiří Techet { false, 'P', "prototype", "function prototypes"},
2802683f446SJiří Techet { true, 's', "signal", "signals"},
2812683f446SJiří Techet { true, 't', "task", "tasks"},
2822683f446SJiří Techet { true, 'T', "typedef", "typedefs"},
2832683f446SJiří Techet { true, 'v', "variable", "variable definitions"},
2842683f446SJiří Techet { false, 'x', "externvar", "external variable declarations"},
2852683f446SJiří Techet { true, 'h', "header", "included header files",
2862683f446SJiří Techet .referenceOnly = true, ATTACH_ROLES(VeraHeaderRoles)},
2872683f446SJiří Techet { false, 'D', "macroParameter", "cpp macro parameters"},
2882683f446SJiří Techet };
2892683f446SJiří Techet
2902683f446SJiří Techet static const keywordDesc KeywordTable [] = {
291*eb1b3c1bSJiří Techet { "bad_state", KEYWORD_BAD_STATE, },
292*eb1b3c1bSJiří Techet { "bad_trans", KEYWORD_BAD_TRANS, },
293*eb1b3c1bSJiří Techet { "bind", KEYWORD_BIND, },
294*eb1b3c1bSJiří Techet { "bind_var", KEYWORD_BIND_VAR, },
295*eb1b3c1bSJiří Techet { "bit", KEYWORD_BIT, },
296*eb1b3c1bSJiří Techet { "class", KEYWORD_CLASS, },
297*eb1b3c1bSJiří Techet { "CLOCK", KEYWORD_CLOCK, },
298*eb1b3c1bSJiří Techet { "constraint", KEYWORD_CONSTRAINT, },
299*eb1b3c1bSJiří Techet { "coverage_block", KEYWORD_COVERAGE_BLOCK, },
300*eb1b3c1bSJiří Techet { "coverage_def", KEYWORD_COVERAGE_DEF, },
301*eb1b3c1bSJiří Techet { "enum", KEYWORD_ENUM, },
302*eb1b3c1bSJiří Techet { "event", KEYWORD_EVENT, },
303*eb1b3c1bSJiří Techet { "extends", KEYWORD_EXTENDS, },
304*eb1b3c1bSJiří Techet { "extern", KEYWORD_EXTERN, },
305*eb1b3c1bSJiří Techet { "function", KEYWORD_FUNCTION, },
306*eb1b3c1bSJiří Techet { "hdl_node", KEYWORD_HDL_NODE, },
307*eb1b3c1bSJiří Techet { "inout", KEYWORD_INOUT, },
308*eb1b3c1bSJiří Techet { "input", KEYWORD_INPUT, },
309*eb1b3c1bSJiří Techet { "integer", KEYWORD_INTEGER, },
310*eb1b3c1bSJiří Techet { "interface", KEYWORD_INTERFACE, },
311*eb1b3c1bSJiří Techet { "local", KEYWORD_LOCAL, },
312*eb1b3c1bSJiří Techet { "m_bad_state", KEYWORD_M_BAD_STATE, },
313*eb1b3c1bSJiří Techet { "m_bad_trans", KEYWORD_M_BAD_TRANS, },
314*eb1b3c1bSJiří Techet { "m_state", KEYWORD_M_STATE, },
315*eb1b3c1bSJiří Techet { "m_trans", KEYWORD_M_TRANS, },
316*eb1b3c1bSJiří Techet { "newcov", KEYWORD_NEWCOV, },
317*eb1b3c1bSJiří Techet { "NHOLD", KEYWORD_NHOLD, },
318*eb1b3c1bSJiří Techet { "NSAMPLE", KEYWORD_NSAMPLE, },
319*eb1b3c1bSJiří Techet { "output", KEYWORD_OUTPUT, },
320*eb1b3c1bSJiří Techet { "packed", KEYWORD_PACKED, },
321*eb1b3c1bSJiří Techet { "PHOLD", KEYWORD_PHOLD, },
322*eb1b3c1bSJiří Techet { "port", KEYWORD_PORT, },
323*eb1b3c1bSJiří Techet { "program", KEYWORD_PROGRAM, },
324*eb1b3c1bSJiří Techet { "protected", KEYWORD_PROTECTED, },
325*eb1b3c1bSJiří Techet { "PSAMPLE", KEYWORD_PSAMPLE, },
326*eb1b3c1bSJiří Techet { "public", KEYWORD_PUBLIC, },
327*eb1b3c1bSJiří Techet { "shadow", KEYWORD_SHADOW, },
328*eb1b3c1bSJiří Techet { "state", KEYWORD_STATE, },
329*eb1b3c1bSJiří Techet { "static", KEYWORD_STATIC, },
330*eb1b3c1bSJiří Techet { "string", KEYWORD_STRING, },
331*eb1b3c1bSJiří Techet { "task", KEYWORD_TASK, },
332*eb1b3c1bSJiří Techet { "trans", KEYWORD_TRANS, },
333*eb1b3c1bSJiří Techet { "transition", KEYWORD_TRANSITION, },
334*eb1b3c1bSJiří Techet { "typedef", KEYWORD_TYPEDEF, },
335*eb1b3c1bSJiří Techet { "virtual", KEYWORD_VIRTUAL, },
336*eb1b3c1bSJiří Techet { "void", KEYWORD_VOID, },
3372683f446SJiří Techet };
3382683f446SJiří Techet
3392683f446SJiří Techet /*
3402683f446SJiří Techet * FUNCTION PROTOTYPES
3412683f446SJiří Techet */
3422683f446SJiří Techet static void createTags (const unsigned int nestLevel, statementInfo *const parent);
3432683f446SJiří Techet
3442683f446SJiří Techet /*
3452683f446SJiří Techet * FUNCTION DEFINITIONS
3462683f446SJiří Techet */
3472683f446SJiří Techet
3482683f446SJiří Techet /*
3492683f446SJiří Techet * Token management
3502683f446SJiří Techet */
3512683f446SJiří Techet
initToken(tokenInfo * const token)3522683f446SJiří Techet static void initToken (tokenInfo* const token)
3532683f446SJiří Techet {
3542683f446SJiří Techet token->type = TOKEN_NONE;
3552683f446SJiří Techet token->keyword = KEYWORD_NONE;
3562683f446SJiří Techet token->lineNumber = getInputLineNumber ();
3572683f446SJiří Techet token->filePosition = getInputFilePosition ();
3582683f446SJiří Techet vStringClear (token->name);
3592683f446SJiří Techet }
3602683f446SJiří Techet
advanceToken(statementInfo * const st)3612683f446SJiří Techet static void advanceToken (statementInfo* const st)
3622683f446SJiří Techet {
3632683f446SJiří Techet if (st->tokenIndex >= (unsigned int) NumTokens - 1)
3642683f446SJiří Techet st->tokenIndex = 0;
3652683f446SJiří Techet else
3662683f446SJiří Techet ++st->tokenIndex;
3672683f446SJiří Techet initToken (st->token [st->tokenIndex]);
3682683f446SJiří Techet }
3692683f446SJiří Techet
prevToken(const statementInfo * const st,unsigned int n)3702683f446SJiří Techet static tokenInfo *prevToken (const statementInfo *const st, unsigned int n)
3712683f446SJiří Techet {
3722683f446SJiří Techet unsigned int tokenIndex;
3732683f446SJiří Techet unsigned int num = (unsigned int) NumTokens;
3742683f446SJiří Techet Assert (n < num);
3752683f446SJiří Techet tokenIndex = (st->tokenIndex + num - n) % num;
3762683f446SJiří Techet return st->token [tokenIndex];
3772683f446SJiří Techet }
3782683f446SJiří Techet
setToken(statementInfo * const st,const tokenType type)3792683f446SJiří Techet static void setToken (statementInfo *const st, const tokenType type)
3802683f446SJiří Techet {
3812683f446SJiří Techet tokenInfo *token;
3822683f446SJiří Techet token = activeToken (st);
3832683f446SJiří Techet initToken (token);
3842683f446SJiří Techet token->type = type;
3852683f446SJiří Techet }
3862683f446SJiří Techet
retardToken(statementInfo * const st)3872683f446SJiří Techet static void retardToken (statementInfo *const st)
3882683f446SJiří Techet {
3892683f446SJiří Techet if (st->tokenIndex == 0)
3902683f446SJiří Techet st->tokenIndex = (unsigned int) NumTokens - 1;
3912683f446SJiří Techet else
3922683f446SJiří Techet --st->tokenIndex;
3932683f446SJiří Techet setToken (st, TOKEN_NONE);
3942683f446SJiří Techet }
3952683f446SJiří Techet
newToken(void)3962683f446SJiří Techet static tokenInfo *newToken (void)
3972683f446SJiří Techet {
3982683f446SJiří Techet tokenInfo *const token = xMalloc (1, tokenInfo);
3992683f446SJiří Techet token->name = vStringNew ();
4002683f446SJiří Techet initToken (token);
4012683f446SJiří Techet return token;
4022683f446SJiří Techet }
4032683f446SJiří Techet
deleteToken(tokenInfo * const token)4042683f446SJiří Techet static void deleteToken (tokenInfo *const token)
4052683f446SJiří Techet {
4062683f446SJiří Techet if (token != NULL)
4072683f446SJiří Techet {
4082683f446SJiří Techet vStringDelete (token->name);
4092683f446SJiří Techet eFree (token);
4102683f446SJiří Techet }
4112683f446SJiří Techet }
4122683f446SJiří Techet
accessString(const accessType access)4132683f446SJiří Techet static const char *accessString (const accessType access)
4142683f446SJiří Techet {
4152683f446SJiří Techet static const char *const names [] = {
416b9c6970bSJiří Techet "?", "local", "private", "protected", "public"
4172683f446SJiří Techet };
4182683f446SJiří Techet Assert (ARRAY_SIZE (names) == ACCESS_COUNT);
4192683f446SJiří Techet Assert ((int) access < ACCESS_COUNT);
4202683f446SJiří Techet return names [(int) access];
4212683f446SJiří Techet }
4222683f446SJiří Techet
4232683f446SJiří Techet /*
4242683f446SJiří Techet * Debugging functions
4252683f446SJiří Techet */
4262683f446SJiří Techet
4272683f446SJiří Techet #ifdef DEBUG
4282683f446SJiří Techet
4292683f446SJiří Techet #define boolString(c) ((c) ? "true" : "false")
4302683f446SJiří Techet
tokenString(const tokenType type)4312683f446SJiří Techet static const char *tokenString (const tokenType type)
4322683f446SJiří Techet {
4332683f446SJiří Techet static const char *const names [] = {
4342683f446SJiří Techet "none", "args", "}", "{", "colon", "comma", "double colon", "keyword",
43501dc7f65SJiří Techet "name", "paren-name", "semicolon"
4362683f446SJiří Techet };
4372683f446SJiří Techet Assert (ARRAY_SIZE (names) == TOKEN_COUNT);
4382683f446SJiří Techet Assert ((int) type < TOKEN_COUNT);
4392683f446SJiří Techet return names [(int) type];
4402683f446SJiří Techet }
4412683f446SJiří Techet
scopeString(const tagScope scope)4422683f446SJiří Techet static const char *scopeString (const tagScope scope)
4432683f446SJiří Techet {
4442683f446SJiří Techet static const char *const names [] = {
44501dc7f65SJiří Techet "global", "static", "extern", "typedef"
4462683f446SJiří Techet };
4472683f446SJiří Techet Assert (ARRAY_SIZE (names) == SCOPE_COUNT);
4482683f446SJiří Techet Assert ((int) scope < SCOPE_COUNT);
4492683f446SJiří Techet return names [(int) scope];
4502683f446SJiří Techet }
4512683f446SJiří Techet
declString(const declType declaration)4522683f446SJiří Techet static const char *declString (const declType declaration)
4532683f446SJiří Techet {
4542683f446SJiří Techet static const char *const names [] = {
45501dc7f65SJiří Techet "?", "base", "class", "enum", "event", "function",
45601dc7f65SJiří Techet "interface",
45701dc7f65SJiří Techet "program", "task"
4582683f446SJiří Techet };
4592683f446SJiří Techet Assert (ARRAY_SIZE (names) == DECL_COUNT);
4602683f446SJiří Techet Assert ((int) declaration < DECL_COUNT);
4612683f446SJiří Techet return names [(int) declaration];
4622683f446SJiří Techet }
4632683f446SJiří Techet
keywordString(const keywordId keyword)4642683f446SJiří Techet static const char *keywordString (const keywordId keyword)
4652683f446SJiří Techet {
4662683f446SJiří Techet const size_t count = ARRAY_SIZE (KeywordTable);
4672683f446SJiří Techet const char *name = "none";
4682683f446SJiří Techet size_t i;
4692683f446SJiří Techet for (i = 0 ; i < count ; ++i)
4702683f446SJiří Techet {
4712683f446SJiří Techet const keywordDesc *p = &KeywordTable [i];
4722683f446SJiří Techet if (p->id == keyword)
4732683f446SJiří Techet {
4742683f446SJiří Techet name = p->name;
4752683f446SJiří Techet break;
4762683f446SJiří Techet }
4772683f446SJiří Techet }
4782683f446SJiří Techet return name;
4792683f446SJiří Techet }
4802683f446SJiří Techet
pt(tokenInfo * const token)4812683f446SJiří Techet static void CTAGS_ATTR_UNUSED pt (tokenInfo *const token)
4822683f446SJiří Techet {
4832683f446SJiří Techet if (isType (token, TOKEN_NAME))
4842683f446SJiří Techet printf ("type: %-12s: %-13s line: %lu\n",
4852683f446SJiří Techet tokenString (token->type), vStringValue (token->name),
4862683f446SJiří Techet token->lineNumber);
4872683f446SJiří Techet else if (isType (token, TOKEN_KEYWORD))
4882683f446SJiří Techet printf ("type: %-12s: %-13s line: %lu\n",
4892683f446SJiří Techet tokenString (token->type), keywordString (token->keyword),
4902683f446SJiří Techet token->lineNumber);
4912683f446SJiří Techet else
4922683f446SJiří Techet printf ("type: %-12s line: %lu\n",
4932683f446SJiří Techet tokenString (token->type), token->lineNumber);
4942683f446SJiří Techet }
4952683f446SJiří Techet
ps(statementInfo * const st)4962683f446SJiří Techet static void CTAGS_ATTR_UNUSED ps (statementInfo *const st)
4972683f446SJiří Techet {
4982683f446SJiří Techet #define P "[%-7u]"
4992683f446SJiří Techet static unsigned int id = 0;
5002683f446SJiří Techet unsigned int i;
5012683f446SJiří Techet printf (P"scope: %s decl: %s gotName: %s gotParenName: %s\n", id,
5022683f446SJiří Techet scopeString (st->scope), declString (st->declaration),
5032683f446SJiří Techet boolString (st->gotName), boolString (st->gotParenName));
5042683f446SJiří Techet printf (P"haveQualifyingName: %s\n", id, boolString (st->haveQualifyingName));
5052683f446SJiří Techet printf (P"access: %s default: %s\n", id, accessString (st->member.access),
5062683f446SJiří Techet accessString (st->member.accessDefault));
5072683f446SJiří Techet printf (P"token : ", id);
5082683f446SJiří Techet pt (activeToken (st));
5092683f446SJiří Techet for (i = 1 ; i < (unsigned int) NumTokens ; ++i)
5102683f446SJiří Techet {
5112683f446SJiří Techet printf (P"prev %u : ", id, i);
5122683f446SJiří Techet pt (prevToken (st, i));
5132683f446SJiří Techet }
5142683f446SJiří Techet printf (P"context: ", id);
5152683f446SJiří Techet pt (st->context);
5162683f446SJiří Techet id++;
5172683f446SJiří Techet #undef P
5182683f446SJiří Techet }
5192683f446SJiří Techet
5202683f446SJiří Techet #endif
5212683f446SJiří Techet
5222683f446SJiří Techet /*
5232683f446SJiří Techet * Statement management
5242683f446SJiří Techet */
5252683f446SJiří Techet
isContextualKeyword(const tokenInfo * const token)5262683f446SJiří Techet static bool isContextualKeyword (const tokenInfo *const token)
5272683f446SJiří Techet {
5282683f446SJiří Techet bool result;
5292683f446SJiří Techet switch (token->keyword)
5302683f446SJiří Techet {
5312683f446SJiří Techet case KEYWORD_CLASS:
5322683f446SJiří Techet case KEYWORD_ENUM:
5332683f446SJiří Techet case KEYWORD_INTERFACE:
5342683f446SJiří Techet result = true;
5352683f446SJiří Techet break;
5362683f446SJiří Techet
5372683f446SJiří Techet default: result = false; break;
5382683f446SJiří Techet }
5392683f446SJiří Techet return result;
5402683f446SJiří Techet }
5412683f446SJiří Techet
isContextualStatement(const statementInfo * const st)5422683f446SJiří Techet static bool isContextualStatement (const statementInfo *const st)
5432683f446SJiří Techet {
5442683f446SJiří Techet bool result = false;
5452683f446SJiří Techet if (st != NULL) switch (st->declaration)
5462683f446SJiří Techet {
5472683f446SJiří Techet case DECL_CLASS:
5482683f446SJiří Techet case DECL_ENUM:
5492683f446SJiří Techet case DECL_INTERFACE:
5502683f446SJiří Techet result = true;
5512683f446SJiří Techet break;
5522683f446SJiří Techet
5532683f446SJiří Techet default: result = false; break;
5542683f446SJiří Techet }
5552683f446SJiří Techet return result;
5562683f446SJiří Techet }
5572683f446SJiří Techet
isMember(const statementInfo * const st)5582683f446SJiří Techet static bool isMember (const statementInfo *const st)
5592683f446SJiří Techet {
5602683f446SJiří Techet bool result;
5612683f446SJiří Techet if (isType (st->context, TOKEN_NAME))
5622683f446SJiří Techet result = true;
5632683f446SJiří Techet else
5642683f446SJiří Techet result = (bool)
5652683f446SJiří Techet (st->parent != NULL && isContextualStatement (st->parent));
5662683f446SJiří Techet return result;
5672683f446SJiří Techet }
5682683f446SJiří Techet
initMemberInfo(statementInfo * const st)5692683f446SJiří Techet static void initMemberInfo (statementInfo *const st)
5702683f446SJiří Techet {
5712683f446SJiří Techet accessType accessDefault = ACCESS_UNDEFINED;
5722683f446SJiří Techet if (st->parent != NULL) switch (st->parent->declaration)
5732683f446SJiří Techet {
5742683f446SJiří Techet case DECL_ENUM:
57523c6e73eSJiří Techet accessDefault = ACCESS_UNDEFINED;
5762683f446SJiří Techet break;
5772683f446SJiří Techet
5782683f446SJiří Techet case DECL_CLASS:
5792683f446SJiří Techet accessDefault = ACCESS_PRIVATE;
5802683f446SJiří Techet break;
5812683f446SJiří Techet
5822683f446SJiří Techet case DECL_INTERFACE:
5832683f446SJiří Techet accessDefault = ACCESS_PUBLIC;
5842683f446SJiří Techet break;
5852683f446SJiří Techet
5862683f446SJiří Techet default: break;
5872683f446SJiří Techet }
5882683f446SJiří Techet st->member.accessDefault = accessDefault;
5892683f446SJiří Techet st->member.access = accessDefault;
5902683f446SJiří Techet }
5912683f446SJiří Techet
reinitStatement(statementInfo * const st,const bool partial)5922683f446SJiří Techet static void reinitStatement (statementInfo *const st, const bool partial)
5932683f446SJiří Techet {
5942683f446SJiří Techet unsigned int i;
5952683f446SJiří Techet
5962683f446SJiří Techet if (! partial)
5972683f446SJiří Techet {
5982683f446SJiří Techet st->scope = SCOPE_GLOBAL;
5992683f446SJiří Techet if (isContextualStatement (st->parent))
6002683f446SJiří Techet st->declaration = DECL_BASE;
6012683f446SJiří Techet else
6022683f446SJiří Techet st->declaration = DECL_NONE;
6032683f446SJiří Techet }
6042683f446SJiří Techet st->gotParenName = false;
6052683f446SJiří Techet st->isPointer = false;
6062683f446SJiří Techet st->inFunction = false;
6072683f446SJiří Techet st->assignment = false;
6082683f446SJiří Techet st->notVariable = false;
6092683f446SJiří Techet st->implementation = IMP_DEFAULT;
6102683f446SJiří Techet st->gotArgs = false;
6112683f446SJiří Techet st->gotName = false;
6122683f446SJiří Techet st->haveQualifyingName = false;
6132683f446SJiří Techet st->tokenIndex = 0;
6142683f446SJiří Techet
6152683f446SJiří Techet if (st->parent != NULL)
6162683f446SJiří Techet st->inFunction = st->parent->inFunction;
6172683f446SJiří Techet
6182683f446SJiří Techet for (i = 0 ; i < (unsigned int) NumTokens ; ++i)
6192683f446SJiří Techet initToken (st->token [i]);
6202683f446SJiří Techet
6212683f446SJiří Techet initToken (st->context);
6222683f446SJiří Techet
6232683f446SJiří Techet /* Keep the block name, so that a variable following after a comma will
6242683f446SJiří Techet * still have the structure name.
6252683f446SJiří Techet */
6262683f446SJiří Techet if (! partial)
6272683f446SJiří Techet initToken (st->blockName);
6282683f446SJiří Techet
6292683f446SJiří Techet vStringClear (st->parentClasses);
6302683f446SJiří Techet
6312683f446SJiří Techet /* Init member info.
6322683f446SJiří Techet */
6332683f446SJiří Techet if (! partial)
6342683f446SJiří Techet st->member.access = st->member.accessDefault;
6352683f446SJiří Techet }
6362683f446SJiří Techet
initStatement(statementInfo * const st,statementInfo * const parent)6372683f446SJiří Techet static void initStatement (statementInfo *const st, statementInfo *const parent)
6382683f446SJiří Techet {
6392683f446SJiří Techet st->parent = parent;
6402683f446SJiří Techet initMemberInfo (st);
6412683f446SJiří Techet reinitStatement (st, false);
6422683f446SJiří Techet }
6432683f446SJiří Techet
6442683f446SJiří Techet /*
6452683f446SJiří Techet * Tag generation functions
6462683f446SJiří Techet */
6472683f446SJiří Techet #define veraTagKind(type) veraTagKindFull(type, true)
6482683f446SJiří Techet #define veraTagKindNoAssert(type) veraTagKindFull(type, false)
veraTagKindFull(const tagType type,bool with_assert)6492683f446SJiří Techet static veraKind veraTagKindFull (const tagType type, bool with_assert) {
6502683f446SJiří Techet veraKind result = VK_UNDEFINED;
6512683f446SJiří Techet switch (type)
6522683f446SJiří Techet {
6532683f446SJiří Techet case TAG_CLASS: result = VK_CLASS; break;
6542683f446SJiří Techet case TAG_ENUM: result = VK_ENUMERATION; break;
6552683f446SJiří Techet case TAG_ENUMERATOR: result = VK_ENUMERATOR; break;
6562683f446SJiří Techet case TAG_FUNCTION: result = VK_FUNCTION; break;
6572683f446SJiří Techet case TAG_INTERFACE: result = VK_INTERFACE; break;
6582683f446SJiří Techet case TAG_LOCAL: result = VK_LOCAL; break;
6592683f446SJiří Techet case TAG_MEMBER: result = VK_MEMBER; break;
6602683f446SJiří Techet case TAG_PROGRAM: result = VK_PROGRAM; break;
6612683f446SJiří Techet case TAG_PROTOTYPE: result = VK_PROTOTYPE; break;
6622683f446SJiří Techet case TAG_SIGNAL: result = VK_SIGNAL; break;
6632683f446SJiří Techet case TAG_TASK: result = VK_TASK; break;
6642683f446SJiří Techet case TAG_TYPEDEF: result = VK_TYPEDEF; break;
6652683f446SJiří Techet case TAG_VARIABLE: result = VK_VARIABLE; break;
6662683f446SJiří Techet case TAG_EXTERN_VAR: result = VK_EXTERN_VARIABLE; break;
6672683f446SJiří Techet
6682683f446SJiří Techet default: if (with_assert) Assert ("Bad Vera tag type" == NULL); break;
6692683f446SJiří Techet }
6702683f446SJiří Techet return result;
6712683f446SJiří Techet }
6722683f446SJiří Techet
kindIndexForType(const tagType type)6732683f446SJiří Techet static int kindIndexForType (const tagType type)
6742683f446SJiří Techet {
67523c6e73eSJiří Techet return veraTagKind (type);
6762683f446SJiří Techet }
6772683f446SJiří Techet
tagName(const tagType type)6782683f446SJiří Techet static const char *tagName (const tagType type)
6792683f446SJiří Techet {
68023c6e73eSJiří Techet return VeraKinds [veraTagKind (type)].name;
6812683f446SJiří Techet }
6822683f446SJiří Techet
includeTag(const tagType type,const bool isFileScope)6832683f446SJiří Techet static bool includeTag (const tagType type, const bool isFileScope)
6842683f446SJiří Techet {
6852683f446SJiří Techet bool result;
6862683f446SJiří Techet int k = COMMONK_UNDEFINED;
6872683f446SJiří Techet
6882683f446SJiří Techet if (isFileScope && !isXtagEnabled(XTAG_FILE_SCOPE))
6892683f446SJiří Techet return false;
6902683f446SJiří Techet
69123c6e73eSJiří Techet k = veraTagKindNoAssert (type);
6922683f446SJiří Techet if (k == COMMONK_UNDEFINED)
6932683f446SJiří Techet result = false;
6942683f446SJiří Techet else
6952683f446SJiří Techet result = isInputLanguageKindEnabled (k);
6962683f446SJiří Techet
6972683f446SJiří Techet return result;
6982683f446SJiří Techet }
6992683f446SJiří Techet
declToTagType(const declType declaration)7002683f446SJiří Techet static tagType declToTagType (const declType declaration)
7012683f446SJiří Techet {
7022683f446SJiří Techet tagType type = TAG_UNDEFINED;
7032683f446SJiří Techet
7042683f446SJiří Techet switch (declaration)
7052683f446SJiří Techet {
7062683f446SJiří Techet case DECL_CLASS: type = TAG_CLASS; break;
7072683f446SJiří Techet case DECL_ENUM: type = TAG_ENUM; break;
7082683f446SJiří Techet case DECL_EVENT: type = TAG_EVENT; break;
7092683f446SJiří Techet case DECL_FUNCTION: type = TAG_FUNCTION; break;
7102683f446SJiří Techet case DECL_INTERFACE: type = TAG_INTERFACE; break;
7112683f446SJiří Techet case DECL_PROGRAM: type = TAG_PROGRAM; break;
7122683f446SJiří Techet case DECL_TASK: type = TAG_TASK; break;
7132683f446SJiří Techet
7142683f446SJiří Techet default: Assert ("Unexpected declaration" == NULL); break;
7152683f446SJiří Techet }
7162683f446SJiří Techet return type;
7172683f446SJiří Techet }
7182683f446SJiří Techet
accessField(const statementInfo * const st)7192683f446SJiří Techet static const char* accessField (const statementInfo *const st)
7202683f446SJiří Techet {
7212683f446SJiří Techet const char* result = NULL;
7222683f446SJiří Techet if (st->member.access != ACCESS_UNDEFINED)
7232683f446SJiří Techet result = accessString (st->member.access);
7242683f446SJiří Techet return result;
7252683f446SJiří Techet }
7262683f446SJiří Techet
addOtherFields(tagEntryInfo * const tag,const tagType type,const statementInfo * const st,vString * const scope,vString * const typeRef)7272683f446SJiří Techet static void addOtherFields (tagEntryInfo* const tag, const tagType type,
7282683f446SJiří Techet const statementInfo *const st,
7292683f446SJiří Techet vString *const scope, vString *const typeRef)
7302683f446SJiří Techet {
7312683f446SJiří Techet /* For selected tag types, append an extension flag designating the
7322683f446SJiří Techet * parent object in which the tag is defined.
7332683f446SJiří Techet */
7342683f446SJiří Techet switch (type)
7352683f446SJiří Techet {
7362683f446SJiří Techet default: break;
7372683f446SJiří Techet
7382683f446SJiří Techet case TAG_FUNCTION:
7392683f446SJiří Techet case TAG_PROTOTYPE:
7402683f446SJiří Techet if (vStringLength (Signature) > 0)
7412683f446SJiří Techet tag->extensionFields.signature = vStringValue (Signature);
7422683f446SJiří Techet case TAG_CLASS:
7432683f446SJiří Techet case TAG_ENUM:
7442683f446SJiří Techet case TAG_ENUMERATOR:
7452683f446SJiří Techet case TAG_EVENT:
7462683f446SJiří Techet case TAG_INTERFACE:
7472683f446SJiří Techet case TAG_MEMBER:
7482683f446SJiří Techet case TAG_SIGNAL:
7492683f446SJiří Techet case TAG_TASK:
7502683f446SJiří Techet case TAG_TYPEDEF:
75101dc7f65SJiří Techet if (vStringLength (scope) > 0 && isMember (st))
7522683f446SJiří Techet {
7532683f446SJiří Techet tagType ptype;
7542683f446SJiří Techet
7552683f446SJiří Techet if (isType (st->context, TOKEN_NAME))
7562683f446SJiří Techet {
7572683f446SJiří Techet tag->extensionFields.scopeKindIndex = kindIndexForType (TAG_CLASS);
7582683f446SJiří Techet tag->extensionFields.scopeName = vStringValue (scope);
7592683f446SJiří Techet }
7602683f446SJiří Techet else if ((ptype = declToTagType (parentDecl (st))) &&
7612683f446SJiří Techet includeTag (ptype, isXtagEnabled(XTAG_FILE_SCOPE)))
7622683f446SJiří Techet {
7632683f446SJiří Techet tag->extensionFields.scopeKindIndex = kindIndexForType (ptype);
7642683f446SJiří Techet tag->extensionFields.scopeName = vStringValue (scope);
7652683f446SJiří Techet }
7662683f446SJiří Techet }
767b9c6970bSJiří Techet if ((type == TAG_CLASS || type == TAG_INTERFACE) &&
768b9c6970bSJiří Techet vStringLength (st->parentClasses) > 0)
7692683f446SJiří Techet {
7702683f446SJiří Techet
7712683f446SJiří Techet tag->extensionFields.inheritance =
7722683f446SJiří Techet vStringValue (st->parentClasses);
7732683f446SJiří Techet }
7742683f446SJiří Techet if (isMember (st))
7752683f446SJiří Techet {
7762683f446SJiří Techet tag->extensionFields.access = accessField (st);
7772683f446SJiří Techet }
7782683f446SJiří Techet break;
7792683f446SJiří Techet }
7802683f446SJiří Techet
7812683f446SJiří Techet /* Add typename info, type of the tag and name of struct/union/etc. */
7822683f446SJiří Techet if ((type == TAG_TYPEDEF || type == TAG_VARIABLE || type == TAG_MEMBER)
7832683f446SJiří Techet && isContextualStatement(st))
7842683f446SJiří Techet {
7852683f446SJiří Techet char *p;
7862683f446SJiří Techet
7872683f446SJiří Techet tag->extensionFields.typeRef [0] =
7882683f446SJiří Techet tagName (declToTagType (st->declaration));
7892683f446SJiří Techet p = vStringValue (st->blockName->name);
7902683f446SJiří Techet
7912683f446SJiří Techet /* If there was no {} block get the name from the token before the
7922683f446SJiří Techet * name (current token is ';' or ',', previous token is the name).
7932683f446SJiří Techet */
7942683f446SJiří Techet if (p == NULL || *p == '\0')
7952683f446SJiří Techet {
7962683f446SJiří Techet tokenInfo *const prev2 = prevToken (st, 2);
7972683f446SJiří Techet if (isType (prev2, TOKEN_NAME))
7982683f446SJiří Techet p = vStringValue (prev2->name);
7992683f446SJiří Techet }
8002683f446SJiří Techet
8012683f446SJiří Techet /* Prepend the scope name if there is one. */
8022683f446SJiří Techet if (vStringLength (scope) > 0)
8032683f446SJiří Techet {
8042683f446SJiří Techet vStringCopy(typeRef, scope);
8052683f446SJiří Techet vStringCatS(typeRef, p);
8062683f446SJiří Techet p = vStringValue (typeRef);
8072683f446SJiří Techet }
8082683f446SJiří Techet tag->extensionFields.typeRef [1] = p;
8092683f446SJiří Techet }
8102683f446SJiří Techet }
8112683f446SJiří Techet
findScopeHierarchy(vString * const string,const statementInfo * const st)8122683f446SJiří Techet static bool findScopeHierarchy (vString *const string, const statementInfo *const st)
8132683f446SJiří Techet {
8142683f446SJiří Techet bool found = false;
8152683f446SJiří Techet
8162683f446SJiří Techet vStringClear (string);
8172683f446SJiří Techet
8182683f446SJiří Techet if (isType (st->context, TOKEN_NAME))
8192683f446SJiří Techet {
8202683f446SJiří Techet vStringCopy (string, st->context->name);
8212683f446SJiří Techet found = true;
8222683f446SJiří Techet }
8232683f446SJiří Techet
8242683f446SJiří Techet if (st->parent != NULL)
8252683f446SJiří Techet {
8262683f446SJiří Techet vString *temp = vStringNew ();
8272683f446SJiří Techet const statementInfo *s;
8282683f446SJiří Techet for (s = st->parent ; s != NULL ; s = s->parent)
8292683f446SJiří Techet {
8302683f446SJiří Techet if (isContextualStatement (s) ||
8312683f446SJiří Techet s->declaration == DECL_PROGRAM)
8322683f446SJiří Techet {
8332683f446SJiří Techet found = true;
8342683f446SJiří Techet vStringCopy (temp, string);
8352683f446SJiří Techet vStringClear (string);
8362683f446SJiří Techet if (isType (s->blockName, TOKEN_NAME))
8372683f446SJiří Techet {
8382683f446SJiří Techet if (isType (s->context, TOKEN_NAME) &&
8392683f446SJiří Techet vStringLength (s->context->name) > 0)
8402683f446SJiří Techet {
8412683f446SJiří Techet vStringCat (string, s->context->name);
8422683f446SJiří Techet }
8432683f446SJiří Techet vStringCat (string, s->blockName->name);
8442683f446SJiří Techet vStringCat (string, temp);
8452683f446SJiří Techet }
8462683f446SJiří Techet else
8472683f446SJiří Techet {
8482683f446SJiří Techet /* Information for building scope string
8492683f446SJiří Techet is lacking. Maybe input is broken. */
8502683f446SJiří Techet found = false;
8512683f446SJiří Techet }
8522683f446SJiří Techet }
8532683f446SJiří Techet }
8542683f446SJiří Techet vStringDelete (temp);
8552683f446SJiří Techet }
8562683f446SJiří Techet return found;
8572683f446SJiří Techet }
8582683f446SJiří Techet
makeExtraTagEntry(const tagType type,tagEntryInfo * const e,vString * const scope)8592683f446SJiří Techet static void makeExtraTagEntry (const tagType type, tagEntryInfo *const e,
8602683f446SJiří Techet vString *const scope)
8612683f446SJiří Techet {
8622683f446SJiří Techet if (isXtagEnabled(XTAG_QUALIFIED_TAGS) &&
8632683f446SJiří Techet scope != NULL && vStringLength (scope) > 0)
8642683f446SJiří Techet {
8652683f446SJiří Techet vString *const scopedName = vStringNew ();
8662683f446SJiří Techet
8672683f446SJiří Techet if (type != TAG_ENUMERATOR)
8682683f446SJiří Techet vStringCopy (scopedName, scope);
8692683f446SJiří Techet else
8702683f446SJiří Techet {
8712683f446SJiří Techet /* remove last component (i.e. enumeration name) from scope */
8722683f446SJiří Techet const char* const sc = vStringValue (scope);
8732683f446SJiří Techet const char* colon = strrchr (sc, ':');
8742683f446SJiří Techet if (colon != NULL)
8752683f446SJiří Techet {
8762683f446SJiří Techet while (*colon == ':' && colon > sc)
8772683f446SJiří Techet --colon;
8782683f446SJiří Techet vStringNCopy (scopedName, scope, colon + 1 - sc);
8792683f446SJiří Techet }
8802683f446SJiří Techet }
8812683f446SJiří Techet if (vStringLength (scopedName) > 0)
8822683f446SJiří Techet {
8832683f446SJiří Techet vStringCatS (scopedName, e->name);
8842683f446SJiří Techet e->name = vStringValue (scopedName);
8852683f446SJiří Techet markTagExtraBit (e, XTAG_QUALIFIED_TAGS);
8862683f446SJiří Techet makeTagEntry (e);
8872683f446SJiří Techet }
8882683f446SJiří Techet vStringDelete (scopedName);
8892683f446SJiří Techet }
8902683f446SJiří Techet }
8912683f446SJiří Techet
makeTag(const tokenInfo * const token,const statementInfo * const st,bool isFileScope,const tagType type)8922683f446SJiří Techet static int makeTag (const tokenInfo *const token,
8932683f446SJiří Techet const statementInfo *const st,
8942683f446SJiří Techet bool isFileScope, const tagType type)
8952683f446SJiří Techet {
8962683f446SJiří Techet int corkIndex = CORK_NIL;
8972683f446SJiří Techet /* Nothing is really of file scope when it appears in a header file.
8982683f446SJiří Techet */
8992683f446SJiří Techet isFileScope = (bool) (isFileScope && ! isInputHeaderFile ());
9002683f446SJiří Techet
9012683f446SJiří Techet if (isType (token, TOKEN_NAME) && vStringLength (token->name) > 0 &&
9022683f446SJiří Techet includeTag (type, isFileScope))
9032683f446SJiří Techet {
9042683f446SJiří Techet vString *scope;
9052683f446SJiří Techet vString *typeRef;
9062683f446SJiří Techet bool isScopeBuilt;
9072683f446SJiří Techet /* Use "typeRef" to store the typename from addOtherFields() until
9082683f446SJiří Techet * it's used in makeTagEntry().
9092683f446SJiří Techet */
9102683f446SJiří Techet tagEntryInfo e;
9112683f446SJiří Techet int kind;
9122683f446SJiří Techet
9132683f446SJiří Techet scope = vStringNew ();
9142683f446SJiří Techet typeRef = vStringNew ();
9152683f446SJiří Techet
9162683f446SJiří Techet kind = kindIndexForType(type);
9172683f446SJiří Techet initTagEntry (&e, vStringValue (token->name), kind);
9182683f446SJiří Techet
9192683f446SJiří Techet e.lineNumber = token->lineNumber;
9202683f446SJiří Techet e.filePosition = token->filePosition;
9212683f446SJiří Techet e.isFileScope = isFileScope;
9222683f446SJiří Techet if (e.isFileScope)
9232683f446SJiří Techet markTagExtraBit (&e, XTAG_FILE_SCOPE);
9242683f446SJiří Techet
9252683f446SJiří Techet isScopeBuilt = findScopeHierarchy (scope, st);
9262683f446SJiří Techet addOtherFields (&e, type, st, scope, typeRef);
9272683f446SJiří Techet
9282683f446SJiří Techet corkIndex = makeTagEntry (&e);
9292683f446SJiří Techet if (isScopeBuilt)
9302683f446SJiří Techet makeExtraTagEntry (type, &e, scope);
9312683f446SJiří Techet vStringDelete (scope);
9322683f446SJiří Techet vStringDelete (typeRef);
9332683f446SJiří Techet }
9342683f446SJiří Techet return corkIndex;
9352683f446SJiří Techet }
9362683f446SJiří Techet
isValidTypeSpecifier(const declType declaration)9372683f446SJiří Techet static bool isValidTypeSpecifier (const declType declaration)
9382683f446SJiří Techet {
9392683f446SJiří Techet bool result;
9402683f446SJiří Techet switch (declaration)
9412683f446SJiří Techet {
9422683f446SJiří Techet case DECL_BASE:
9432683f446SJiří Techet case DECL_CLASS:
9442683f446SJiří Techet case DECL_ENUM:
9452683f446SJiří Techet case DECL_EVENT:
9462683f446SJiří Techet result = true;
9472683f446SJiří Techet break;
9482683f446SJiří Techet
9492683f446SJiří Techet default:
9502683f446SJiří Techet result = false;
9512683f446SJiří Techet break;
9522683f446SJiří Techet }
9532683f446SJiří Techet return result;
9542683f446SJiří Techet }
9552683f446SJiří Techet
qualifyEnumeratorTag(const statementInfo * const st,const tokenInfo * const nameToken)9562683f446SJiří Techet static int qualifyEnumeratorTag (const statementInfo *const st,
9572683f446SJiří Techet const tokenInfo *const nameToken)
9582683f446SJiří Techet {
9592683f446SJiří Techet int corkIndex = CORK_NIL;
9602683f446SJiří Techet if (isType (nameToken, TOKEN_NAME))
9612683f446SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_ENUMERATOR);
9622683f446SJiří Techet return corkIndex;
9632683f446SJiří Techet }
9642683f446SJiří Techet
qualifyFunctionTag(const statementInfo * const st,const tokenInfo * const nameToken)9652683f446SJiří Techet static int qualifyFunctionTag (const statementInfo *const st,
9662683f446SJiří Techet const tokenInfo *const nameToken)
9672683f446SJiří Techet {
9682683f446SJiří Techet int corkIndex = CORK_NIL;
9692683f446SJiří Techet if (isType (nameToken, TOKEN_NAME))
9702683f446SJiří Techet {
9712683f446SJiří Techet tagType type;
9722683f446SJiří Techet const bool isFileScope =
9732683f446SJiří Techet (bool) (st->member.access == ACCESS_PRIVATE ||
9742683f446SJiří Techet (!isMember (st) && st->scope == SCOPE_STATIC));
97523c6e73eSJiří Techet if (st->declaration == DECL_TASK)
9762683f446SJiří Techet type = TAG_TASK;
9772683f446SJiří Techet else
9782683f446SJiří Techet type = TAG_FUNCTION;
9792683f446SJiří Techet corkIndex = makeTag (nameToken, st, isFileScope, type);
9802683f446SJiří Techet }
9812683f446SJiří Techet return corkIndex;
9822683f446SJiří Techet }
9832683f446SJiří Techet
qualifyFunctionDeclTag(const statementInfo * const st,const tokenInfo * const nameToken)9842683f446SJiří Techet static int qualifyFunctionDeclTag (const statementInfo *const st,
9852683f446SJiří Techet const tokenInfo *const nameToken)
9862683f446SJiří Techet {
9872683f446SJiří Techet int corkIndex = CORK_NIL;
9882683f446SJiří Techet if (! isType (nameToken, TOKEN_NAME))
9892683f446SJiří Techet ;
9902683f446SJiří Techet else if (st->scope == SCOPE_TYPEDEF)
9912683f446SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_TYPEDEF);
99223c6e73eSJiří Techet else if (isValidTypeSpecifier (st->declaration))
9932683f446SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_PROTOTYPE);
9942683f446SJiří Techet return corkIndex;
9952683f446SJiří Techet }
9962683f446SJiří Techet
qualifyCompoundTag(const statementInfo * const st,const tokenInfo * const nameToken)9972683f446SJiří Techet static int qualifyCompoundTag (const statementInfo *const st,
9982683f446SJiří Techet const tokenInfo *const nameToken)
9992683f446SJiří Techet {
10002683f446SJiří Techet int corkIndex = CORK_NIL;
10012683f446SJiří Techet if (isType (nameToken, TOKEN_NAME))
10022683f446SJiří Techet {
10032683f446SJiří Techet const tagType type = declToTagType (st->declaration);
10042683f446SJiří Techet
10052683f446SJiří Techet if (type != TAG_UNDEFINED)
100623c6e73eSJiří Techet corkIndex = makeTag (nameToken, st, false, type);
10072683f446SJiří Techet }
10082683f446SJiří Techet return corkIndex;
10092683f446SJiří Techet }
10102683f446SJiří Techet
qualifyBlockTag(statementInfo * const st,const tokenInfo * const nameToken)10112683f446SJiří Techet static int qualifyBlockTag (statementInfo *const st,
10122683f446SJiří Techet const tokenInfo *const nameToken)
10132683f446SJiří Techet {
10142683f446SJiří Techet int corkIndex = CORK_NIL;
10152683f446SJiří Techet switch (st->declaration)
10162683f446SJiří Techet {
10172683f446SJiří Techet
10182683f446SJiří Techet case DECL_CLASS:
10192683f446SJiří Techet case DECL_ENUM:
10202683f446SJiří Techet case DECL_INTERFACE:
10212683f446SJiří Techet case DECL_PROGRAM:
10222683f446SJiří Techet corkIndex = qualifyCompoundTag (st, nameToken);
10232683f446SJiří Techet break;
10242683f446SJiří Techet default: break;
10252683f446SJiří Techet }
10262683f446SJiří Techet return corkIndex;
10272683f446SJiří Techet }
10282683f446SJiří Techet
qualifyVariableTag(const statementInfo * const st,const tokenInfo * const nameToken)10292683f446SJiří Techet static int qualifyVariableTag (const statementInfo *const st,
10302683f446SJiří Techet const tokenInfo *const nameToken)
10312683f446SJiří Techet {
10322683f446SJiří Techet int corkIndex = CORK_NIL;
10332683f446SJiří Techet /* We have to watch that we do not interpret a declaration of the
10342683f446SJiří Techet * form "struct tag;" as a variable definition. In such a case, the
10352683f446SJiří Techet * token preceding the name will be a keyword.
10362683f446SJiří Techet */
10372683f446SJiří Techet if (! isType (nameToken, TOKEN_NAME))
10382683f446SJiří Techet ;
10392683f446SJiří Techet else if (st->scope == SCOPE_TYPEDEF)
10402683f446SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_TYPEDEF);
10412683f446SJiří Techet else if (st->declaration == DECL_EVENT)
10422683f446SJiří Techet corkIndex = makeTag (nameToken, st, (bool) (st->member.access == ACCESS_PRIVATE),
10432683f446SJiří Techet TAG_EVENT);
10442683f446SJiří Techet else if (isValidTypeSpecifier (st->declaration))
10452683f446SJiří Techet {
10462683f446SJiří Techet if (st->notVariable)
10472683f446SJiří Techet ;
10482683f446SJiří Techet else if (isMember (st))
10492683f446SJiří Techet {
105023c6e73eSJiří Techet if (st->scope == SCOPE_GLOBAL || st->scope == SCOPE_STATIC)
10512683f446SJiří Techet corkIndex = makeTag (nameToken, st, true, TAG_MEMBER);
10522683f446SJiří Techet }
10532683f446SJiří Techet else
10542683f446SJiří Techet {
10552683f446SJiří Techet if (st->scope == SCOPE_EXTERN || ! st->haveQualifyingName)
10562683f446SJiří Techet corkIndex = makeTag (nameToken, st, false, TAG_EXTERN_VAR);
10572683f446SJiří Techet else if (st->inFunction)
10582683f446SJiří Techet corkIndex = makeTag (nameToken, st, (bool) (st->scope == SCOPE_STATIC),
10592683f446SJiří Techet TAG_LOCAL);
10602683f446SJiří Techet else
10612683f446SJiří Techet corkIndex = makeTag (nameToken, st, (bool) (st->scope == SCOPE_STATIC),
10622683f446SJiří Techet TAG_VARIABLE);
10632683f446SJiří Techet }
10642683f446SJiří Techet }
10652683f446SJiří Techet return corkIndex;
10662683f446SJiří Techet }
10672683f446SJiří Techet
10682683f446SJiří Techet /*
10692683f446SJiří Techet * Parsing functions
10702683f446SJiří Techet */
10712683f446SJiří Techet
10722683f446SJiří Techet
10732683f446SJiří Techet /* Skip to the next non-white character.
10742683f446SJiří Techet */
skipToNonWhite(void)10752683f446SJiří Techet static int skipToNonWhite (void)
10762683f446SJiří Techet {
10772683f446SJiří Techet bool found = false;
10782683f446SJiří Techet int c;
10792683f446SJiří Techet
10802683f446SJiří Techet #if 0
10812683f446SJiří Techet do
10822683f446SJiří Techet c = cppGetc ();
10832683f446SJiří Techet while (cppIsspace (c));
10842683f446SJiří Techet #else
10852683f446SJiří Techet while (1)
10862683f446SJiří Techet {
10872683f446SJiří Techet c = cppGetc ();
10882683f446SJiří Techet if (cppIsspace (c))
10892683f446SJiří Techet found = true;
10902683f446SJiří Techet else
10912683f446SJiří Techet break;
10922683f446SJiří Techet }
10932683f446SJiří Techet if (CollectingSignature && found)
10942683f446SJiří Techet vStringPut (Signature, ' ');
10952683f446SJiří Techet #endif
10962683f446SJiří Techet
10972683f446SJiří Techet return c;
10982683f446SJiří Techet }
10992683f446SJiří Techet
11002683f446SJiří Techet /* Skips to the next brace in column 1. This is intended for cases where
11012683f446SJiří Techet * preprocessor constructs result in unbalanced braces.
11022683f446SJiří Techet */
skipToFormattedBraceMatch(void)11032683f446SJiří Techet static void skipToFormattedBraceMatch (void)
11042683f446SJiří Techet {
11052683f446SJiří Techet int c, next;
11062683f446SJiří Techet
11072683f446SJiří Techet c = cppGetc ();
11082683f446SJiří Techet next = cppGetc ();
11092683f446SJiří Techet while (c != EOF && (c != '\n' || next != '}'))
11102683f446SJiří Techet {
11112683f446SJiří Techet c = next;
11122683f446SJiří Techet next = cppGetc ();
11132683f446SJiří Techet }
11142683f446SJiří Techet }
11152683f446SJiří Techet
11162683f446SJiří Techet /* Skip to the matching character indicated by the pair string. If skipping
11172683f446SJiří Techet * to a matching brace and any brace is found within a different level of a
11182683f446SJiří Techet * #if conditional statement while brace formatting is in effect, we skip to
11192683f446SJiří Techet * the brace matched by its formatting. It is assumed that we have already
11202683f446SJiří Techet * read the character which starts the group (i.e. the first character of
11212683f446SJiří Techet * "pair").
11222683f446SJiří Techet */
skipToMatch(const char * const pair)11232683f446SJiří Techet static void skipToMatch (const char *const pair)
11242683f446SJiří Techet {
11252683f446SJiří Techet const bool braceMatching = (bool) (strcmp ("{}", pair) == 0);
11262683f446SJiří Techet const bool braceFormatting = (bool) (cppIsBraceFormat () && braceMatching);
11272683f446SJiří Techet const unsigned int initialLevel = cppGetDirectiveNestLevel ();
11282683f446SJiří Techet const int begin = pair [0], end = pair [1];
11292683f446SJiří Techet const unsigned long inputLineNumber = getInputLineNumber ();
11302683f446SJiří Techet int matchLevel = 1;
11312683f446SJiří Techet int c = '\0';
11322683f446SJiří Techet
11332683f446SJiří Techet while (matchLevel > 0 && (c = skipToNonWhite ()) != EOF)
11342683f446SJiří Techet {
11352683f446SJiří Techet if (CollectingSignature)
11362683f446SJiří Techet vStringPut (Signature, c);
11372683f446SJiří Techet if (c == begin)
11382683f446SJiří Techet {
11392683f446SJiří Techet ++matchLevel;
11402683f446SJiří Techet if (braceFormatting && cppGetDirectiveNestLevel () != initialLevel)
11412683f446SJiří Techet {
11422683f446SJiří Techet skipToFormattedBraceMatch ();
11432683f446SJiří Techet break;
11442683f446SJiří Techet }
11452683f446SJiří Techet }
11462683f446SJiří Techet else if (c == end)
11472683f446SJiří Techet {
11482683f446SJiří Techet --matchLevel;
11492683f446SJiří Techet if (braceFormatting && cppGetDirectiveNestLevel () != initialLevel)
11502683f446SJiří Techet {
11512683f446SJiří Techet skipToFormattedBraceMatch ();
11522683f446SJiří Techet break;
11532683f446SJiří Techet }
11542683f446SJiří Techet }
11552683f446SJiří Techet }
11562683f446SJiří Techet if (c == EOF)
11572683f446SJiří Techet {
11582683f446SJiří Techet verbose ("%s: failed to find match for '%c' at line %lu\n",
11592683f446SJiří Techet getInputFileName (), begin, inputLineNumber);
11602683f446SJiří Techet if (braceMatching)
11612683f446SJiří Techet longjmp (Exception, (int) ExceptionBraceFormattingError);
11622683f446SJiří Techet else
11632683f446SJiří Techet longjmp (Exception, (int) ExceptionFormattingError);
11642683f446SJiří Techet }
11652683f446SJiří Techet }
11662683f446SJiří Techet
analyzeKeyword(const char * const name)11672683f446SJiří Techet static keywordId analyzeKeyword (const char *const name)
11682683f446SJiří Techet {
11692683f446SJiří Techet const keywordId id = (keywordId) lookupKeyword (name, getInputLanguage ());
11702683f446SJiří Techet return id;
11712683f446SJiří Techet }
11722683f446SJiří Techet
analyzeIdentifier(tokenInfo * const token)11732683f446SJiří Techet static void analyzeIdentifier (tokenInfo *const token)
11742683f446SJiří Techet {
11752683f446SJiří Techet const char * name = vStringValue (token->name);
11762683f446SJiří Techet
11772683f446SJiří Techet vString * replacement = NULL;
11782683f446SJiří Techet
11792683f446SJiří Techet // C: check for ignored token
11802683f446SJiří Techet // (FIXME: java doesn't support -I... but maybe it should?)
11812683f446SJiří Techet const cppMacroInfo * macro = cppFindMacro(name);
11822683f446SJiří Techet
11832683f446SJiří Techet if(macro)
11842683f446SJiří Techet {
11852683f446SJiří Techet if(macro->hasParameterList)
11862683f446SJiří Techet {
11872683f446SJiří Techet // This old parser does not support macro parameters: we simply assume them to be empty
11882683f446SJiří Techet int c = skipToNonWhite ();
11892683f446SJiří Techet
11902683f446SJiří Techet if (c == '(')
11912683f446SJiří Techet skipToMatch ("()");
11922683f446SJiří Techet }
11932683f446SJiří Techet
11942683f446SJiří Techet if(macro->replacements)
11952683f446SJiří Techet {
11962683f446SJiří Techet // There is a replacement: analyze it
11972683f446SJiří Techet replacement = cppBuildMacroReplacement(macro,NULL,0);
11982683f446SJiří Techet name = replacement ? vStringValue(replacement) : NULL;
11992683f446SJiří Techet } else {
12002683f446SJiří Techet // There is no replacement: just ignore
12012683f446SJiří Techet name = NULL;
12022683f446SJiří Techet }
12032683f446SJiří Techet }
12042683f446SJiří Techet
12052683f446SJiří Techet if(!name)
12062683f446SJiří Techet {
12072683f446SJiří Techet initToken(token);
12082683f446SJiří Techet if(replacement)
12092683f446SJiří Techet vStringDelete(replacement);
12102683f446SJiří Techet return;
12112683f446SJiří Techet }
12122683f446SJiří Techet
12132683f446SJiří Techet token->keyword = analyzeKeyword (name);
12142683f446SJiří Techet
12152683f446SJiří Techet if (token->keyword == KEYWORD_NONE)
12162683f446SJiří Techet token->type = TOKEN_NAME;
12172683f446SJiří Techet else
12182683f446SJiří Techet token->type = TOKEN_KEYWORD;
12192683f446SJiří Techet
12202683f446SJiří Techet if(replacement)
12212683f446SJiří Techet vStringDelete(replacement);
12222683f446SJiří Techet }
12232683f446SJiří Techet
readIdentifier(tokenInfo * const token,const int firstChar)12242683f446SJiří Techet static void readIdentifier (tokenInfo *const token, const int firstChar)
12252683f446SJiří Techet {
12262683f446SJiří Techet vString *const name = token->name;
12272683f446SJiří Techet int c = firstChar;
12282683f446SJiří Techet bool first = true;
12292683f446SJiří Techet
12302683f446SJiří Techet initToken (token);
12312683f446SJiří Techet
12322683f446SJiří Techet do
12332683f446SJiří Techet {
12342683f446SJiří Techet vStringPut (name, c);
12352683f446SJiří Techet if (CollectingSignature)
12362683f446SJiří Techet {
12372683f446SJiří Techet if (!first)
12382683f446SJiří Techet vStringPut (Signature, c);
12392683f446SJiří Techet first = false;
12402683f446SJiří Techet }
12412683f446SJiří Techet c = cppGetc ();
124223c6e73eSJiří Techet } while (cppIsident (c));
12432683f446SJiří Techet cppUngetc (c); /* unget non-identifier character */
12442683f446SJiří Techet
12452683f446SJiří Techet analyzeIdentifier (token);
12462683f446SJiří Techet }
12472683f446SJiří Techet
processName(statementInfo * const st)12482683f446SJiří Techet static void processName (statementInfo *const st)
12492683f446SJiří Techet {
12502683f446SJiří Techet Assert (isType (activeToken (st), TOKEN_NAME));
12512683f446SJiří Techet if (st->gotName && st->declaration == DECL_NONE)
12522683f446SJiří Techet st->declaration = DECL_BASE;
12532683f446SJiří Techet st->gotName = true;
12542683f446SJiří Techet st->haveQualifyingName = true;
12552683f446SJiří Techet }
12562683f446SJiří Techet
copyToken(tokenInfo * const dest,const tokenInfo * const src)12572683f446SJiří Techet static void copyToken (tokenInfo *const dest, const tokenInfo *const src)
12582683f446SJiří Techet {
12592683f446SJiří Techet dest->type = src->type;
12602683f446SJiří Techet dest->keyword = src->keyword;
12612683f446SJiří Techet dest->filePosition = src->filePosition;
12622683f446SJiří Techet dest->lineNumber = src->lineNumber;
12632683f446SJiří Techet vStringCopy (dest->name, src->name);
12642683f446SJiří Techet }
12652683f446SJiří Techet
setAccess(statementInfo * const st,const accessType access)12662683f446SJiří Techet static void setAccess (statementInfo *const st, const accessType access)
12672683f446SJiří Techet {
12682683f446SJiří Techet if (isMember (st))
12692683f446SJiří Techet {
12702683f446SJiří Techet st->member.access = access;
12712683f446SJiří Techet }
12722683f446SJiří Techet }
12732683f446SJiří Techet
addParentClass(statementInfo * const st,tokenInfo * const token)12742683f446SJiří Techet static void addParentClass (statementInfo *const st, tokenInfo *const token)
12752683f446SJiří Techet {
12762683f446SJiří Techet if (vStringLength (token->name) > 0 &&
12772683f446SJiří Techet vStringLength (st->parentClasses) > 0)
12782683f446SJiří Techet {
12792683f446SJiří Techet vStringPut (st->parentClasses, ',');
12802683f446SJiří Techet }
12812683f446SJiří Techet vStringCat (st->parentClasses, token->name);
12822683f446SJiří Techet }
12832683f446SJiří Techet
readParents(statementInfo * const st,const int qualifier)12842683f446SJiří Techet static void readParents (statementInfo *const st, const int qualifier)
12852683f446SJiří Techet {
12862683f446SJiří Techet tokenInfo *const token = newToken ();
12872683f446SJiří Techet tokenInfo *const parent = newToken ();
12882683f446SJiří Techet int c;
12892683f446SJiří Techet
12902683f446SJiří Techet do
12912683f446SJiří Techet {
12922683f446SJiří Techet c = skipToNonWhite ();
12932683f446SJiří Techet if (cppIsident1 (c))
12942683f446SJiří Techet {
12952683f446SJiří Techet readIdentifier (token, c);
12962683f446SJiří Techet if (isType (token, TOKEN_NAME))
12972683f446SJiří Techet vStringCat (parent->name, token->name);
12982683f446SJiří Techet else
12992683f446SJiří Techet {
13002683f446SJiří Techet addParentClass (st, parent);
13012683f446SJiří Techet initToken (parent);
13022683f446SJiří Techet }
13032683f446SJiří Techet }
13042683f446SJiří Techet else if (c == qualifier)
13052683f446SJiří Techet vStringPut (parent->name, c);
13062683f446SJiří Techet else if (c == '<')
13072683f446SJiří Techet skipToMatch ("<>");
13082683f446SJiří Techet else if (isType (token, TOKEN_NAME))
13092683f446SJiří Techet {
13102683f446SJiří Techet addParentClass (st, parent);
13112683f446SJiří Techet initToken (parent);
13122683f446SJiří Techet }
13132683f446SJiří Techet } while (c != '{' && c != EOF);
13142683f446SJiří Techet cppUngetc (c);
13152683f446SJiří Techet deleteToken (parent);
13162683f446SJiří Techet deleteToken (token);
13172683f446SJiří Techet }
13182683f446SJiří Techet
processInterface(statementInfo * const st)13192683f446SJiří Techet static void processInterface (statementInfo *const st)
13202683f446SJiří Techet {
13212683f446SJiří Techet st->declaration = DECL_INTERFACE;
13222683f446SJiří Techet }
13232683f446SJiří Techet
checkIsClassEnum(statementInfo * const st,const declType decl)13242683f446SJiří Techet static void checkIsClassEnum (statementInfo *const st, const declType decl)
13252683f446SJiří Techet {
13262683f446SJiří Techet st->declaration = decl;
13272683f446SJiří Techet }
13282683f446SJiří Techet
processToken(tokenInfo * const token,statementInfo * const st)13292683f446SJiří Techet static void processToken (tokenInfo *const token, statementInfo *const st)
13302683f446SJiří Techet {
13312683f446SJiří Techet switch ((int)token->keyword) /* is it a reserved word? */
13322683f446SJiří Techet {
13332683f446SJiří Techet default: break;
13342683f446SJiří Techet
13352683f446SJiří Techet case KEYWORD_NONE: processName (st); break;
13362683f446SJiří Techet case KEYWORD_BIND: st->declaration = DECL_BASE; break;
13372683f446SJiří Techet case KEYWORD_BIT: st->declaration = DECL_BASE; break;
13382683f446SJiří Techet case KEYWORD_CLASS: checkIsClassEnum (st, DECL_CLASS); break;
13392683f446SJiří Techet case KEYWORD_ENUM: st->declaration = DECL_ENUM; break;
13402683f446SJiří Techet case KEYWORD_EXTENDS: readParents (st, '.');
13412683f446SJiří Techet setToken (st, TOKEN_NONE); break;
13422683f446SJiří Techet case KEYWORD_FUNCTION: st->declaration = DECL_BASE; break;
13432683f446SJiří Techet case KEYWORD_INTEGER: st->declaration = DECL_BASE; break;
13442683f446SJiří Techet case KEYWORD_INTERFACE: processInterface (st); break;
13452683f446SJiří Techet case KEYWORD_LOCAL: setAccess (st, ACCESS_LOCAL); break;
13462683f446SJiří Techet case KEYWORD_PROGRAM: st->declaration = DECL_PROGRAM; break;
13472683f446SJiří Techet case KEYWORD_PROTECTED: setAccess (st, ACCESS_PROTECTED); break;
13482683f446SJiří Techet case KEYWORD_PUBLIC: setAccess (st, ACCESS_PUBLIC); break;
13492683f446SJiří Techet case KEYWORD_STRING: st->declaration = DECL_BASE; break;
13502683f446SJiří Techet case KEYWORD_TASK: st->declaration = DECL_TASK; break;
13512683f446SJiří Techet case KEYWORD_VOID: st->declaration = DECL_BASE; break;
13522683f446SJiří Techet case KEYWORD_VIRTUAL: st->implementation = IMP_VIRTUAL; break;
13532683f446SJiří Techet
13542683f446SJiří Techet case KEYWORD_EVENT:
13552683f446SJiří Techet break;
13562683f446SJiří Techet
13572683f446SJiří Techet case KEYWORD_TYPEDEF:
13582683f446SJiří Techet reinitStatement (st, false);
13592683f446SJiří Techet st->scope = SCOPE_TYPEDEF;
13602683f446SJiří Techet break;
13612683f446SJiří Techet
13622683f446SJiří Techet case KEYWORD_EXTERN:
13632683f446SJiří Techet reinitStatement (st, false);
13642683f446SJiří Techet st->scope = SCOPE_EXTERN;
13652683f446SJiří Techet st->declaration = DECL_BASE;
13662683f446SJiří Techet break;
13672683f446SJiří Techet
13682683f446SJiří Techet case KEYWORD_STATIC:
13692683f446SJiří Techet reinitStatement (st, false);
13702683f446SJiří Techet st->scope = SCOPE_STATIC;
13712683f446SJiří Techet st->declaration = DECL_BASE;
13722683f446SJiří Techet break;
13732683f446SJiří Techet }
13742683f446SJiří Techet }
13752683f446SJiří Techet
13762683f446SJiří Techet /*
13772683f446SJiří Techet * Parenthesis handling functions
13782683f446SJiří Techet */
13792683f446SJiří Techet
restartStatement(statementInfo * const st)13802683f446SJiří Techet static void restartStatement (statementInfo *const st)
13812683f446SJiří Techet {
13822683f446SJiří Techet tokenInfo *const save = newToken ();
13832683f446SJiří Techet tokenInfo *token = activeToken (st);
13842683f446SJiří Techet
13852683f446SJiří Techet copyToken (save, token);
13862683f446SJiří Techet DebugStatement ( if (debug (DEBUG_PARSE)) printf ("<ES>");)
13872683f446SJiří Techet reinitStatement (st, false);
13882683f446SJiří Techet token = activeToken (st);
13892683f446SJiří Techet copyToken (token, save);
13902683f446SJiří Techet deleteToken (save);
13912683f446SJiří Techet processToken (token, st);
13922683f446SJiří Techet }
13932683f446SJiří Techet
13942683f446SJiří Techet /* Skips over a mem-initializer-list of a ctor-initializer, defined as:
13952683f446SJiří Techet *
13962683f446SJiří Techet * mem-initializer-list:
13972683f446SJiří Techet * mem-initializer, mem-initializer-list
13982683f446SJiří Techet *
13992683f446SJiří Techet * mem-initializer:
14002683f446SJiří Techet * [::] [nested-name-spec] class-name (...)
14012683f446SJiří Techet * identifier
14022683f446SJiří Techet */
skipMemIntializerList(tokenInfo * const token)14032683f446SJiří Techet static void skipMemIntializerList (tokenInfo *const token)
14042683f446SJiří Techet {
14052683f446SJiří Techet int c;
14062683f446SJiří Techet
14072683f446SJiří Techet do
14082683f446SJiří Techet {
14092683f446SJiří Techet c = skipToNonWhite ();
14102683f446SJiří Techet while (cppIsident1 (c) || c == ':')
14112683f446SJiří Techet {
14122683f446SJiří Techet if (c != ':')
14132683f446SJiří Techet readIdentifier (token, c);
14142683f446SJiří Techet c = skipToNonWhite ();
14152683f446SJiří Techet }
14162683f446SJiří Techet if (c == '<')
14172683f446SJiří Techet {
14182683f446SJiří Techet skipToMatch ("<>");
14192683f446SJiří Techet c = skipToNonWhite ();
14202683f446SJiří Techet }
14212683f446SJiří Techet if (c == '(')
14222683f446SJiří Techet {
14232683f446SJiří Techet skipToMatch ("()");
14242683f446SJiří Techet c = skipToNonWhite ();
14252683f446SJiří Techet }
14262683f446SJiří Techet } while (c == ',');
14272683f446SJiří Techet cppUngetc (c);
14282683f446SJiří Techet }
14292683f446SJiří Techet
skipMacro(statementInfo * const st)14302683f446SJiří Techet static void skipMacro (statementInfo *const st)
14312683f446SJiří Techet {
14322683f446SJiří Techet tokenInfo *const prev2 = prevToken (st, 2);
14332683f446SJiří Techet
14342683f446SJiří Techet if (isType (prev2, TOKEN_NAME))
14352683f446SJiří Techet retardToken (st);
14362683f446SJiří Techet skipToMatch ("()");
14372683f446SJiří Techet }
14382683f446SJiří Techet
14392683f446SJiří Techet /* Skips over characters following the parameter list.
14402683f446SJiří Techet * Originally written for C++, may contain unnecessary stuff.
14412683f446SJiří Techet *
14422683f446SJiří Techet * C#:
14432683f446SJiří Techet * public C(double x) : base(x) {}
14442683f446SJiří Techet */
skipPostArgumentStuff(statementInfo * const st,parenInfo * const info)14452683f446SJiří Techet static bool skipPostArgumentStuff (
14462683f446SJiří Techet statementInfo *const st, parenInfo *const info)
14472683f446SJiří Techet {
14482683f446SJiří Techet tokenInfo *const token = activeToken (st);
14492683f446SJiří Techet unsigned int parameters = info->parameterCount;
14502683f446SJiří Techet unsigned int elementCount = 0;
14512683f446SJiří Techet bool restart = false;
14522683f446SJiří Techet bool end = false;
14532683f446SJiří Techet int c = skipToNonWhite ();
14542683f446SJiří Techet
14552683f446SJiří Techet do
14562683f446SJiří Techet {
14572683f446SJiří Techet switch (c)
14582683f446SJiří Techet {
14592683f446SJiří Techet case ')': break;
14602683f446SJiří Techet case ':': skipMemIntializerList (token);break; /* ctor-initializer */
14612683f446SJiří Techet case '[': skipToMatch ("[]"); break;
14622683f446SJiří Techet case '=': cppUngetc (c); end = true; break;
14632683f446SJiří Techet case '{': cppUngetc (c); end = true; break;
14642683f446SJiří Techet case '}': cppUngetc (c); end = true; break;
14652683f446SJiří Techet
14662683f446SJiří Techet case '(':
14672683f446SJiří Techet if (elementCount > 0)
14682683f446SJiří Techet ++elementCount;
14692683f446SJiří Techet skipToMatch ("()");
14702683f446SJiří Techet break;
14712683f446SJiří Techet
14722683f446SJiří Techet case ';':
14732683f446SJiří Techet if (parameters == 0 || elementCount < 2)
14742683f446SJiří Techet {
14752683f446SJiří Techet cppUngetc (c);
14762683f446SJiří Techet end = true;
14772683f446SJiří Techet }
14782683f446SJiří Techet else if (--parameters == 0)
14792683f446SJiří Techet end = true;
14802683f446SJiří Techet break;
14812683f446SJiří Techet
14822683f446SJiří Techet default:
14832683f446SJiří Techet if (cppIsident1 (c))
14842683f446SJiří Techet {
14852683f446SJiří Techet readIdentifier (token, c);
14862683f446SJiří Techet switch (token->keyword)
14872683f446SJiří Techet {
14882683f446SJiří Techet case KEYWORD_CLASS:
14892683f446SJiří Techet case KEYWORD_EXTERN:
14902683f446SJiří Techet case KEYWORD_NEWCOV:
14912683f446SJiří Techet case KEYWORD_PROTECTED:
14922683f446SJiří Techet case KEYWORD_PUBLIC:
14932683f446SJiří Techet case KEYWORD_STATIC:
14942683f446SJiří Techet case KEYWORD_TYPEDEF:
14952683f446SJiří Techet case KEYWORD_VIRTUAL:
14962683f446SJiří Techet /* Never allowed within parameter declarations. */
14972683f446SJiří Techet restart = true;
14982683f446SJiří Techet end = true;
14992683f446SJiří Techet break;
15002683f446SJiří Techet
15012683f446SJiří Techet default:
15022683f446SJiří Techet if (isType (token, TOKEN_NONE))
15032683f446SJiří Techet ;
15042683f446SJiří Techet else
15052683f446SJiří Techet {
15062683f446SJiří Techet /* If we encounter any other identifier immediately
15072683f446SJiří Techet * following an empty parameter list, this is almost
15082683f446SJiří Techet * certainly one of those Microsoft macro "thingies"
15092683f446SJiří Techet * that the automatic source code generation sticks
15102683f446SJiří Techet * in. Terminate the current statement.
15112683f446SJiří Techet */
15122683f446SJiří Techet restart = true;
15132683f446SJiří Techet end = true;
15142683f446SJiří Techet }
15152683f446SJiří Techet break;
15162683f446SJiří Techet }
15172683f446SJiří Techet }
15182683f446SJiří Techet }
15192683f446SJiří Techet if (! end)
15202683f446SJiří Techet {
15212683f446SJiří Techet c = skipToNonWhite ();
15222683f446SJiří Techet if (c == EOF)
15232683f446SJiří Techet end = true;
15242683f446SJiří Techet }
15252683f446SJiří Techet } while (! end);
15262683f446SJiří Techet
15272683f446SJiří Techet if (restart)
15282683f446SJiří Techet restartStatement (st);
15292683f446SJiří Techet else
15302683f446SJiří Techet setToken (st, TOKEN_NONE);
15312683f446SJiří Techet
15322683f446SJiří Techet return (bool) (c != EOF);
15332683f446SJiří Techet }
15342683f446SJiří Techet
analyzePostParens(statementInfo * const st,parenInfo * const info)15352683f446SJiří Techet static void analyzePostParens (statementInfo *const st, parenInfo *const info)
15362683f446SJiří Techet {
15372683f446SJiří Techet const unsigned long inputLineNumber = getInputLineNumber ();
15382683f446SJiří Techet int c = skipToNonWhite ();
15392683f446SJiří Techet
15402683f446SJiří Techet cppUngetc (c);
15412683f446SJiří Techet if (isOneOf (c, "{;,="))
15422683f446SJiří Techet ;
154323c6e73eSJiří Techet else {
15442683f446SJiří Techet if (! skipPostArgumentStuff (st, info))
15452683f446SJiří Techet {
15462683f446SJiří Techet verbose (
15472683f446SJiří Techet "%s: confusing argument declarations beginning at line %lu\n",
15482683f446SJiří Techet getInputFileName (), inputLineNumber);
15492683f446SJiří Techet longjmp (Exception, (int) ExceptionFormattingError);
15502683f446SJiří Techet }
15512683f446SJiří Techet }
15522683f446SJiří Techet }
15532683f446SJiří Techet
processAngleBracket(void)15542683f446SJiří Techet static void processAngleBracket (void)
15552683f446SJiří Techet {
15562683f446SJiří Techet int c = cppGetc ();
15572683f446SJiří Techet if (c == '>') {
15582683f446SJiří Techet /* already found match for template */
15592683f446SJiří Techet } else if (c == '<') {
15602683f446SJiří Techet /* skip "<<" or "<<=". */
15612683f446SJiří Techet c = cppGetc ();
15622683f446SJiří Techet if (c != '=') {
15632683f446SJiří Techet cppUngetc (c);
15642683f446SJiří Techet }
15652683f446SJiří Techet } else {
15662683f446SJiří Techet cppUngetc (c);
15672683f446SJiří Techet }
15682683f446SJiří Techet }
15692683f446SJiří Techet
parseParens(statementInfo * const st,parenInfo * const info)15702683f446SJiří Techet static int parseParens (statementInfo *const st, parenInfo *const info)
15712683f446SJiří Techet {
15722683f446SJiří Techet tokenInfo *const token = activeToken (st);
15732683f446SJiří Techet unsigned int identifierCount = 0;
15742683f446SJiří Techet unsigned int depth = 1;
15752683f446SJiří Techet bool firstChar = true;
15762683f446SJiří Techet int nextChar = '\0';
15772683f446SJiří Techet
15782683f446SJiří Techet CollectingSignature = true;
15792683f446SJiří Techet vStringClear (Signature);
15802683f446SJiří Techet vStringPut (Signature, '(');
15812683f446SJiří Techet info->parameterCount = 1;
15822683f446SJiří Techet do
15832683f446SJiří Techet {
15842683f446SJiří Techet int c = skipToNonWhite ();
15852683f446SJiří Techet vStringPut (Signature, c);
15862683f446SJiří Techet
15872683f446SJiří Techet switch (c)
15882683f446SJiří Techet {
15892683f446SJiří Techet case '^':
15902683f446SJiří Techet break;
15912683f446SJiří Techet
15922683f446SJiří Techet case '&':
15932683f446SJiří Techet case '*':
15942683f446SJiří Techet info->isPointer = true;
15952683f446SJiří Techet if (identifierCount == 0)
15962683f446SJiří Techet info->isParamList = false;
15972683f446SJiří Techet initToken (token);
15982683f446SJiří Techet break;
15992683f446SJiří Techet
16002683f446SJiří Techet case ':':
16012683f446SJiří Techet break;
16022683f446SJiří Techet
16032683f446SJiří Techet case '.':
16042683f446SJiří Techet info->isNameCandidate = false;
16052683f446SJiří Techet c = cppGetc ();
16062683f446SJiří Techet if (c != '.')
16072683f446SJiří Techet cppUngetc (c);
16082683f446SJiří Techet else
16092683f446SJiří Techet {
16102683f446SJiří Techet c = cppGetc ();
16112683f446SJiří Techet if (c != '.')
16122683f446SJiří Techet cppUngetc (c);
16132683f446SJiří Techet else
16142683f446SJiří Techet vStringCatS (Signature, "..."); /* variable arg list */
16152683f446SJiří Techet }
16162683f446SJiří Techet break;
16172683f446SJiří Techet
16182683f446SJiří Techet case ',':
16192683f446SJiří Techet info->isNameCandidate = false;
16202683f446SJiří Techet break;
16212683f446SJiří Techet
16222683f446SJiří Techet case '=':
16232683f446SJiří Techet info->isNameCandidate = false;
16242683f446SJiří Techet if (firstChar)
16252683f446SJiří Techet {
16262683f446SJiří Techet info->isParamList = false;
16272683f446SJiří Techet skipMacro (st);
16282683f446SJiří Techet depth = 0;
16292683f446SJiří Techet }
16302683f446SJiří Techet break;
16312683f446SJiří Techet
16322683f446SJiří Techet case '[':
16332683f446SJiří Techet skipToMatch ("[]");
16342683f446SJiří Techet break;
16352683f446SJiří Techet
16362683f446SJiří Techet case '<':
16372683f446SJiří Techet processAngleBracket ();
16382683f446SJiří Techet break;
16392683f446SJiří Techet
16402683f446SJiří Techet case ')':
16412683f446SJiří Techet if (firstChar)
16422683f446SJiří Techet info->parameterCount = 0;
16432683f446SJiří Techet --depth;
16442683f446SJiří Techet break;
16452683f446SJiří Techet
16462683f446SJiří Techet case '(':
16472683f446SJiří Techet if (firstChar)
16482683f446SJiří Techet {
16492683f446SJiří Techet info->isNameCandidate = false;
16502683f446SJiří Techet cppUngetc (c);
16512683f446SJiří Techet vStringClear (Signature);
16522683f446SJiří Techet skipMacro (st);
16532683f446SJiří Techet depth = 0;
16542683f446SJiří Techet vStringChop (Signature);
16552683f446SJiří Techet }
16562683f446SJiří Techet else if (isType (token, TOKEN_PAREN_NAME))
16572683f446SJiří Techet {
16582683f446SJiří Techet c = skipToNonWhite ();
16592683f446SJiří Techet if (c == '*') /* check for function pointer */
16602683f446SJiří Techet {
16612683f446SJiří Techet skipToMatch ("()");
16622683f446SJiří Techet c = skipToNonWhite ();
16632683f446SJiří Techet if (c == '(')
16642683f446SJiří Techet skipToMatch ("()");
16652683f446SJiří Techet else
16662683f446SJiří Techet cppUngetc (c);
16672683f446SJiří Techet }
16682683f446SJiří Techet else
16692683f446SJiří Techet {
16702683f446SJiří Techet cppUngetc (c);
16712683f446SJiří Techet cppUngetc ('(');
16722683f446SJiří Techet info->nestedArgs = true;
16732683f446SJiří Techet }
16742683f446SJiří Techet }
16752683f446SJiří Techet else
16762683f446SJiří Techet ++depth;
16772683f446SJiří Techet break;
16782683f446SJiří Techet
16792683f446SJiří Techet default:
168023c6e73eSJiří Techet if (cppIsident1 (c))
16812683f446SJiří Techet {
16822683f446SJiří Techet readIdentifier (token, c);
16832683f446SJiří Techet if (isType (token, TOKEN_NAME) && info->isNameCandidate)
16842683f446SJiří Techet token->type = TOKEN_PAREN_NAME;
16852683f446SJiří Techet else if (isType (token, TOKEN_KEYWORD))
16862683f446SJiří Techet {
16872683f446SJiří Techet info->isNameCandidate = false;
16882683f446SJiří Techet }
16892683f446SJiří Techet }
16902683f446SJiří Techet else
16912683f446SJiří Techet {
16922683f446SJiří Techet info->isParamList = false;
16932683f446SJiří Techet info->isNameCandidate = false;
16942683f446SJiří Techet info->invalidContents = true;
16952683f446SJiří Techet }
16962683f446SJiří Techet break;
16972683f446SJiří Techet }
16982683f446SJiří Techet firstChar = false;
16992683f446SJiří Techet } while (! info->nestedArgs && depth > 0 && info->isNameCandidate);
17002683f446SJiří Techet
17012683f446SJiří Techet if (! info->nestedArgs) while (depth > 0)
17022683f446SJiří Techet {
17032683f446SJiří Techet skipToMatch ("()");
17042683f446SJiří Techet --depth;
17052683f446SJiří Techet }
17062683f446SJiří Techet
17072683f446SJiří Techet if (! info->isNameCandidate)
17082683f446SJiří Techet initToken (token);
17092683f446SJiří Techet
17102683f446SJiří Techet CollectingSignature = false;
17112683f446SJiří Techet return nextChar;
17122683f446SJiří Techet }
17132683f446SJiří Techet
initParenInfo(parenInfo * const info)17142683f446SJiří Techet static void initParenInfo (parenInfo *const info)
17152683f446SJiří Techet {
17162683f446SJiří Techet info->isPointer = false;
17172683f446SJiří Techet info->isParamList = true;
17182683f446SJiří Techet info->isNameCandidate = true;
17192683f446SJiří Techet info->invalidContents = false;
17202683f446SJiří Techet info->nestedArgs = false;
17212683f446SJiří Techet info->parameterCount = 0;
17222683f446SJiří Techet }
17232683f446SJiří Techet
analyzeParens(statementInfo * const st)17242683f446SJiří Techet static void analyzeParens (statementInfo *const st)
17252683f446SJiří Techet {
17262683f446SJiří Techet tokenInfo *const prev = prevToken (st, 1);
17272683f446SJiří Techet
17282683f446SJiří Techet if (st->inFunction && !st->assignment)
17292683f446SJiří Techet st->notVariable = true;
17302683f446SJiří Techet
17312683f446SJiří Techet if (! isType (prev, TOKEN_NONE)) /* in case of ignored enclosing macros */
17322683f446SJiří Techet {
17332683f446SJiří Techet tokenInfo *const token = activeToken (st);
17342683f446SJiří Techet parenInfo info;
17352683f446SJiří Techet int c;
17362683f446SJiří Techet
17372683f446SJiří Techet initParenInfo (&info);
17382683f446SJiří Techet parseParens (st, &info);
17392683f446SJiří Techet c = skipToNonWhite ();
17402683f446SJiří Techet cppUngetc (c);
17412683f446SJiří Techet if (info.invalidContents)
17422683f446SJiří Techet {
17432683f446SJiří Techet /* FIXME: This breaks parsing of variable instantiations that have
17442683f446SJiří Techet constants as parameters: Type var(0) or Type var("..."). */
17452683f446SJiří Techet reinitStatement (st, false);
17462683f446SJiří Techet }
17472683f446SJiří Techet else if (info.isNameCandidate && isType (token, TOKEN_PAREN_NAME) &&
17482683f446SJiří Techet ! st->gotParenName &&
17492683f446SJiří Techet (! info.isParamList || ! st->haveQualifyingName ||
17502683f446SJiří Techet c == '(' ||
17512683f446SJiří Techet (c == '=' && st->implementation != IMP_VIRTUAL) ||
17522683f446SJiří Techet (st->declaration == DECL_NONE && isOneOf (c, ",;"))))
17532683f446SJiří Techet {
17542683f446SJiří Techet token->type = TOKEN_NAME;
17552683f446SJiří Techet processName (st);
17562683f446SJiří Techet st->gotParenName = true;
17572683f446SJiří Techet if (! (c == '(' && info.nestedArgs))
17582683f446SJiří Techet st->isPointer = info.isPointer;
17592683f446SJiří Techet }
17602683f446SJiří Techet else if (! st->gotArgs && info.isParamList)
17612683f446SJiří Techet {
17622683f446SJiří Techet st->gotArgs = true;
17632683f446SJiří Techet setToken (st, TOKEN_ARGS);
17642683f446SJiří Techet advanceToken (st);
17652683f446SJiří Techet if (st->scope != SCOPE_TYPEDEF)
17662683f446SJiří Techet analyzePostParens (st, &info);
17672683f446SJiří Techet }
17682683f446SJiří Techet else
17692683f446SJiří Techet setToken (st, TOKEN_NONE);
17702683f446SJiří Techet }
17712683f446SJiří Techet }
17722683f446SJiří Techet
17732683f446SJiří Techet /*
17742683f446SJiří Techet * Token parsing functions
17752683f446SJiří Techet */
17762683f446SJiří Techet
addContext(statementInfo * const st,const tokenInfo * const token)17772683f446SJiří Techet static void addContext (statementInfo *const st, const tokenInfo* const token)
17782683f446SJiří Techet {
17792683f446SJiří Techet if (isType (token, TOKEN_NAME))
17802683f446SJiří Techet {
17812683f446SJiří Techet vStringCat (st->context->name, token->name);
17822683f446SJiří Techet st->context->type = TOKEN_NAME;
17832683f446SJiří Techet }
17842683f446SJiří Techet }
17852683f446SJiří Techet
processColon(statementInfo * const st)17862683f446SJiří Techet static void processColon (statementInfo *const st)
17872683f446SJiří Techet {
17882683f446SJiří Techet int c = skipToNonWhite ();
17892683f446SJiří Techet const bool doubleColon = (bool) (c == ':');
17902683f446SJiří Techet
17912683f446SJiří Techet if (doubleColon)
17922683f446SJiří Techet {
17932683f446SJiří Techet setToken (st, TOKEN_DOUBLE_COLON);
17942683f446SJiří Techet st->haveQualifyingName = false;
17952683f446SJiří Techet }
17962683f446SJiří Techet else
17972683f446SJiří Techet {
17982683f446SJiří Techet const tokenInfo *const prev = prevToken (st, 1);
179901dc7f65SJiří Techet cppUngetc (c);
18007bdd792eSJiří Techet if (st->parent != NULL)
18012683f446SJiří Techet {
18022683f446SJiří Techet makeTag (prev, st, false, TAG_LABEL);
18032683f446SJiří Techet reinitStatement (st, false);
18042683f446SJiří Techet }
18052683f446SJiří Techet }
18062683f446SJiří Techet }
18072683f446SJiří Techet
18082683f446SJiří Techet /* Skips over any initializing value which may follow an '=' character in a
18092683f446SJiří Techet * variable definition.
18102683f446SJiří Techet */
skipInitializer(statementInfo * const st)18112683f446SJiří Techet static int skipInitializer (statementInfo *const st)
18122683f446SJiří Techet {
18132683f446SJiří Techet bool done = false;
18142683f446SJiří Techet int c;
18152683f446SJiří Techet
18162683f446SJiří Techet while (! done)
18172683f446SJiří Techet {
18182683f446SJiří Techet c = skipToNonWhite ();
18192683f446SJiří Techet
18202683f446SJiří Techet if (c == EOF)
18212683f446SJiří Techet longjmp (Exception, (int) ExceptionFormattingError);
18222683f446SJiří Techet else switch (c)
18232683f446SJiří Techet {
18242683f446SJiří Techet case ',':
18252683f446SJiří Techet case ';': done = true; break;
18262683f446SJiří Techet
18272683f446SJiří Techet case '0':
18282683f446SJiří Techet if (st->implementation == IMP_VIRTUAL)
18292683f446SJiří Techet st->implementation = IMP_PURE_VIRTUAL;
18302683f446SJiří Techet break;
18312683f446SJiří Techet
18322683f446SJiří Techet case '[': skipToMatch ("[]"); break;
18332683f446SJiří Techet case '(': skipToMatch ("()"); break;
18342683f446SJiří Techet case '{': skipToMatch ("{}"); break;
18352683f446SJiří Techet case '<': processAngleBracket(); break;
18362683f446SJiří Techet
18372683f446SJiří Techet case '}':
18382683f446SJiří Techet if (insideEnumBody (st))
18392683f446SJiří Techet done = true;
18402683f446SJiří Techet else if (! cppIsBraceFormat ())
18412683f446SJiří Techet {
18422683f446SJiří Techet verbose ("%s: unexpected closing brace at line %lu\n",
18432683f446SJiří Techet getInputFileName (), getInputLineNumber ());
18442683f446SJiří Techet longjmp (Exception, (int) ExceptionBraceFormattingError);
18452683f446SJiří Techet }
18462683f446SJiří Techet break;
18472683f446SJiří Techet
18482683f446SJiří Techet default: break;
18492683f446SJiří Techet }
18502683f446SJiří Techet }
18512683f446SJiří Techet return c;
18522683f446SJiří Techet }
18532683f446SJiří Techet
processInitializer(statementInfo * const st)18542683f446SJiří Techet static void processInitializer (statementInfo *const st)
18552683f446SJiří Techet {
18562683f446SJiří Techet const bool inEnumBody = insideEnumBody (st);
18572683f446SJiří Techet int c = cppGetc ();
18582683f446SJiří Techet
18592683f446SJiří Techet if (c != '=')
18602683f446SJiří Techet {
18612683f446SJiří Techet cppUngetc (c);
18622683f446SJiří Techet c = skipInitializer (st);
18632683f446SJiří Techet st->assignment = true;
18642683f446SJiří Techet if (c == ';')
18652683f446SJiří Techet setToken (st, TOKEN_SEMICOLON);
18662683f446SJiří Techet else if (c == ',')
18672683f446SJiří Techet setToken (st, TOKEN_COMMA);
18682683f446SJiří Techet else if (c == '}' && inEnumBody)
18692683f446SJiří Techet {
18702683f446SJiří Techet cppUngetc (c);
18712683f446SJiří Techet setToken (st, TOKEN_COMMA);
18722683f446SJiří Techet }
18732683f446SJiří Techet if (st->scope == SCOPE_EXTERN)
18742683f446SJiří Techet st->scope = SCOPE_GLOBAL;
18752683f446SJiří Techet }
18762683f446SJiří Techet }
18772683f446SJiří Techet
parseIdentifier(statementInfo * const st,const int c)18782683f446SJiří Techet static void parseIdentifier (statementInfo *const st, const int c)
18792683f446SJiří Techet {
18802683f446SJiří Techet tokenInfo *const token = activeToken (st);
18812683f446SJiří Techet
18822683f446SJiří Techet readIdentifier (token, c);
18832683f446SJiří Techet if (! isType (token, TOKEN_NONE))
18842683f446SJiří Techet processToken (token, st);
18852683f446SJiří Techet }
18862683f446SJiří Techet
parseGeneralToken(statementInfo * const st,const int c)18872683f446SJiří Techet static void parseGeneralToken (statementInfo *const st, const int c)
18882683f446SJiří Techet {
18892683f446SJiří Techet const tokenInfo *const prev = prevToken (st, 1);
18902683f446SJiří Techet
189123c6e73eSJiří Techet if (cppIsident1 (c))
18922683f446SJiří Techet {
18932683f446SJiří Techet
18942683f446SJiří Techet parseIdentifier (st, c);
18952683f446SJiří Techet if (isType (st->context, TOKEN_NAME) &&
18962683f446SJiří Techet isType (activeToken (st), TOKEN_NAME) && isType (prev, TOKEN_NAME))
18972683f446SJiří Techet {
18982683f446SJiří Techet initToken (st->context);
18992683f446SJiří Techet }
19002683f446SJiří Techet }
19012683f446SJiří Techet else if (c == '.' || c == '-')
19022683f446SJiří Techet {
19032683f446SJiří Techet if (! st->assignment)
19042683f446SJiří Techet st->notVariable = true;
19052683f446SJiří Techet if (c == '-')
19062683f446SJiří Techet {
19072683f446SJiří Techet int c2 = cppGetc ();
19082683f446SJiří Techet if (c2 != '>')
19092683f446SJiří Techet cppUngetc (c2);
19102683f446SJiří Techet }
19112683f446SJiří Techet }
19122683f446SJiří Techet else if (c == '!' || c == '>')
19132683f446SJiří Techet {
19142683f446SJiří Techet int c2 = cppGetc ();
19152683f446SJiří Techet if (c2 != '=')
19162683f446SJiří Techet cppUngetc (c2);
19172683f446SJiří Techet }
19182683f446SJiří Techet else if (c == STRING_SYMBOL) {
19192683f446SJiří Techet setToken(st, TOKEN_NONE);
19202683f446SJiří Techet }
19212683f446SJiří Techet }
19222683f446SJiří Techet
19232683f446SJiří Techet /* Reads characters from the pre-processor and assembles tokens, setting
19242683f446SJiří Techet * the current statement state.
19252683f446SJiří Techet */
nextToken(statementInfo * const st)19262683f446SJiří Techet static void nextToken (statementInfo *const st)
19272683f446SJiří Techet {
19282683f446SJiří Techet tokenInfo *token;
19292683f446SJiří Techet do
19302683f446SJiří Techet {
19312683f446SJiří Techet int c = skipToNonWhite ();
19322683f446SJiří Techet switch (c)
19332683f446SJiří Techet {
19342683f446SJiří Techet case EOF: longjmp (Exception, (int) ExceptionEOF); break;
19352683f446SJiří Techet case '(': analyzeParens (st); break;
19362683f446SJiří Techet case '<': processAngleBracket (); break;
19372683f446SJiří Techet case '*': st->haveQualifyingName = false; break;
19382683f446SJiří Techet case ',': setToken (st, TOKEN_COMMA); break;
19392683f446SJiří Techet case ':': processColon (st); break;
19402683f446SJiří Techet case ';': setToken (st, TOKEN_SEMICOLON); break;
19412683f446SJiří Techet case '=': processInitializer (st); break;
19422683f446SJiří Techet case '[': skipToMatch ("[]"); break;
19432683f446SJiří Techet case '{': setToken (st, TOKEN_BRACE_OPEN); break;
19442683f446SJiří Techet case '}': setToken (st, TOKEN_BRACE_CLOSE); break;
19452683f446SJiří Techet default: parseGeneralToken (st, c); break;
19462683f446SJiří Techet }
19472683f446SJiří Techet token = activeToken (st);
19482683f446SJiří Techet } while (isType (token, TOKEN_NONE));
19492683f446SJiří Techet }
19502683f446SJiří Techet
19512683f446SJiří Techet /*
19522683f446SJiří Techet * Scanning support functions
19532683f446SJiří Techet */
19542683f446SJiří Techet
19552683f446SJiří Techet static statementInfo *CurrentStatement = NULL;
19562683f446SJiří Techet
newStatement(statementInfo * const parent)19572683f446SJiří Techet static statementInfo *newStatement (statementInfo *const parent)
19582683f446SJiří Techet {
19592683f446SJiří Techet statementInfo *const st = xMalloc (1, statementInfo);
19602683f446SJiří Techet unsigned int i;
19612683f446SJiří Techet
19622683f446SJiří Techet for (i = 0 ; i < (unsigned int) NumTokens ; ++i)
19632683f446SJiří Techet st->token [i] = newToken ();
19642683f446SJiří Techet
19652683f446SJiří Techet st->context = newToken ();
19662683f446SJiří Techet st->blockName = newToken ();
19672683f446SJiří Techet st->parentClasses = vStringNew ();
19682683f446SJiří Techet
19692683f446SJiří Techet initStatement (st, parent);
19702683f446SJiří Techet CurrentStatement = st;
19712683f446SJiří Techet
19722683f446SJiří Techet return st;
19732683f446SJiří Techet }
19742683f446SJiří Techet
deleteStatement(void)19752683f446SJiří Techet static void deleteStatement (void)
19762683f446SJiří Techet {
19772683f446SJiří Techet statementInfo *const st = CurrentStatement;
19782683f446SJiří Techet statementInfo *const parent = st->parent;
19792683f446SJiří Techet unsigned int i;
19802683f446SJiří Techet
19812683f446SJiří Techet for (i = 0 ; i < (unsigned int) NumTokens ; ++i)
19822683f446SJiří Techet {
19832683f446SJiří Techet deleteToken (st->token [i]); st->token [i] = NULL;
19842683f446SJiří Techet }
19852683f446SJiří Techet deleteToken (st->blockName); st->blockName = NULL;
19862683f446SJiří Techet deleteToken (st->context); st->context = NULL;
19872683f446SJiří Techet vStringDelete (st->parentClasses); st->parentClasses = NULL;
19882683f446SJiří Techet eFree (st);
19892683f446SJiří Techet CurrentStatement = parent;
19902683f446SJiří Techet }
19912683f446SJiří Techet
deleteAllStatements(void)19922683f446SJiří Techet static void deleteAllStatements (void)
19932683f446SJiří Techet {
19942683f446SJiří Techet while (CurrentStatement != NULL)
19952683f446SJiří Techet deleteStatement ();
19962683f446SJiří Techet }
19972683f446SJiří Techet
isStatementEnd(const statementInfo * const st)19982683f446SJiří Techet static bool isStatementEnd (const statementInfo *const st)
19992683f446SJiří Techet {
20002683f446SJiří Techet const tokenInfo *const token = activeToken (st);
20012683f446SJiří Techet bool isEnd;
20022683f446SJiří Techet
20032683f446SJiří Techet if (isType (token, TOKEN_SEMICOLON))
20042683f446SJiří Techet isEnd = true;
20052683f446SJiří Techet else if (isType (token, TOKEN_BRACE_CLOSE))
200623c6e73eSJiří Techet isEnd = ! isContextualStatement (st);
20072683f446SJiří Techet else
20082683f446SJiří Techet isEnd = false;
20092683f446SJiří Techet
20102683f446SJiří Techet return isEnd;
20112683f446SJiří Techet }
20122683f446SJiří Techet
checkStatementEnd(statementInfo * const st,int corkIndex)20132683f446SJiří Techet static void checkStatementEnd (statementInfo *const st, int corkIndex)
20142683f446SJiří Techet {
20152683f446SJiří Techet const tokenInfo *const token = activeToken (st);
20162683f446SJiří Techet
20172683f446SJiří Techet tagEntryInfo *e = getEntryInCorkQueue (corkIndex);
20182683f446SJiří Techet if (e)
20192683f446SJiří Techet e->extensionFields.endLine = token->lineNumber;
20202683f446SJiří Techet
20212683f446SJiří Techet if (isType (token, TOKEN_COMMA))
20222683f446SJiří Techet reinitStatement (st, true);
20232683f446SJiří Techet else if (isStatementEnd (st))
20242683f446SJiří Techet {
20252683f446SJiří Techet DebugStatement ( if (debug (DEBUG_PARSE)) printf ("<ES>"); )
20262683f446SJiří Techet reinitStatement (st, false);
20272683f446SJiří Techet cppEndStatement ();
20282683f446SJiří Techet }
20292683f446SJiří Techet else
20302683f446SJiří Techet {
20312683f446SJiří Techet cppBeginStatement ();
20322683f446SJiří Techet advanceToken (st);
20332683f446SJiří Techet }
20342683f446SJiří Techet }
20352683f446SJiří Techet
nest(statementInfo * const st,const unsigned int nestLevel)20362683f446SJiří Techet static void nest (statementInfo *const st, const unsigned int nestLevel)
20372683f446SJiří Techet {
20382683f446SJiří Techet switch (st->declaration)
20392683f446SJiří Techet {
20402683f446SJiří Techet case DECL_CLASS:
20412683f446SJiří Techet case DECL_ENUM:
20422683f446SJiří Techet case DECL_INTERFACE:
20432683f446SJiří Techet createTags (nestLevel, st);
20442683f446SJiří Techet break;
20452683f446SJiří Techet
20462683f446SJiří Techet case DECL_FUNCTION:
20472683f446SJiří Techet case DECL_TASK:
20482683f446SJiří Techet st->inFunction = true;
20492683f446SJiří Techet /* fall through */
20502683f446SJiří Techet default:
20512683f446SJiří Techet if (includeTag (TAG_LOCAL, false) || includeTag (TAG_LABEL, false))
20522683f446SJiří Techet createTags (nestLevel, st);
20532683f446SJiří Techet else
20542683f446SJiří Techet skipToMatch ("{}");
20552683f446SJiří Techet break;
20562683f446SJiří Techet }
20572683f446SJiří Techet advanceToken (st);
20582683f446SJiří Techet setToken (st, TOKEN_BRACE_CLOSE);
20592683f446SJiří Techet }
20602683f446SJiří Techet
tagCheck(statementInfo * const st)20612683f446SJiří Techet static int tagCheck (statementInfo *const st)
20622683f446SJiří Techet {
20632683f446SJiří Techet const tokenInfo *const token = activeToken (st);
20642683f446SJiří Techet const tokenInfo *const prev = prevToken (st, 1);
20652683f446SJiří Techet const tokenInfo *const prev2 = prevToken (st, 2);
20662683f446SJiří Techet int corkIndex = CORK_NIL;
20672683f446SJiří Techet
20682683f446SJiří Techet switch (token->type)
20692683f446SJiří Techet {
20702683f446SJiří Techet case TOKEN_NAME:
20712683f446SJiří Techet if (insideEnumBody (st))
20722683f446SJiří Techet corkIndex = qualifyEnumeratorTag (st, token);
207323c6e73eSJiří Techet if (insideInterfaceBody (st))
20742683f446SJiří Techet {
20752683f446SJiří Techet /* Quoted from
20762683f446SJiří Techet http://www.asic-world.com/vera/hdl1.html#Interface_Declaration
20772683f446SJiří Techet ------------------------------------------------
20782683f446SJiří Techet interface interface_name
20792683f446SJiří Techet {
20802683f446SJiří Techet signal_direction [signal_width] signal_name signal_type
20812683f446SJiří Techet [skew] [depth value][vca q_value][force][hdl_node "hdl_path"];
20822683f446SJiří Techet }
20832683f446SJiří Techet Where
20842683f446SJiří Techet signal_direction : This can be one of the following
20852683f446SJiří Techet input : ...
20862683f446SJiří Techet output : ...
20872683f446SJiří Techet inout : ...
20882683f446SJiří Techet signal_width : The signal_width is a range specifying the width of
20892683f446SJiří Techet a vector signal. It must be in the form [msb:lsb].
20902683f446SJiří Techet Interface signals can have any integer lsb value,
20912683f446SJiří Techet even a negative value. The default width is 1.
20922683f446SJiří Techet signal_name : The signal_name identifies the signal being defined.
20932683f446SJiří Techet It is the Vera name for the HDL signal being connected.
20942683f446SJiří Techet signal_type : There are many signals types, most commonly used one are
20952683f446SJiří Techet NHOLD : ...
20962683f446SJiří Techet PHOLD : ...
20972683f446SJiří Techet PHOLD NHOLD : ...
20982683f446SJiří Techet NSAMPLE : ...
20992683f446SJiří Techet PSAMPLE : ...
21002683f446SJiří Techet PSAMPLE NSAMPLE : ...
21012683f446SJiří Techet CLOCK : ...
21022683f446SJiří Techet PSAMPLE PHOLD : ...
21032683f446SJiří Techet NSAMPLE NHOLD : ...
21042683f446SJiří Techet PSAMPLE PHOLD NSAMPLE NHOLD : ...
21052683f446SJiří Techet ------------------------------------------------
21062683f446SJiří Techet We want to capture "signal_name" here.
21072683f446SJiří Techet */
21082683f446SJiří Techet if (( isType (prev, TOKEN_KEYWORD)
21092683f446SJiří Techet && isSignalDirection(prev) ) ||
21102683f446SJiří Techet ( isType (prev2, TOKEN_KEYWORD)
21112683f446SJiří Techet && isSignalDirection(prev) ))
21122683f446SJiří Techet corkIndex = makeTag (token, st, false, TAG_SIGNAL);
21132683f446SJiří Techet }
21142683f446SJiří Techet break;
21152683f446SJiří Techet case TOKEN_BRACE_OPEN:
21162683f446SJiří Techet if (isType (prev, TOKEN_ARGS))
21172683f446SJiří Techet {
211801dc7f65SJiří Techet if (st->haveQualifyingName)
21192683f446SJiří Techet {
21202683f446SJiří Techet if (isType (prev2, TOKEN_NAME))
21212683f446SJiří Techet copyToken (st->blockName, prev2);
21222683f446SJiří Techet
21232683f446SJiří Techet corkIndex = qualifyFunctionTag (st, prev2);
21242683f446SJiří Techet }
21252683f446SJiří Techet }
21262683f446SJiří Techet else if (isContextualStatement (st) ||
21272683f446SJiří Techet st->declaration == DECL_PROGRAM)
21282683f446SJiří Techet {
21292683f446SJiří Techet const tokenInfo *name_token = prev;
21302683f446SJiří Techet
21312683f446SJiří Techet if (isType (name_token, TOKEN_NAME))
21322683f446SJiří Techet copyToken (st->blockName, name_token);
21332683f446SJiří Techet else
21342683f446SJiří Techet {
21352683f446SJiří Techet /* For an anonymous struct or union we use a unique ID
21362683f446SJiří Techet * a number, so that the members can be found.
21372683f446SJiří Techet */
21382683f446SJiří Techet char buf [20]; /* length of "_anon" + digits + null */
21392683f446SJiří Techet sprintf (buf, "__anon%d", ++AnonymousID);
21402683f446SJiří Techet vStringCopyS (st->blockName->name, buf);
21412683f446SJiří Techet st->blockName->type = TOKEN_NAME;
21422683f446SJiří Techet st->blockName->keyword = KEYWORD_NONE;
21432683f446SJiří Techet }
21442683f446SJiří Techet corkIndex = qualifyBlockTag (st, name_token);
21452683f446SJiří Techet }
21462683f446SJiří Techet break;
21472683f446SJiří Techet
21482683f446SJiří Techet case TOKEN_KEYWORD:
21492683f446SJiří Techet break;
21502683f446SJiří Techet
21512683f446SJiří Techet case TOKEN_SEMICOLON:
21522683f446SJiří Techet case TOKEN_COMMA:
21532683f446SJiří Techet if (insideEnumBody (st))
21542683f446SJiří Techet ;
21552683f446SJiří Techet else if (isType (prev, TOKEN_NAME))
21562683f446SJiří Techet {
21572683f446SJiří Techet if (isContextualKeyword (prev2))
21582683f446SJiří Techet corkIndex = makeTag (prev, st, true, TAG_EXTERN_VAR);
21592683f446SJiří Techet else
21602683f446SJiří Techet corkIndex = qualifyVariableTag (st, prev);
21612683f446SJiří Techet }
21622683f446SJiří Techet else if (isType (prev, TOKEN_ARGS) && isType (prev2, TOKEN_NAME))
21632683f446SJiří Techet {
21642683f446SJiří Techet if (st->isPointer || st->inFunction)
21652683f446SJiří Techet {
21662683f446SJiří Techet /* If it looks like a pointer or we are in a function body then
21672683f446SJiří Techet it's far more likely to be a variable. */
21682683f446SJiří Techet corkIndex = qualifyVariableTag (st, prev2);
21692683f446SJiří Techet }
21702683f446SJiří Techet else
21712683f446SJiří Techet corkIndex = qualifyFunctionDeclTag (st, prev2);
21722683f446SJiří Techet }
21732683f446SJiří Techet break;
21742683f446SJiří Techet
21752683f446SJiří Techet default: break;
21762683f446SJiří Techet }
21772683f446SJiří Techet
21782683f446SJiří Techet return corkIndex;
21792683f446SJiří Techet }
21802683f446SJiří Techet
21812683f446SJiří Techet /* Parses the current file and decides whether to write out and tags that
21822683f446SJiří Techet * are discovered.
21832683f446SJiří Techet */
createTags(const unsigned int nestLevel,statementInfo * const parent)21842683f446SJiří Techet static void createTags (const unsigned int nestLevel,
21852683f446SJiří Techet statementInfo *const parent)
21862683f446SJiří Techet {
21872683f446SJiří Techet statementInfo *const st = newStatement (parent);
21882683f446SJiří Techet
21892683f446SJiří Techet DebugStatement ( if (nestLevel > 0) debugParseNest (true, nestLevel); )
21902683f446SJiří Techet while (true)
21912683f446SJiří Techet {
21922683f446SJiří Techet tokenInfo *token;
21932683f446SJiří Techet
21942683f446SJiří Techet nextToken (st);
21952683f446SJiří Techet token = activeToken (st);
21962683f446SJiří Techet if (isType (token, TOKEN_BRACE_CLOSE))
21972683f446SJiří Techet {
21982683f446SJiří Techet if (nestLevel > 0)
21992683f446SJiří Techet break;
22002683f446SJiří Techet else
22012683f446SJiří Techet {
22022683f446SJiří Techet verbose ("%s: unexpected closing brace at line %lu\n",
22032683f446SJiří Techet getInputFileName (), getInputLineNumber ());
22042683f446SJiří Techet longjmp (Exception, (int) ExceptionBraceFormattingError);
22052683f446SJiří Techet }
22062683f446SJiří Techet }
22072683f446SJiří Techet else if (isType (token, TOKEN_DOUBLE_COLON))
22082683f446SJiří Techet {
22092683f446SJiří Techet addContext (st, prevToken (st, 1));
22102683f446SJiří Techet advanceToken (st);
22112683f446SJiří Techet }
22122683f446SJiří Techet else
22132683f446SJiří Techet {
22142683f446SJiří Techet int corkIndex = tagCheck (st);
22152683f446SJiří Techet if (isType (token, TOKEN_BRACE_OPEN))
22162683f446SJiří Techet nest (st, nestLevel + 1);
22172683f446SJiří Techet checkStatementEnd (st, corkIndex);
22182683f446SJiří Techet }
22192683f446SJiří Techet }
22202683f446SJiří Techet deleteStatement ();
22212683f446SJiří Techet DebugStatement ( if (nestLevel > 0) debugParseNest (false, nestLevel - 1); )
22222683f446SJiří Techet }
22232683f446SJiří Techet
findCTags(const unsigned int passCount)22242683f446SJiří Techet static rescanReason findCTags (const unsigned int passCount)
22252683f446SJiří Techet {
22262683f446SJiří Techet exception_t exception;
22272683f446SJiří Techet rescanReason rescan;
222823c6e73eSJiří Techet int kind_for_define = VK_DEFINE;
222923c6e73eSJiří Techet int kind_for_header = VK_HEADER;
223023c6e73eSJiří Techet int kind_for_param = VK_MACRO_PARAM;
223123c6e73eSJiří Techet int role_for_macro_undef = VR_MACRO_UNDEF;
223223c6e73eSJiří Techet int role_for_macro_condition = VR_MACRO_CONDITION;
223323c6e73eSJiří Techet int role_for_header_system = VR_HEADER_SYSTEM;
223423c6e73eSJiří Techet int role_for_header_local = VR_HEADER_LOCAL;
22352683f446SJiří Techet
22362683f446SJiří Techet Assert (passCount < 3);
22372683f446SJiří Techet
22382683f446SJiří Techet AnonymousID = 0;
22392683f446SJiří Techet
224023c6e73eSJiří Techet cppInit ((bool) (passCount > 1), false, false,
224123c6e73eSJiří Techet true,
22422683f446SJiří Techet kind_for_define, role_for_macro_undef, role_for_macro_condition, kind_for_param,
22432683f446SJiří Techet kind_for_header, role_for_header_system, role_for_header_local,
22442683f446SJiří Techet FIELD_UNKNOWN);
22452683f446SJiří Techet
22462683f446SJiří Techet Signature = vStringNew ();
22472683f446SJiří Techet
22482683f446SJiří Techet exception = (exception_t) setjmp (Exception);
22492683f446SJiří Techet rescan = RESCAN_NONE;
22502683f446SJiří Techet if (exception == ExceptionNone)
22512683f446SJiří Techet createTags (0, NULL);
22522683f446SJiří Techet else
22532683f446SJiří Techet {
22542683f446SJiří Techet deleteAllStatements ();
22552683f446SJiří Techet if (exception == ExceptionBraceFormattingError && passCount == 1)
22562683f446SJiří Techet {
22572683f446SJiří Techet rescan = RESCAN_FAILED;
22582683f446SJiří Techet verbose ("%s: retrying file with fallback brace matching algorithm\n",
22592683f446SJiří Techet getInputFileName ());
22602683f446SJiří Techet }
22612683f446SJiří Techet }
22622683f446SJiří Techet vStringDelete (Signature);
22632683f446SJiří Techet cppTerminate ();
22642683f446SJiří Techet return rescan;
22652683f446SJiří Techet }
22662683f446SJiří Techet
buildKeywordHash(const langType language,unsigned int idx)22672683f446SJiří Techet static void buildKeywordHash (const langType language, unsigned int idx)
22682683f446SJiří Techet {
22692683f446SJiří Techet const size_t count = ARRAY_SIZE (KeywordTable);
22702683f446SJiří Techet size_t i;
22712683f446SJiří Techet for (i = 0 ; i < count ; ++i)
22722683f446SJiří Techet {
22732683f446SJiří Techet const keywordDesc* const p = &KeywordTable [i];
22742683f446SJiří Techet addKeyword (p->name, language, (int) p->id);
22752683f446SJiří Techet }
22762683f446SJiří Techet }
22772683f446SJiří Techet
initializeVeraParser(const langType language)22782683f446SJiří Techet static void initializeVeraParser (const langType language)
22792683f446SJiří Techet {
22802683f446SJiří Techet Lang_vera = language;
228123c6e73eSJiří Techet buildKeywordHash (language, 0);
22822683f446SJiří Techet }
22832683f446SJiří Techet
VeraParser(void)22842683f446SJiří Techet extern parserDefinition* VeraParser (void)
22852683f446SJiří Techet {
22862683f446SJiří Techet static const char *const extensions [] = { "vr", "vri", "vrh", NULL };
22872683f446SJiří Techet parserDefinition* def = parserNew ("Vera");
22882683f446SJiří Techet def->kindTable = VeraKinds;
22892683f446SJiří Techet def->kindCount = ARRAY_SIZE (VeraKinds);
22902683f446SJiří Techet def->extensions = extensions;
22912683f446SJiří Techet def->parser2 = findCTags;
22922683f446SJiří Techet def->initialize = initializeVeraParser;
22932683f446SJiří Techet // end: field is not tested.
22942683f446SJiří Techet
22952683f446SJiří Techet /* cpreprocessor wants corkQueue. */
22962683f446SJiří Techet def->useCork = CORK_QUEUE;
22972683f446SJiří Techet
22982683f446SJiří Techet return def;
22992683f446SJiří Techet }
2300