📄 cpp.c
字号:
/* * Copyright (c) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 * Tama Communications Corporation * * This file is part of GNU GLOBAL. * * GNU GLOBAL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GNU GLOBAL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <ctype.h>#ifdef HAVE_LIMITS_H#include <limits.h>#endif#include <stdio.h>#ifdef STDC_HEADERS#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#include "gctags.h"#include "defined.h"#include "die.h"#include "locatestring.h"#include "strbuf.h"#include "strlimcpy.h"#include "token.h"#include "cpp_res.h"static void process_attribute(int);static int function_definition(int);static int seems_datatype(const char *);static void condition_macro(int, int);#define MAXCOMPLETENAME 1024 /* max size of complete name of class */#define MAXCLASSSTACK 100 /* max size of class stack */#define IS_CV_QUALIFIER(c) ((c) == CPP_CONST || (c) == CPP_VOLATILE)/* * #ifdef stack. */#define MAXPIFSTACK 100static struct { short start; /* level when #if block started */ short end; /* level when #if block end */ short if0only; /* #if 0 or notdef only */} pifstack[MAXPIFSTACK], *cur;static int piflevel; /* condition macro level */static int level; /* brace level */static int namespacelevel; /* namespace block level *//* * Cpp: read C++ file and pickup tag entries. */voidCpp(file) const char *file;{ int c, cc; int savelevel; int target; int startclass, startthrow, startmacro, startsharp, startequal; char classname[MAXTOKEN]; char completename[MAXCOMPLETENAME]; int classlevel; struct { char *classname; char *terminate; int level; } stack[MAXCLASSSTACK]; const char *interested = "{}=;~"; STRBUF *sb = strbuf_open(0); *classname = *completename = 0; stack[0].classname = completename; stack[0].terminate = completename; stack[0].level = 0; level = classlevel = piflevel = namespacelevel = 0; savelevel = -1; target = (sflag) ? SYM : (rflag) ? REF : DEF; startclass = startthrow = startmacro = startsharp = startequal = 0; if (!opentoken(file)) die("'%s' cannot open.", file); cmode = 1; /* allow token like '#xxx' */ crflag = 1; /* require '\n' as a token */ cppmode = 1; /* treat '::' as a token */ while ((cc = nexttoken(interested, cpp_reserved_word)) != EOF) { if (cc == '~' && level == stack[classlevel].level) continue; switch (cc) { case SYMBOL: /* symbol */ if (startclass || startthrow) { if (target == REF && defined(token)) PUT(token, lineno, sp); } else if (peekc(0) == '('/* ) */) { if (isnotfunction(token)) { if (target == REF && defined(token)) PUT(token, lineno, sp); } else if (level > stack[classlevel].level || startequal || startmacro) { if (target == REF) { if (defined(token)) PUT(token, lineno, sp); } else if (target == SYM) { if (!defined(token)) PUT(token, lineno, sp); } } else if (level == stack[classlevel].level && !startmacro && !startsharp && !startequal) { char savetok[MAXTOKEN], *saveline; int savelineno = lineno; strlimcpy(savetok, token, sizeof(savetok)); strbuf_reset(sb); strbuf_puts(sb, sp); saveline = strbuf_value(sb); if (function_definition(target)) { /* ignore constructor */ if (target == DEF && strcmp(stack[classlevel].classname, savetok)) PUT(savetok, savelineno, saveline); } else { if (target == REF && defined(savetok)) PUT(savetok, savelineno, saveline); } } } else { if (dflag) { if (target == REF) { if (defined(token)) PUT(token, lineno, sp); } else if (target == SYM) { if (!defined(token)) PUT(token, lineno, sp); } } else { if (target == SYM) PUT(token, lineno, sp); } } break; case CPP_USING: if ((c = nexttoken(interested, cpp_reserved_word)) == CPP_NAMESPACE) { if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL) { if (target == REF) PUT(token, lineno, sp); } else { if (wflag) warning("missing namespace name. [+%d %s].", lineno, curfile); pushbacktoken(); } } else pushbacktoken(); /* FALLTHROUGH */ case CPP_NAMESPACE: if (peekc(0) != '{') /* } */ { if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL) if (target == DEF) PUT(token, lineno, sp); } while ((c = nexttoken(interested, cpp_reserved_word)) == '\n') ; /* * Namespace block doesn't have any influence on level. */ if (c == '{') /* } */ { namespacelevel++; } else { if (wflag) warning("missing namespace block. [+%d %s](0x%x).", lineno, curfile, c); } break; case CPP_CLASS: DBG_PRINT(level, "class"); if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL) { strlimcpy(classname, token, sizeof(classname)); if (target == DEF) PUT(token, lineno, sp); if (peekc(0) != ';') startclass = 1; } break; case '{': /* } */ DBG_PRINT(level, "{"); /* } */ ++level; if (bflag && atfirst) { if (wflag && level != 1) warning("forced level 1 block start by '{' at column 0 [+%d %s].", lineno, curfile); /* } */ level = 1; } if (startclass) { char *p = stack[classlevel].terminate; char *q = classname; if (++classlevel >= MAXCLASSSTACK) die("class stack over flow.[%s]", curfile); if (classlevel > 1) *p++ = '.'; stack[classlevel].classname = p; while (*q) *p++ = *q++; stack[classlevel].terminate = p; stack[classlevel].level = level; *p++ = 0; } startclass = startthrow = 0; break; /* { */ case '}': if (--level < 0) { if (namespacelevel > 0) namespacelevel--; else if (wflag) warning("missing left '{' [+%d %s].", lineno, curfile); /* } */ level = 0; } if (eflag && atfirst) { if (wflag && level != 0) /* { */ warning("forced level 0 block end by '}' at column 0 [+%d %s].", lineno, curfile); level = 0; } if (level < stack[classlevel].level) *(stack[--classlevel].terminate) = 0; /* { */ DBG_PRINT(level, "}"); break; case '=': startequal = 1; break; case ';': startthrow = startequal = 0; break; case '\n': if (startmacro && level != savelevel) { if (wflag) warning("different level before and after #define macro. reseted. [+%d %s].", lineno, curfile); level = savelevel; } startmacro = startsharp = 0; break; /* * #xxx */ case SHARP_DEFINE: case SHARP_UNDEF: startmacro = 1; savelevel = level; if ((c = nexttoken(interested, cpp_reserved_word)) != SYMBOL) { pushbacktoken(); break; } if (peekc(1) == '('/* ) */) { if (target == DEF) PUT(token, lineno, sp); while ((c = nexttoken("()", cpp_reserved_word)) != EOF && c != '\n' && c != /* ( */ ')') if (c == SYMBOL && target == SYM) PUT(token, lineno, sp); if (c == '\n') pushbacktoken(); } else { if (dflag) { if (target == DEF) PUT(token, lineno, sp); } else { if (target == SYM) PUT(token, lineno, sp); } } break; case SHARP_IMPORT: case SHARP_INCLUDE: case SHARP_INCLUDE_NEXT: case SHARP_ERROR: case SHARP_LINE: case SHARP_PRAGMA: case SHARP_WARNING: case SHARP_IDENT: case SHARP_SCCS: while ((c = nexttoken(interested, cpp_reserved_word)) != EOF && c != '\n') ; break; case SHARP_IFDEF: case SHARP_IFNDEF: case SHARP_IF: case SHARP_ELIF: case SHARP_ELSE: case SHARP_ENDIF: condition_macro(cc, target); break; case SHARP_SHARP: /* ## */ (void)nexttoken(interested, cpp_reserved_word); break; case CPP_NEW: if ((c = nexttoken(interested, cpp_reserved_word)) == SYMBOL) if (target == REF && defined(token)) PUT(token, lineno, sp); break; case CPP_STRUCT: c = nexttoken(interested, cpp_reserved_word); if (c == '{' /* } */) { pushbacktoken(); break; } if (c == SYMBOL) if (target == SYM) PUT(token, lineno, sp); break; case CPP_TEMPLATE: { int level = 0; while ((c = nexttoken("<>", cpp_reserved_word)) != EOF) { if (c == '<') ++level; else if (c == '>') { if (--level == 0) break; } else if (c == SYMBOL) { if (target == SYM) PUT(token, lineno, sp); } } if (c == EOF && wflag) warning("templete <...> isn't closed. [+%d %s].", lineno, curfile); } break; case CPP_OPERATOR: while ((c = nexttoken(";{", /* } */ cpp_reserved_word)) != EOF) { if (c == '{') /* } */ { pushbacktoken(); break; } else if (c == ';') { break; } else if (c == SYMBOL) { if (target == SYM) PUT(token, lineno, sp); } } if (c == EOF && wflag) warning("'{' doesn't exist after 'operator'. [+%d %s].", lineno, curfile); /* } */ break; /* control statement check */ case CPP_THROW: startthrow = 1; case CPP_BREAK: case CPP_CASE: case CPP_CATCH: case CPP_CONTINUE: case CPP_DEFAULT: case CPP_DELETE: case CPP_DO: case CPP_ELSE: case CPP_FOR:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -