学会读程序

那天在网上搜索半天,发现竟然没有对vi 这个程序源代码进行讲解的文章,于是便有空去看了看vi的源代码。主要想介绍一种思路--从宏观把握 vi的框架
vi的程序代码有3960行(包括注释),我想那么大的一个程序,一般人估计是看的会有点头晕。因为它是一个功能比较全的文本编辑器,又是纯c写的,所以可能会被它的庞大结构迷惑而不是其语法。在后面我会贴出vi.c的源码,有兴趣看看
怎么去分析这个程序呢?细节不想说,只想说说宏观的把握。这里涉及到一个重要的概念--宏#ifdef
#endif等,宏在C程序中是挺有用的一个工具,在linux下它往往用来作为控制代码跨平台的编译,在不同的平台选择不同的宏控制,去编译不同的代码,以此实现跨平台操作。大家都用过内核编译,其中的选项的可选与否,在代码中就是用到宏控制。
下面开始分析vi:
(1)
#ifdef STANDALONE
#define BB_FEATURE_VI_COLON // 4288
#define BB_FEATURE_VI_YANKMARK // 1408
#define BB_FEATURE_VI_SEARCH // 1088
#define BB_FEATURE_VI_USE_SIGNALS // 1056
#define BB_FEATURE_VI_DOT_CMD // 576
#define BB_FEATURE_VI_READONLY // 128
#define BB_FEATURE_VI_SETOPTS // 576
#define BB_FEATURE_VI_SET // 224
#define BB_FEATURE_VI_WIN_RESIZE // 256 WIN_RESIZE
#endif

vi这个程序一开始用到STANDALONE宏,对vi编辑器的标准配置进行规定
其中又定义了9个宏对应于vi的9种功能,其中包括冒号功能:,复制粘贴功能,查找功能,信号功能,逗号功能,只读功能, 选项设置功能,基本设置功能和定义初始屏幕尺寸功能。这9种功能的实现再加上vi最基本的功能的实现就形成了完整的一个vi编辑程序;是不是有点组件的味道了:),vi中通过宏实现功能的添加删除。


#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR
static int last_row; // where the cursor was last moved to
#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */
#ifdef BB_FEATURE_VI_USE_SIGNALS
static jmp_buf restart; // catch_sig()
#endif /* BB_FEATURE_VI_USE_SIGNALS */
#ifdef BB_FEATURE_VI_WIN_RESIZE
static struct winsize winsize; // remember the window size
#endif /* BB_FEATURE_VI_WIN_RESIZE */
#ifdef BB_FEATURE_VI_DOT_CMD
static int adding2q; // are we currently adding user input to q
static Byte *last_modifying_cmd; // last modifying cmd for "."
static Byte *ioq, *ioq_start; // pointer to string for get_one_char to "read"
#endif /* BB_FEATURE_VI_DOT_CMD

接下来的这段代码是通过定义的不同宏,进行不同功能的不同参数的设置初始化,如果只想实现其中一个功能,完全可以只看其中一段代码


#ifdef BB_FEATURE_VI_COLON
static void Hit_Return(void);
static Byte *get_one_address(Byte *, int *); // get colon addr, if present
static Byte *get_address(Byte *, int *, int *); // get two colon addrs, if present
static void colon(Byte *); // execute the "colon" mode cmds
#endif /* BB_FEATURE_VI_COLON */

这是有宏控制的函数的声明,在不同的功能实现不同的函数,编译器也只会编译宏控制下的函数。达到可选择的目的

static Byte *next_line(Byte *); // return pointer to next line B-o-l
static Byte *end_screen(void); // get pointer to last char on screen
static int count_lines(Byte *, Byte *); // count line from start to stop
static Byte *find_line(int); // fi

这些函数是必须要编译的,意味着是实现vc基本功能的函数

extern int vi_main(int argc, char **argv)
主函数的定义,开始对不同的宏所定义的全局变量结构进行初始化,然后进入while循环
while ((c = getopt(argc, argv, "hCR")) != -1)
通过getopt接受参数判断进入的是vi的那种模式?帮助:只读还是crashme命令 ,接下来 把程序的指挥权交给edit_file(前面还做个判断,如果没参数则打开新文件,有则打开以有文件)

static void edit_file(Byte * fn)
它接替了主函数的任务开始继续对有些变量数据初始化,其中包括初始化界面,信号,复制板等,当然这些功能也都是可选的,然后是进入循环
while (editing > 0)
这个循环中开始接受命令
#ifdef BB_FEATURE_VI_CRASHME
#ifdef BB_FEATURE_VI_YANKMARK
#ifdef BB_FEATURE_VI_DOT_CMD
然后调用do_cmd(c);开始执行,有点类似与windows的消息循环机制
执行完后进行后续操作,刷新,显示状态等
if (mysleep(0) == 0) {
// no input pending- so update output
refresh(FALSE);
show_status_line();
}
然后继续循环接受命令
直到不满足条件时退出
然后做些后续操作


然后是各个函数的定义以及实现功能。。。。。具体可以参照源代码细看,就不说了。

说了那么多,其实就是想告诉大家如何把一个大的程序(也能勉强算把)给逐步细分,然后从宏观上把握它,明白它是做什么的,大致的框架是什么。可能你具体细节会有不懂,我也是,不过没有关系,知识的学习就是慢慢一点一点的积累,但是思想一定要有。明白了就不会仅陷于学语言的泥潭了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值