gpt4 book ai didi

c++ - 获取对源文件中特定函数的所有调用并生成其他文件(使用 C、C++ 预处理器或脚本)

转载 作者:太空宇宙 更新时间:2023-11-04 02:30:06 25 4
gpt4 key购买 nike

我有一个如下的程序:

// test.c
#include <stdio.h>

#define LOG printf
int main(int argc, char *argv[])
{
LOG("Hello, my name %s, my age %d\n", "John", 30);
LOG("I have wife and %d kids\n", 2);
return 0;
}

我想创建一个包含所有文本的日志文件,如:

// message.txt
LINE: "Hello, my name %s, my age %d\n"
LINE: "I have wife and %d kids\n"

是否可以使用 C 的预处理器ma​​ke,甚至是脚本来实现?


编辑:

假设我有一个程序可以用英语打印这些消息,我肯定有源代码,现在我想支持法语:
我需要获取开发人员放入其程序中的所有消息,并创建一个包含所有文本的 message.txt,将原始程序中的每条消息替换为一个标识号,该标识号映射到 message 中的每条消息。文本文件。我想以编程方式而不是手动方式进行。

最佳答案

您正在寻找的是本地化,阅读相关内容here .如果您使用的是 posix 系统,则可以为此使用 gettext(),请参阅 manpage .如果您使用的是 Windows,您可以查看 GetText for Windows .


尽管如此,我还是编写了一个 C++ 小程序来生成您想要的文件,请参见下面的代码。您可以通过 myProg filename logFunction 调用它,其中 filename 是您要输入的源文件,logFunction 例如是 LOG.

您将获得一个名为 filename_map 的 map 文件和一个新的源文件 filename_new。新的源文件将包含一个新的宏 LOG 和一个函数 readLocaleStrings(),它将在程序开始时从 filename_map 文件中读取所有字符串.新的宏 LOG 将自动使用正确的字符串。


在您的示例中,您将通过 myProg test.c LOG 调用它并获得:

test_map.txt:

7: "Hello, my name %s, my age %d\n"
8: "I have wife and %d kids\n"

和一个test_new.c:

// test.c
#include <stdio.h>

#define LOG(filename,line,...) printf(localeStrings.strings[localeStrings.lastIdx++], __VA_ARGS__)

/* Beginning: Generated code for localization */
#include <stdlib.h>
#include <string.h>

typedef struct {
size_t count;
size_t lastIdx;
char ** strings;
} stringArray_t;

stringArray_t localeStrings = { 0, 0, NULL };

int readLocaleStrings (const char * const filename)
{
FILE * file = NULL;
char * line = NULL;
char * str = NULL;
size_t len = 0;
ssize_t read;

file = fopen(filename, "r");
if (file == NULL)
{
return -1;
}

localeStrings.strings = malloc (sizeof (char *));
localeStrings.count = 0;

while (-1 != (read = getline(&line, &len, file)))
{
size_t curIdx = localeStrings.count++;
localeStrings.strings = realloc(localeStrings.strings, localeStrings.count * sizeof (char *));

str = strstr(line, "\"");
localeStrings.strings[curIdx] = malloc(sizeof (char) * (size_t)(1 + read));
strcpy (localeStrings.strings[curIdx], str);
}

fclose(file);
if (line)
{
free(line);
}

return 0;
}

void freeLocaleStrings()
{
size_t idx;
for (idx = 0; idx < localeStrings.count; ++idx)
{
free(localeStrings.strings[idx]);
}
free(localeStrings.strings);
}
/* End: Generated code for localization */

int main(int argc, char *argv[])
{
readLocaleStrings("test_map.txt");
LOG("test_map.txt", "7", "John", 30);
LOG("test_map.txt", "8", 2);
freeLocaleStrings();
return 0;
}

C++程序:

C++ 程序有局限性,它只会查找 LOG(" 如果您还想查找带空格的 LOG,例如:LOG (" 你必须更改该代码。此外,还有多行消息、已被注释掉的消息等情况。你必须根据你的要求扩展代码。也没有很好的参数解析处理或错误检查。进一步编写帮助程序代码需要找到主要功能。但是对于您给定的输入文件,它工作得很好,应该只是为您指明正确的方向。使用正则表达式库可以更轻松地扩展它并使其更灵活会很明智。

代码:

#include <iostream>
#include <fstream>

/* Function definition is under main function */
const char * getNextHelperFunctionLine();

std::string getExtension (const std::string filename)
{
/* get dot of e.g. foo.c */
size_t posDot = filename.rfind('.');

/* extract extension */
std::string extension;
if (std::string::npos != posDot)
{
/* extension found */
extension = filename.substr(posDot);
}

return extension;
}

std::string getFilename (const std::string filename)
{
/* get dot of e.g. foo.c */
size_t posDot = filename.rfind('.');

/* extract filename */
std::string name = filename;
if (std::string::npos != posDot)
{
name = name.substr(0, posDot);
}

return name;
}

int main (int argc, char* argv[])
{
if (argc < 3)
{
std::cerr << "Usage: "
<< " " << argv[0] << " filename logFunction"
<< std::endl;

return 0;
}
std::string infileName (argv[1]);

/* extract filename and extension */
std::string filename = getFilename(infileName);
std::string extension = getExtension(infileName);;

/* names for generated files */
std::string mapfileName = filename + "_map.txt";
std::string mappedfileName = filename + "_new" + extension;

/* open streams for input and output */
std::ifstream infile(infileName.c_str());
std::ofstream fileMap(mapfileName.c_str());
std::ofstream fileMapped(mappedfileName.c_str());

/* string for log function e.g. "LOG(" */
std::string logFun = std::string(argv[2]);
std::string logFunOpen = logFun + "(\"";

std::string lineRead;
size_t lineNr = 1;

size_t mainParanthesis = 0;
bool mainReturnFound = false;

/* Loop through whole input file */
while (std::getline(infile, lineRead))
{
/* position of log function opening e.g. "LOG(" */
size_t posLogOpen = lineRead.find(logFunOpen);

/* opening found? */
bool foundOpen = std::string::npos != posLogOpen;
if (foundOpen)
{
bool foundClose = false;
/* position of the string beginning */
size_t posLogStringBeg = posLogOpen + logFunOpen.length();
size_t posLogClose = posLogStringBeg;
/* find closing of the log function e.g. "LOG(...)" */
while (!foundClose)
{
/* search for '"' and skip these if they are in the string */
posLogClose = lineRead.find("\"", posLogClose + 1);
if (std::string::npos != posLogClose)
{
foundClose = (0 != lineRead.compare(posLogClose - 1, 1, "\\"));
}
}

/* closing found write map file and new source file */
if (foundClose)
{
size_t len = posLogClose - posLogStringBeg;

fileMap << lineNr << ": \""
<< lineRead.substr(posLogStringBeg, len) << "\""
<< std::endl;

fileMapped << lineRead.substr(0, posLogStringBeg - 1)
<< '"' << mapfileName << "\", "
<< '"' << lineNr
<< lineRead.substr(posLogClose)
<< std::endl;
}
}
/* not a log function write normal code */
else
{
if ( std::string::npos != lineRead.find("#define")
&& std::string::npos != lineRead.find(logFun))
{
/* log functions needs to be changed */
fileMapped << "#define "
<< logFun << "(filename,line,...) "
<< "printf(localeStrings.strings[localeStrings.lastIdx++], __VA_ARGS__)" << std::endl;
}
else if ( 0 == mainParanthesis
&& std::string::npos != lineRead.find(" main")
&& std::string::npos != lineRead.find("(")
&& std::string::npos != lineRead.find(")"))
{
/* found main function write all helper functions in front of it */
const char * helperLine;
while ((helperLine = getNextHelperFunctionLine()))
{
fileMapped << helperLine << std::endl;
}

/* write main function part */
fileMapped << lineRead << std::endl;

/* is there an opening parenthesis? */
if (std::string::npos != lineRead.find("{"))
{
++mainParanthesis;
fileMapped << " readLocaleStrings(\"" << mapfileName << "\");" << std::endl;
}
}
else
{
/* in main function write first part */
if (std::string::npos != lineRead.find("{"))
{
/* write opening */
fileMapped << lineRead << std::endl;

if (0 == mainParanthesis)
{
fileMapped << " readLocaleStrings(\"" << mapfileName << "\");" << std::endl;
}
++mainParanthesis;
}
/* return statement? */
else if ( 1 == mainParanthesis
&& std::string::npos != lineRead.find("return"))
{
mainReturnFound = true;
fileMapped << " freeLocaleStrings();" << std::endl;

/* write return */
fileMapped << lineRead << std::endl;
}
else if ( 1 == mainParanthesis
&& std::string::npos != lineRead.find("}"))
{
--mainParanthesis;
if (!mainReturnFound)
{
fileMapped << " freeLocaleStrings();" << std::endl;
}

/* write closing */
fileMapped << lineRead << std::endl;
}
else
{
/* write other code */
fileMapped << lineRead << std::endl;
}
}
}
++lineNr;
}

return 0;
}

const char * getNextHelperFunctionLine()
{
static size_t idx = 0;
static const char * helperFunLines[] =
{
"",
"/* Beginning: Generated code for localization */",
"#include <stdlib.h>",
"#include <string.h>",
"",
"typedef struct {",
" size_t count;",
" size_t lastIdx;",
" char ** strings;",
"} stringArray_t;",
"",
"stringArray_t localeStrings = { 0, 0, NULL };",
"",
"int readLocaleStrings (const char * const filename)",
"{",
" FILE * file = NULL;",
" char * line = NULL;",
" char * str = NULL;",
" size_t len = 0;",
" ssize_t read;",
"",
" file = fopen(filename, \"r\");",
" if (file == NULL)",
" {",
" return -1;",
" }",
"",
" localeStrings.strings = malloc (sizeof (char *));",
" localeStrings.count = 0;",
"",
" while (-1 != (read = getline(&line, &len, file)))",
" {",
" size_t curIdx = localeStrings.count++;",
" localeStrings.strings = realloc(localeStrings.strings, localeStrings.count * sizeof (char *));",
"",
" str = strstr(line, \"\\\"\");",
" localeStrings.strings[curIdx] = malloc(sizeof (char) * (size_t)(1 + read));",
" strcpy (localeStrings.strings[curIdx], str);",
" }",
"",
" fclose(file);",
" if (line)",
" {",
" free(line);",
" }",
"",
" return 0;",
"}",
"",
"void freeLocaleStrings()",
"{",
" size_t idx;",
" for (idx = 0; idx < localeStrings.count; ++idx)",
" {",
" free(localeStrings.strings[idx]);",
" }",
" free(localeStrings.strings);",
"}",
"/* End: Generated code for localization */",
""
};

if (idx < (sizeof (helperFunLines) / sizeof (helperFunLines[0])))
{
return helperFunLines[idx++];
}
else
{
return nullptr; /* use NULL if compiler doesn't support nullptr */
}
}

关于c++ - 获取对源文件中特定函数的所有调用并生成其他文件(使用 C、C++ 预处理器或脚本),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44588886/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com