LEMON源码分析笔记——分割源码
2011-03-23 09:21
309 查看
LEMON源码分析笔记——分割源码
五千多行代码集于一个文件,这不是什么明智之举。根据源码中的提示,可以编程一个分割程序。
分割程序的工作是,识别出文件名,并把用它创建文件,写入相应内容。在处理过程序,记录头文件。在识别出源文件时,把在其前的头文件#include进去。理论上这样做是可行的。因为源文件所需的定义或声明一定在其前的头文件中包含了。而源文件之间没有什么瓜葛。但LEMON源代码并不是想象中的那么规范。有许多地方要改。
l
调用了其它文件的静态函数。msort.c实现的内部函数msort被action.c中调用;action.c实现的内部函数action_sort在report.c中调用。
l
调用其它源文件的静态变量。main.c中定义的内部变量int
nDefine,char** szDefine在parse.c中引用。
l
源文件中定义宏与结构体。action.c中定义了的宏acttab_size,acttab_yyaction,acttab_lookahead会在report.c中引用。action.c中还定义了acttab结构体,而此结构在report.c中需要引用。
为消除警告而采取的修改
小结:
1.
两源程序中出现同名结构体,以本文件的结构体定义为准。Extern过来的变量,其值直接覆盖在本文件结构体上。
/*file1.c*/
struct
node
{
char ch1;
char ch2;
};
struct
node n = {1, 0};
/*file2.c*/
struct
node
{
int data;
};
/*在file2.c中,n只量使用data域,其值被,0由低到高填充,故为*/
2.
只要函数在声明或定义的开头加上了static那么,它就是一个静态函数。只能够在本文件内被访问。
3.
C语言允许函数在没有声明之前就发生调用。包括库函数
void
main()
{
printf("hello world!/n");
fopen("test.data","wb");
}
但assert函数不行,因为这是一个宏
#define
assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression),
_CRT_WIDE(__FILE__),
__LINE__), 0) )
4.
头文件中通常会包含内部函数与全局函数的声明。内部函数不向外提供调用,那么为什么要包括在头文件中呢?原因是,为其所在源文件内部对其的调用,提供事先声明。头文件的内部函数声明,不是为别的源文件而声的,而是为该内部函数所在的源文件声的。当然其中的全局函数也是出于这个原因,但全局函数还得为别源文件提供事先声明。
问题是如果将这样的头文件包含在未定义其中内部函数的源文件中,结果会是怎样的呢?分四种情况:
5.
头文件不参加编译。如果头文件未被include进源文件中,编译器不会检查其语法的。
五千多行代码集于一个文件,这不是什么明智之举。根据源码中的提示,可以编程一个分割程序。
分割程序的工作是,识别出文件名,并把用它创建文件,写入相应内容。在处理过程序,记录头文件。在识别出源文件时,把在其前的头文件#include进去。理论上这样做是可行的。因为源文件所需的定义或声明一定在其前的头文件中包含了。而源文件之间没有什么瓜葛。但LEMON源代码并不是想象中的那么规范。有许多地方要改。
l
调用了其它文件的静态函数。msort.c实现的内部函数msort被action.c中调用;action.c实现的内部函数action_sort在report.c中调用。
l
调用其它源文件的静态变量。main.c中定义的内部变量int
nDefine,char** szDefine在parse.c中引用。
l
源文件中定义宏与结构体。action.c中定义了的宏acttab_size,acttab_yyaction,acttab_lookahead会在report.c中引用。action.c中还定义了acttab结构体,而此结构在report.c中需要引用。
为消除警告而采取的修改
警告 | 修改 |
buildshift中调用了没有声明的Action_add | 在action.h中添加Acion_add声明 |
Configlist中调用的msort的第三个参数与configcmp不匹配 | 强制类型转换(int (*)(const char*,const char*)) |
main 中调用的qsort的第四个参数与Symbolcmp类型不匹配 | 强制类型转换(int (__cdecl *)(const void *,const void *)) |
VSdeprecate警告 | 在global.h中添加#pragma warning(disable 4996) |
ReportTable的调用的acttab_action,acttab_alloc,acttab_insert没有事先声明 | 在acttab.h中添加声明 |
append_str中n+sizeof(zInt)*2+used >= alloced警告“signed/unsigned mismatch” | n+(int)sizeof(zInt)*2+used >= alloced |
警告NEXT宏类型转换:“'type cast' : pointer truncation from 'char *' to 'unsigned long'” | 工程属性->C/C++->常规->【检测64位可移植性问题】选否 |
1.
两源程序中出现同名结构体,以本文件的结构体定义为准。Extern过来的变量,其值直接覆盖在本文件结构体上。
/*file1.c*/
struct
node
{
char ch1;
char ch2;
};
struct
node n = {1, 0};
/*file2.c*/
struct
node
{
int data;
};
/*在file2.c中,n只量使用data域,其值被,0由低到高填充,故为*/
2.
只要函数在声明或定义的开头加上了static那么,它就是一个静态函数。只能够在本文件内被访问。
3.
C语言允许函数在没有声明之前就发生调用。包括库函数
void
main()
{
printf("hello world!/n");
fopen("test.data","wb");
}
但assert函数不行,因为这是一个宏
#define
assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression),
_CRT_WIDE(__FILE__),
__LINE__), 0) )
4.
头文件中通常会包含内部函数与全局函数的声明。内部函数不向外提供调用,那么为什么要包括在头文件中呢?原因是,为其所在源文件内部对其的调用,提供事先声明。头文件的内部函数声明,不是为别的源文件而声的,而是为该内部函数所在的源文件声的。当然其中的全局函数也是出于这个原因,但全局函数还得为别源文件提供事先声明。
问题是如果将这样的头文件包含在未定义其中内部函数的源文件中,结果会是怎样的呢?分四种情况:
调用 | 定义 | |
内部函数 | declared but not defined | ok |
全局函数 | ok | 找到一个或多个多重定义的符号 |
头文件不参加编译。如果头文件未被include进源文件中,编译器不会检查其语法的。
相关文章推荐
- LEMON源码分析笔记——状态默认动作
- LEMON源码分析笔记——压缩分析表
- Android M 启动源码分析笔记之 - Init 进程
- Pyunit源码笔记之一 典型例子,后面将分析源码
- 看书 Python 源码分析笔记 (三) dict
- 看书 Python 源码分析笔记 (六) 函数
- android hardware 简述(Android系统源码情景分析 笔记)
- quartz2源码分析(1)--学习笔记
- netty5源码分析(2)--学习笔记
- nginx 源码学习笔记(七)——内存分配相关源码分析
- MarqueeView源码简单分析笔记
- linux内核源码情景分析阅读笔记(1)
- jQuery 源码分析笔记
- TensorFlow学习笔记之源码分析(2)----手写数字识别mnist example
- zeromq源码分析笔记之线程间收发命令(2)
- jQuery 源码分析笔记(4)
- JFinal个人学习笔记之源码分析3
- 《C++ Concurrency in Action》笔记9 std::unique_lock源码分析
- Lighttpd1.4.20源码分析 笔记 状态机与插件
- LEMON源码分析——项目FOLLOW集求法