【问题标题】:ctags does not parse stdio.h properlyctags 无法正确解析 stdio.h
【发布时间】:2010-12-10 14:20:36
【问题描述】:

我正在尝试将 ctags 与 VIM 一起使用,而且我对两者都是新手。为了测试 ctags 的有用程度,我决定对其进行一个非常简单的测试,即解析 /usr/include 中的标头,以便我可以自动完成一些非常基本的功能。

当我运行命令时

 ctags  --c++-kinds=+p --fields=+iaS -f ~/.tags/tags /usr/include/*.h

然后输出打印

BUFSIZ /usr/include/stdio.h 108;" d EOF /usr/include/stdio.h 115;" d 文件 /usr/include/stdio.h /^typedef struct _IO_FILE FILE;$/;" t typeref:struct:_IO_FILE FSETLOCKING_BYCALLER /usr/include/stdio_ext.h /^ FSETLOCKING_BYCALLER$/;" e enum:__anon122 FSETLOCKING_BYCALLER /usr/include/stdio_ext.h 39;" d FSETLOCKING_INTERNAL /usr/include/stdio_ext.h /^ FSETLOCKING_INTERNAL,$/;" e enum:__anon122 FSETLOCKING_INTERNAL /usr/include/stdio_ext.h 36;" d FSETLOCKING_QUERY /usr/include/stdio_ext.h /^ FSETLOCKING_QUERY = 0,$/;" e enum:__anon122 FSETLOCKING_QUERY /usr/include/stdio_ext.h 32;" d P_tmpdir /usr/include/stdio.h 128;" d SEEK_CUR /usr/include/stdio.h 122;" d SEEK_END /usr/include/stdio.h 123;" d SEEK_SET /usr/include/stdio.h 121;" d _IOFBF /usr/include/stdio.h 101;" d _IOLBF /usr/include/stdio.h 102;" d _IONBF /usr/include/stdio.h 103;" d _IO_STDIO /usr/include/libio.h 165;" d _IO_STDIO_H /usr/include/libio.h 30;" d _OLD_STDIO_MAGIC /usr/include/libio.h 121;" d _STDIO_EXT_H /usr/include/stdio_ext.h 24;" d _STDIO_H /usr/include/stdio.h 27;" d _STDIO_USES_IOSTREAM /usr/include/stdio.h 73;" d _VA_LIST_DEFINED /usr/include/stdio.h 81;" d __FILE /usr/include/stdio.h /^typedef struct _IO_FILE __FILE;$/;" t typeref:struct:_IO_FILE __FILE_defined /usr/include/stdio.h 57;" d ____FILE_defined /usr/include/stdio.h 67;" d __need_FILE /usr/include/stdio.h 37;" d __need_FILE /usr/include/stdio.h 59;" d __need_NULL /usr/include/stdio.h 33;" d __need___FILE /usr/include/stdio.h 38;" d __need___FILE /usr/include/stdio.h 69;" d __need_getopt /usr/include/stdio.h 902;" d __need_size_t /usr/include/stdio.h 32;" d __wur /usr/include/stdio.h /^ _IO_cookie_io_functions_t __io_funcs) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^ __THROW __attribute__ ((__format__ (__printf__, 2, 0))) __wur;$/;" v __wur /usr/include/stdio.h /^ __THROW __attribute__ ((__format__ (__printf__, 2, 3))) __wur;$/;" v __wur /usr/include/stdio.h /^ __THROW __attribute_malloc__ __wur;$/;" v __wur /usr/include/stdio.h /^ __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern FILE *fdopen (int __fd, __const char *__modes) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern char *tmpnam (char *__s) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern char *tmpnam_r (char *__s) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern int feof (FILE *__stream) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern int feof_unlocked (FILE *__stream) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern int ferror (FILE *__stream) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern int ferror_unlocked (FILE *__stream) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern int fileno (FILE *__stream) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern int fileno_unlocked (FILE *__stream) __THROW __wur;$/;" v __wur /usr/include/stdio.h /^extern int ftrylockfile (FILE *__stream) __THROW __wur;$/;" v _flushlbf /usr/include/stdio_ext.h /^extern void _flushlbf (void);$/;" p 签名:(void) cuserid /usr/include/stdio.h /^extern char *cuserid (char *__s);$/;" p 签名:(char *__s) dprintf /usr/include/stdio.h /^extern int dprintf (int __fd, __const char *__restrict __fmt, ...)$/;" p 签名:(int __fd, __const char *__restrict __fmt, ...) fclose /usr/include/stdio.h /^extern int fclose (FILE *__stream);$/;" p 签名:(FILE *__stream) fcloseall /usr/include/stdio.h /^extern int fcloseall (void);$/;" p 签名:(void) fflush /usr/include/stdio.h /^extern int fflush (FILE *__stream);$/;" p 签名:(FILE *__stream) fflush_unlocked /usr/include/stdio.h /^extern int fflush_unlocked (FILE *__stream);$/;" p 签名:(FILE *__stream) fgetc /usr/include/stdio.h /^extern int fgetc (FILE *__stream);$/;" p 签名:(FILE *__stream) fgetc_unlocked /usr/include/stdio.h /^extern int fgetc_unlocked (FILE *__stream);$/;" p 签名:(FILE *__stream) fgetpos /usr/include/stdio.h /^extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos);$/;" p 签名:(FILE *__restrict __stream, fpos_t *__restrict __pos) fgetpos64 /usr/include/stdio.h /^extern int fgetpos64 (FILE *__restrict __stream, fpos64_t *__restrict __pos);$/;" p 签名:(FILE *__restrict __stream, fpos64_t *__restrict __pos) fpos64_t /usr/include/stdio.h /^typedef _G_fpos64_t fpos64_t;$/;" t fpos_t /usr/include/stdio.h /^typedef _G_fpos_t fpos_t;$/;" t fprintf /usr/include/stdio.h /^extern int fprintf (FILE *__restrict __stream,$/;" p 签名:(FILE *__restrict __stream, __const char *__restrict __format, ...) fputc /usr/include/stdio.h /^extern int fputc (int __c, FILE *__stream);$/;" p 签名:(int __c, FILE *__stream) fputc_unlocked /usr/include/stdio.h /^extern int fputc_unlocked (int __c, FILE *__stream);$/;" p 签名:(int __c, FILE *__stream) fputs /usr/include/stdio.h /^extern int fputs (__const char *__restrict __s, FILE *__restrict __stream);$/;" p 签名:(__const char *__restrict __s, FILE *__restrict __stream) fputs_unlocked /usr/include/stdio.h /^extern int fputs_unlocked (__const char *__restrict __s,$/;" p 签名:(__const char *__restrict __s, FILE *__restrict __stream) fscanf /usr/include/stdio.h 441;" d fseek /usr/include/stdio.h /^extern int fseek (FILE *__stream, long int __off, int __whence);$/;" p 签名:(FILE *__stream, long int __off, int __whence) fseeko /usr/include/stdio.h /^extern int fseeko (FILE *__stream, __off_t __off, int __whence);$/;" p 签名:(FILE *__stream, __off_t __off, int __whence) fseeko64 /usr/include/stdio.h /^extern int fseeko64 (FILE *__stream, __off64_t __off, int __whence);$/;" p 签名:(FILE *__stream, __off64_t __off, int __whence) fsetpos /usr/include/stdio.h /^extern int fsetpos (FILE *__stream, __const fpos_t *__pos);$/;" p 签名:(FILE *__stream, __const fpos_t *__pos) fsetpos64 /usr/include/stdio.h /^extern int fsetpos64 (FILE *__stream, __const fpos64_t *__pos);$/;" p 签名:(FILE *__stream, __const fpos64_t *__pos) getc /usr/include/stdio.h /^extern int getc (FILE *__stream);$/;" p 签名:(FILE *__stream) getc /usr/include/stdio.h 527;" d getc_unlocked /usr/include/stdio.h /^extern int getc_unlocked (FILE *__stream);$/;" p 签名:(FILE *__stream) getchar /usr/include/stdio.h /^extern int getchar (void);$/;" p 签名:(void) getchar_unlocked /usr/include/stdio.h /^extern int getchar_unlocked (void);$/;" p 签名:(void) getw /usr/include/stdio.h /^extern int getw (FILE *__stream);$/;" p 签名:(FILE *__stream) jpeg_stdio_dest /usr/include/jpeglib.h /^EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile));$/;" p 签名:(j_compress_ptr cinfo, FILE * outfile) jpeg_stdio_dest /usr/include/jpeglib.h 841;" d jpeg_stdio_src /usr/include/jpeglib.h /^EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));$/;" p 签名:(j_decompress_ptr cinfo, FILE * infile) jpeg_stdio_src /usr/include/jpeglib.h 842;" d pclose /usr/include/stdio.h /^extern int pclose (FILE *__stream);$/;" p 签名:(FILE *__stream) perror /usr/include/stdio.h /^extern void perror (__const char *__s);$/;" p 签名:(__const char *__s) printf /usr/include/stdio.h /^extern int printf (__const char *__restrict __format, ...);$/;" p 签名:(__const char *__restrict __format, ...) putc /usr/include/stdio.h /^extern int putc (int __c, FILE *__stream);$/;" p 签名:(int __c, FILE *__stream) putc /usr/include/stdio.h 569;" d putc_unlocked /usr/include/stdio.h /^extern int putc_unlocked (int __c, FILE *__stream);$/;" p 签名:(int __c, FILE *__stream) putchar /usr/include/stdio.h /^extern int putchar (int __c);$/;" p 签名:(int __c) putchar_unlocked /usr/include/stdio.h /^extern int putchar_unlocked (int __c);$/;" p 签名:(int __c) puts /usr/include/stdio.h /^extern int puts (__const char *__s);$/;" p 签名:(__const char *__s) putw /usr/include/stdio.h /^extern int putw (int __w, FILE *__stream);$/;" p 签名:(int __w, FILE *__stream) rewind /usr/include/stdio.h /^extern void rewind (FILE *__stream);$/;" p 签名:(FILE *__stream) scanf /usr/include/stdio.h 442;" d sscanf /usr/include/stdio.h 443;" d 标准错误 /usr/include/stdio.h 152;" d 标准输入 /usr/include/stdio.h 150;" d 标准输出 /usr/include/stdio.h 151;" d ungetc /usr/include/stdio.h /^extern int ungetc (int __c, FILE *__stream);$/;" p 签名:(int __c, FILE *__stream) va_list /usr/include/stdio.h /^typedef _G_va_list va_list;$/;" t vdprintf /usr/include/stdio.h /^extern int vdprintf (int __fd, __const char *__restrict __fmt,$/;" p 签名:(int __fd, __const char *__restrict __fmt, _G_va_list __arg) vfprintf /usr/include/stdio.h /^extern int vfprintf (FILE *__restrict __s, __const char *__restrict __format,$/;" p 签名:(FILE *__restrict __s, __const char *__restrict __format, _G_va_list __arg) vfscanf /usr/include/stdio.h 500;" d vprintf /usr/include/stdio.h /^extern int vprintf (__const char *__restrict __format, _G_va_list __arg);$/;" p 签名:(__const char *__restrict __format, _G_va_list __arg) vscanf /usr/include/stdio.h 501;" d vsscanf /usr/include/stdio.h 502;" d

很明显,ctags 错过了一些非常明显的功能,例如 fopen,但它包含了 fclose 等功能。使用 ctags 解析时是否缺少某些选项?

【问题讨论】:

    标签: c++ c ctags uclinux


    【解决方案1】:

    -I__wur 添加到您的 ctags 命令中,您将获得所需的结果。 __wur__attribute__ ((__warn_unused_result__)) 的宏

    更详尽的解释见:

    http://sourceforge.net/mailarchive/message.php?msg_name=48A7FF60.9080609%40sina.com

    【讨论】:

    • 哦,我明白了,有没有一种通用的方法可以告诉 ctags 我更喜欢函数声明而不是相应的宏?
    【解决方案2】:

    只是一些提示,以便您获得更具体的标签文件:

    # First make sure apt-file is install and then do:
    $ sudo apt-file update
    # set up tags for libc, the standard C library
    $ apt-file list libc6-dev | grep -o '/usr/include/.*\.h'> ~/.vim/tags/libc6-filelist
    $ ctags --sort=foldcase --c++-kinds=+p --fields=+iaS --extra=+q -I./libc6-ignore -f ~/.vim/tags/libc6 -L ~/.vim/tags/libc6-filelist 
    

    文件libc6-ignore的内容是:

    __attribute__
    __attribute_deprecated__
    __attribute_format_arg__
    __attribute_format_strfmon__
    __attribute_malloc__
    __attribute_noinline__
    __attribute_pure__
    __attribute_used__
    __attribute_warn_unused_result__
    __wur
    __THROW
    __nonnull+
    

    我假设您将它与 vim 和 OmniCppComplete 插件一起使用?

    【讨论】:

      【解决方案3】:

      还有更多提示,HTH。

      1。在 Ubuntu 机器下,可以运行dpkg -L libc6-dev |grep -o '/usr/include/.*h' > ~/.vim/tags/libc6-dev_files 来获取 GNU C 库中的头文件。

      2。使用以下命令生成更具体的 ctags 文件。

      # mkdir 如果需要。

      cd ~/.vim/tags
      

      # 使用grep 获取更多被忽略的令牌。

      grep -oe '__attribute\w*__' libc6-dev_tags |sort -u > libc6-dev_ignore-tokens  
      echo __THROW >> libc6-dev_ignore-tokens  
      echo __wur >> libc6-dev_ignore-tokens
      

      # 生成 ctags 文件。详情请参阅 ctags 手册页。

      ctags --c++-kinds=+px --fields=+iaS --extra=+q -I @./libc6-dev_ignore-tokens -L libc6-dev_files -f libc6-dev_tags
      

      3。将此标签文件添加到您的初始标签路径中,即将set tags+=~/.vim/tags/libc6-dev_tags 放在您的 .vimrc 文件中的某个位置。

      【讨论】:

        【解决方案4】:

        同样的问题。使用 -I 选项解决。检查了这个网站的信息: http://ctags.sourceforge.net/ctags.html#OPTIONS

        注意几个“陷阱”。首先,当使用包含忽略列表的文件指定 -I 时,它需要紧跟 @ 或 a 。或 / 或驱动器号(如果在 Windows 中)。我花了几个小时使用 -I ~/ 没有成功。与 -I /home/username/ 相同的东西就像一个魅力。

        其次,确保使用多行解析(--fields=+S)。这已在此线程中指示为 OP 使用的选项,但想再次指出。

        感谢其他所有人的精彩提示!

        【讨论】:

          猜你喜欢
          • 2014-10-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-01
          • 1970-01-01
          • 2019-06-25
          • 2014-12-02
          相关资源
          最近更新 更多