c++ - 为什么我的 C/C++ header 解析器不工作?

标签 c++ c parsing boost header-files

我想捆绑 Boost Preprocessor库(以及最终其他库)到一个合并的头文件中,所以我拼凑了一个小的实用程序来实现这个目标......只是它不起作用!我无法确定是我的程序中的错误还是实现问题(或两者)导致它无法正常工作。

该程序应该打开 boost\preprocessor\library.hpp header (包括整个库)并递归输出到 stdout 库需要的所有 header . Windows 资源管理器报告目录树​​中有(自 Boost Preprocessor v1.59.0 起)270 个头文件,但我的程序仅解析 204 个。

我通过在另一个使用 Boost 预处理器的项目中使用它来测试合并的 header 。当使用 boost\preprocessor\library.hpp header 时,项目编译并工作正常,但当使用我的合并版本时,由于找不到所有需要的 Boost 预处理器宏,编译失败。

完整的、可编译的代码:(仅使用 MSVC v19 进行测试)

#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <unordered_map>

// Remember what header files have already been parsed.
std::unordered_map<std::string, bool> have_parsed;

char include_dir[FILENAME_MAX]; // Passed in from the command line.

// Advance given pointer to next non-whitespace character and return it.
char* find_next_nonwhitespace_char(char* start) {
    while(isspace((int)(*start)) != 0) start++;
    return start;
}

#define DIE(condition, str) if(condition) {perror(str); exit(EXIT_FAILURE);}

int headers_parsed = 0;

void parse_header(const char* filename) {
    headers_parsed++;
    char path[FILENAME_MAX];
    strcpy(path, include_dir);
    strcat(path, filename);

    // Open file, get size and slurp it up.
    FILE* file = fopen(path, "rb");
    DIE(file == NULL, "fopen()");
    fseek(file, 0L, SEEK_END);
    long int file_size = ftell(file);
    rewind(file);
    char* file_buffer = (char*)malloc(file_size+1); // +1 for extra '\0'
    DIE(file_buffer == NULL, "malloc()");
    size_t got = fread(file_buffer, 1, file_size, file);
    DIE(got != file_size, "fread()");
    fclose(file);

    char* read_index = file_buffer;
    char* end_of_file = file_buffer + file_size;
    *end_of_file = '\0';

    // File is now in memory, parse each line.
    while(read_index < end_of_file) {
        char* start_of_line = read_index;
        // Scan forward looking for newline or 'EOF'
        char* end_of_line = strchr(start_of_line, '\n');
        if(end_of_line == NULL) end_of_line = end_of_file;
        *end_of_line = '\0';
        // Advance to the start of the next line for the next read.
        read_index += (end_of_line - start_of_line) + 1;
        // Look for #include directive at the start of the line.
        char* first_char = find_next_nonwhitespace_char(start_of_line);
        if(*first_char == '#') {
            // This could be an include line...
            char* next_char = find_next_nonwhitespace_char(first_char + 1);
            const char include[] = "include ";
            if(strncmp(next_char, include, strlen(include)) == 0) {
                char* open_brace = find_next_nonwhitespace_char(next_char + strlen(include));
                if(*open_brace++ == '<') {
                    char* close_brace = strchr(open_brace, '>');
                    assert(close_brace != NULL);
                    *close_brace = '\0';
                    if(have_parsed[open_brace] == false) {
                        have_parsed[open_brace] = true;
                        parse_header(open_brace); // Recurse
                    }
                    continue;
                }
            }
        }
        fprintf(stdout, "%s\n", start_of_line);
    }
    free(file_buffer);
}

int main(int argc, char* argv[]) {
    if(argc < 3) {
        fprintf(stderr, "%s {include directory} {first header}\n", argv[0]);
        return EXIT_FAILURE;
    }

    // Ensure the include directory has trailing slash
    strcpy(include_dir, argv[1]);
    size_t len = strlen(argv[1]);
    if(include_dir[len-1] != '\\') {
        include_dir[len] = '\\';
        include_dir[len+1] = '\0';
    }

    parse_header(argv[2]);

    fprintf(stderr, "headers parsed: %d\n", headers_parsed);
    return EXIT_SUCCESS;
}

运行编译好的程序:(Boost安装在g:\dev)

g:\dev\amalgamate\amalgamate.exe g:\dev\ boost\preprocessor\library.hpp > boost_pp.h
headers parsed: 204

以及生成的 boost_pp.h header :https://copy.com/vL6xdtScLogqnv9z

怎么了? 为什么我的程序没有创建有效的合并 header ?

最佳答案

library.hpp 实际上没有包含树中的一些 header ,原因是:

  • 它们将其他 header 包装为外部接口(interface)(或者因为它们已被弃用),例如 preprocessor/comma.hpp 仅包含 preprocessor/punctuation/comma.hpp,

  • 将通过宏包含,例如:

    # define BOOST_PP_ITERATE() BOOST_PP_CAT(BOOST_PP_ITERATE_, BOOST_PP_INC(BOOST_PP_ITERATION_DEPTH()))
    #
    # define BOOST_PP_ITERATE_1 <boost/preprocessor/iteration/detail/iter/forward1.hpp>
    # define BOOST_PP_ITERATE_2 <boost/preprocessor/iteration/detail/iter/forward2.hpp>
    # define BOOST_PP_ITERATE_3 <boost/preprocessor/iteration/detail/iter/forward3.hpp>
    # define BOOST_PP_ITERATE_4 <boost/preprocessor/iteration/detail/iter/forward4.hpp>
    # define BOOST_PP_ITERATE_5 <boost/preprocessor/iteration/detail/iter/forward5.hpp>
    

可用于:

#define BOOST_PP_ITERATION_PARAMS_1 (...)
#include BOOST_PP_ITERATE()

关于c++ - 为什么我的 C/C++ header 解析器不工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32625733/

相关文章:

c++ - C/C++ 警告 : address of temporary with BDADDR_ANY Bluetooth library

c++ - 函数返回期间出现奇怪的段错误

C++ for 模板类的范围循环

c++ - 一元 * 的冲突类型错误和无效类型参数具有 int

python - 是否有与 C# 的 DateTime.TryParse() 等效的 Python?

python - 如何使用 beautifulsoup 解析来自特定站点的任何文章以及如何预览该链接的图像?

带 while 循环的 C++11 反向迭代器

c - 系统调用未定义!编译内核模块

c - C中的堆栈实现

android - 解析从 .NET Web 服务返回的 JSONArray 时出错