我的问题似乎很简单......
问题:我有一个包含许多原型的头文件......(如示例所示)
...
// some docu...
MQ_EXTERN enum MqErrorE
MQ_DECL MqSlaveWorker (
struct MqS * const ctx,
MQ_NUM const id,
MQ_CST factory,
struct MqBufferLS ** argsP
);
...
请求:工具生成第二个头文件,其中包含"包裹"原始头文件的定义......
....
#define MqSlaveWorkerE(ctx,id,factory,argsP) \
MqErrorCheck(MqSlaveWorker(ctx,id,factory,argsP))
....
触发器是返回类型 枚举MqErrorE ... 所有使用 return-type 枚举MqErrorE 的原型应该得到一个c-preprocessor-wrapper
答案 0 :(得分:0)
您可能需要Program Transformation System (PTS)。
这些工具可以读取源代码,构建程序的内部表示,并允许您编写源代码转换,这些转换在内部表示上运行以提高效率。当您完成应用转换后,该工具会将内部表示转换回文本并吐出已转换的源代码,即使保留了注释。
除非你的头文件很简单,否则你需要一个实际上有一个完整的C解析器,并且可以准确地捕获你的源代码。否则,它将无法读取您的文件,现在您无处可去。即使这还不够;它必须保留预处理器声明,以便可以操作它们而不是在预处理期间消失。前端还有很多东西;您通常需要名称解析和各种流量分析器。
没有很多具有生产能力的PTS。我们DMS Software Reengineering Toolkit是我所知道的唯一一个(并且我已经做了很长时间的事情),它有一个完整的C Front End,可以保留预处理器命令。
您的任务核心在此DMS重写规则中进行了总结:
rule generate-wrapper(extern: macro_name, decl: macro_name, function_name: IDENTIFIER, a: arguments):
prototype_declaration)->preprocessor_declaration =
" \extern enum MqErrorE \decl \function_name ( \a ) " ->
"#define \generate_derived_macro_name\(\function_name\) (\extract_parameter_name\(\a\) ) \\
\generate_derived_checker_name\(\function_name\)( (\extract_parameter_name\(\a\) )"
其中generate_derived_macro name,generate_derived_checker_name和extract_parameter_name_list是自定义函数。 generate_derived_macro基于您的示例的名称获取其参数并粘合" E"它。提取参数名称更有意义;它必须采用参数列表的interal(AST),挑选参数名称,并从这些名称构造一个参数列表。 DMS提供了帮助您对此进行编码的机制。
还有更多的工作要做:你实际上想要构建你的错误检查函数(这个重写会这样做),然后将它们混合到一个表示单独头文件的内部表单AST。这需要额外的自定义代码,但DMS可以轻松跟踪多个表示,并可以轻松移动树木。
如果您有50个这样的声明,坦率地说,您可以更好地咬住子弹并手动完成。如果您有数千,DMS可能会为您节省大量时间。 YMMV。
答案 1 :(得分:0)
编程~3h后...解决方案是一个使用了很多的(tcl)脚本 regexp 执行以下步骤...
一个。过滤掉所有不通缉代码
湾将想要的代码转换为可用的部分
℃。将这些片段格式化为想要的 #define ... 预处理器代码
步骤1.进行转换
> ./sbin/parse_c_header.tcl
1. 221725 chars after read from 'msgque.h'
2. 221581 chars after '…\n'
2. 107796 chars after '//…$'
3. 57823 chars after '/*…*/'
4. 49701 chars after '{…}'
5. 48303 chars after '{…}'
6. 47839 chars after 'struct…XX…;'
7. 47653 chars after 'enum…XX…;'
8. 40458 chars after '#…'
9. 37707 chars after '\n'
10. 35346 chars after 'typedef…'
11. 35123 chars after 'struct…;'
12. 35053 chars after 'union…;'
13. 32820 chars after '__attribute__…;'
14. 32802 chars after 's+'
15. 32338 chars after '*'
16. 32332 chars after '[]'
17. 24076 chars after '(…,'
18. 20499 chars after ',…)'
19. 20499 chars after ',…,'
20. 17935 chars after '(…)'
21. 17979 chars after '__VA_ARGS__'
22. 17946 chars after 'XX;'
23. 17861 chars after ';'
24. 17861 chars after '…\n'
25. 17500 chars after ';\n'
write: msgqueE.h
步骤2.编写结果
//
// this file was automatically created by 'sbin/parse_c_header.tcl'
//
// : do NOT modify it
//
// this file contains error-protected api-calls of libmsgque
//
// : error-protected mean that all api-calls who return an 'enum MqErrorE'
// : get a 'MqErrorCheck' wrapper. This wrapper check for the return code
// : 'MQ_ERROR' and jump on error to a label called 'error:' to do proper
// : error handing.
//
// example: the following line of code..
//
// > MqErrorCheck ( MqReadU (ctx, &buf));
//
// can be rewritten with:
//
// > #include "msgqueE.h"
// > ...
// > MqReadUE (ctx, &buf);
//
//
#define MqConfigSetIoUdsFileE (ctx,file) MqErrorCheck(MqConfigSetIoUdsFile(ctx,file))
#define MqConfigSetIoTcpE (myhost,myport) MqErrorCheck(MqConfigSetIoTcp(myhost,myport))
#define MqConfigSetIoPipeSocketE (ctx,hdl) MqErrorCheck(MqConfigSetIoPipeSocket(ctx,hdl))
#define MqConfigSetDaemonE (ctx,pidfile) MqErrorCheck(MqConfigSetDaemon(ctx,pidfile))
#define MqFactoryDefaultCreateE (item,contextP) MqErrorCheck(MqFactoryDefaultCreate(item,contextP))
#define MqFactoryCtxSetE (ctx,item) MqErrorCheck(MqFactoryCtxSet(ctx,item))
#define MqFactoryCtxIdentSetE (ctx,ident) MqErrorCheck(MqFactoryCtxIdentSet(ctx,ident))
#define MqCheckForLeftOverArgumentsE (ctx,argvP) MqErrorCheck(MqCheckForLeftOverArguments(ctx,argvP))
#define MqStorageOpenE (ctx,storageFile) MqErrorCheck(MqStorageOpen(ctx,storageFile))
#define MqStorageCloseE (ctx) MqErrorCheck(MqStorageClose(ctx))
#define MqStorageInsertE (ctx,transLIdP) MqErrorCheck(MqStorageInsert(ctx,transLIdP))
#define MqStorageSelectE (ctx,transLIdP) MqErrorCheck(MqStorageSelect(ctx,transLIdP))
#define MqStorageDeleteE (ctx,transLId) MqErrorCheck(MqStorageDelete(ctx,transLId))
#define MqStorageCountE (ctx,countP) MqErrorCheck(MqStorageCount(ctx,countP))
#define MqLinkCreateE (ctx,args) MqErrorCheck(MqLinkCreate(ctx,args))
#define MqLinkConnectE (ctx) MqErrorCheck(MqLinkConnect(ctx))
#define MqLinkCreateChildE (parent,args) MqErrorCheck(MqLinkCreateChild(parent,args))
#define MqLinkCreateRouteE (id,argvP) MqErrorCheck(MqLinkCreateRoute(id,argvP))
#define MqLinkDefaultE (ctx,args) MqErrorCheck(MqLinkDefault(ctx,args))
#define MqLinkGetPathE (ctx,pathP) MqErrorCheck(MqLinkGetPath(ctx,pathP))
#define MqLinkGetTreeE (ctx,tree) MqErrorCheck(MqLinkGetTree(ctx,tree))
...