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

📄 get.c

📁 ctags-5.5.4.tar.gz,一个很好的代码开发以及编辑源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**   $Id: get.c,v 1.7 2003/12/14 18:48:38 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);	makeDefineTag (vStringValue (Cpp.directive.name));    }    Cpp.directive.state = DRCTV_NONE;}static void directivePragma (int c){    if (isident1 (c))    {

⌨️ 快捷键说明

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