⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 get.c

📁 Exuberant Ctags is a multilanguage reimplementation of the much-underused ctags(1) program and is i
💻 C
📖 第 1 页 / 共 2 页
字号:
/**   $Id: get.c,v 1.9 2006/05/30 04:37:12 darren Exp $**   Copyright (c) 1996-2002, Darren Hiebert**   This source code is released for free distribution under the terms of the*   GNU General Public License.**   This module contains the high level source read functions (preprocessor*   directives are handled within this level).*//**   INCLUDE FILES*/#include "general.h"  /* must always come first */#include <string.h>#include "debug.h"#include "entry.h"#include "get.h"#include "options.h"#include "read.h"#include "vstring.h"/**   MACROS*/#define stringMatch(s1,s2)		(strcmp (s1,s2) == 0)#define isspacetab(c)			((c) == SPACE || (c) == TAB)/**   DATA DECLARATIONS*/typedef enum { COMMENT_NONE, COMMENT_C, COMMENT_CPLUS } Comment;enum eCppLimits {	MaxCppNestingLevel = 20,	MaxDirectiveName = 10};/*  Defines the one nesting level of a preprocessor conditional. */typedef struct sConditionalInfo {	boolean ignoreAllBranches;  /* ignoring parent conditional branch */	boolean singleBranch;       /* choose only one branch */	boolean branchChosen;       /* branch already selected */	boolean ignoring;           /* current ignore state */} conditionalInfo;enum eState {	DRCTV_NONE,    /* no known directive - ignore to end of line */	DRCTV_DEFINE,  /* "#define" encountered */	DRCTV_HASH,    /* initial '#' read; determine directive */	DRCTV_IF,      /* "#if" or "#ifdef" encountered */	DRCTV_PRAGMA,  /* #pragma encountered */	DRCTV_UNDEF    /* "#undef" encountered */};/*  Defines the current state of the pre-processor. */typedef struct sCppState {	int		ungetch, ungetch2;   /* ungotten characters, if any */	boolean resolveRequired;     /* must resolve if/else/elif/endif branch */	struct sDirective {		enum eState state;       /* current directive being processed */		boolean	accept;          /* is a directive syntatically permitted? */		vString * name;          /* macro name */		unsigned int nestLevel;  /* level 0 is not used */		conditionalInfo ifdef [MaxCppNestingLevel];	} directive;} cppState;/**   DATA DEFINITIONS*//*  Use brace formatting to detect end of block. */static boolean BraceFormat = FALSE;static cppState Cpp = {	'\0', '\0',  /* ungetch characters */	FALSE,       /* resolveRequired */	{		DRCTV_NONE,  /* state */		FALSE,       /* accept */		NULL,        /* tag name */		0,           /* nestLevel */		{ {FALSE,FALSE,FALSE,FALSE} }  /* ifdef array */	}  /* directive */};/**   FUNCTION DEFINITIONS*/extern boolean isBraceFormat (void){	return BraceFormat;}extern unsigned int getDirectiveNestLevel (void){	return Cpp.directive.nestLevel;}extern void cppInit (const boolean state){	BraceFormat = state;	Cpp.ungetch         = '\0';	Cpp.ungetch2        = '\0';	Cpp.resolveRequired = FALSE;	Cpp.directive.state     = DRCTV_NONE;	Cpp.directive.accept    = TRUE;	Cpp.directive.nestLevel = 0;	Cpp.directive.ifdef [0].ignoreAllBranches = FALSE;	Cpp.directive.ifdef [0].singleBranch = FALSE;	Cpp.directive.ifdef [0].branchChosen = FALSE;	Cpp.directive.ifdef [0].ignoring     = FALSE;	if (Cpp.directive.name == NULL)		Cpp.directive.name = vStringNew ();	else		vStringClear (Cpp.directive.name);}extern void cppTerminate (void){	if (Cpp.directive.name != NULL)	{		vStringDelete (Cpp.directive.name);		Cpp.directive.name = NULL;	}}extern void cppBeginStatement (void){	Cpp.resolveRequired = TRUE;}extern void cppEndStatement (void){	Cpp.resolveRequired = FALSE;}/**   Scanning functions**   This section handles preprocessor directives.  It strips out all*   directives and may emit a tag for #define directives.*//*  This puts a character back into the input queue for the source File. *  Up to two characters may be ungotten. */extern void cppUngetc (const int c){	Assert (Cpp.ungetch2 == '\0');	Cpp.ungetch2 = Cpp.ungetch;	Cpp.ungetch = c;}/*  Reads a directive, whose first character is given by "c", into "name". */static boolean readDirective (int c, char *const name, unsigned int maxLength){	unsigned int i;	for (i = 0  ;  i < maxLength - 1  ;  ++i)	{		if (i > 0)		{			c = fileGetc ();			if (c == EOF  ||  ! isalpha (c))			{				fileUngetc (c);				break;			}		}		name [i] = c;	}	name [i] = '\0';  /* null terminate */	return (boolean) isspacetab (c);}/*  Reads an identifier, whose first character is given by "c", into "tag", *  together with the file location and corresponding line number. */static void readIdentifier (int c, vString *const name){	vStringClear (name);	do	{		vStringPut (name, c);	} while (c = fileGetc (), (c != EOF  &&  isident (c)));	fileUngetc (c);	vStringTerminate (name);}static conditionalInfo *currentConditional (void){	return &Cpp.directive.ifdef [Cpp.directive.nestLevel];}static boolean isIgnore (void){	return Cpp.directive.ifdef [Cpp.directive.nestLevel].ignoring;}static boolean setIgnore (const boolean ignore){	return Cpp.directive.ifdef [Cpp.directive.nestLevel].ignoring = ignore;}static boolean isIgnoreBranch (void){	conditionalInfo *const ifdef = currentConditional ();	/*  Force a single branch if an incomplete statement is discovered	 *  en route. This may have allowed earlier branches containing complete	 *  statements to be followed, but we must follow no further branches.	 */	if (Cpp.resolveRequired  &&  ! BraceFormat)		ifdef->singleBranch = TRUE;	/*  We will ignore this branch in the following cases:	 *	 *  1.  We are ignoring all branches (conditional was within an ignored	 *        branch of the parent conditional)	 *  2.  A branch has already been chosen and either of:	 *      a.  A statement was incomplete upon entering the conditional	 *      b.  A statement is incomplete upon encountering a branch	 */	return (boolean) (ifdef->ignoreAllBranches ||					 (ifdef->branchChosen  &&  ifdef->singleBranch));}static void chooseBranch (void){	if (! BraceFormat)	{		conditionalInfo *const ifdef = currentConditional ();		ifdef->branchChosen = (boolean) (ifdef->singleBranch ||										Cpp.resolveRequired);	}}/*  Pushes one nesting level for an #if directive, indicating whether or not *  the branch should be ignored and whether a branch has already been chosen. */static boolean pushConditional (const boolean firstBranchChosen){	const boolean ignoreAllBranches = isIgnore ();  /* current ignore */	boolean ignoreBranch = FALSE;	if (Cpp.directive.nestLevel < (unsigned int) MaxCppNestingLevel - 1)	{		conditionalInfo *ifdef;		++Cpp.directive.nestLevel;		ifdef = currentConditional ();		/*  We take a snapshot of whether there is an incomplete statement in		 *  progress upon encountering the preprocessor conditional. If so,		 *  then we will flag that only a single branch of the conditional		 *  should be followed.		 */		ifdef->ignoreAllBranches = ignoreAllBranches;		ifdef->singleBranch      = Cpp.resolveRequired;		ifdef->branchChosen      = firstBranchChosen;		ifdef->ignoring = (boolean) (ignoreAllBranches || (				! firstBranchChosen  &&  ! BraceFormat  &&				(ifdef->singleBranch || !Option.if0)));		ignoreBranch = ifdef->ignoring;	}	return ignoreBranch;}/*  Pops one nesting level for an #endif directive. */static boolean popConditional (void){	if (Cpp.directive.nestLevel > 0)		--Cpp.directive.nestLevel;	return isIgnore ();}static void makeDefineTag (const char *const name){	const boolean isFileScope = (boolean) (! isHeaderFile ());	if (includingDefineTags () &&		(! isFileScope  ||  Option.include.fileScope))	{		tagEntryInfo e;		initTagEntry (&e, name);		e.lineNumberEntry = (boolean) (Option.locate != EX_PATTERN);		e.isFileScope  = isFileScope;		e.truncateLine = TRUE;		e.kindName     = "macro";		e.kind         = 'd';		makeTagEntry (&e);	}}static void directiveDefine (const int c){	if (isident1 (c))	{		readIdentifier (c, Cpp.directive.name);		if (! isIgnore ())			makeDefineTag (vStringValue (Cpp.directive.name));	}	Cpp.directive.state = DRCTV_NONE;}static void directivePragma (int c){	if (isident1 (c))	{		readIdentifier (c, Cpp.directive.name);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -