从main函数学起:
使用的数据结构:
1 typedef struct list *List;
2 struct list { /* 循环链表 */
3 char *str; /* option 或者文件名 */
4 List link; /* next list element */
5 };
6
7 static List llist[2]; /* loader files, flags */
8 static List alist; /* assembler flags */
9 static List clist; /* compiler flags */
10 static List plist; /* preprocessor flags */
11 static List ilist; /* 环境变量LCCINPUTS定义的includes目录 */
12 static List rmlist; /* list of files to remove */
13
14
15 static List lccinputs; /* list of input directories */
main函数的调用关系:
win32.c只是为了处理windows和linux之间可移植性做的一个替换。
其中重要的数据和数据结构 :
#define LCCDIR "\\progra~1\\lcc\\4.1\\bin\\"
char *suffixes[] = { ".c;.C", ".i;.I", ".asm;.ASM;.s;.S", ".obj;.OBJ", ".exe", 0 };
char *cpp[] = { LCCDIR "cpp", "-D__STDC__=1", "-Dwin32", "-D_WIN32", "-D_M_IX86","$1", "$2", "$3", 0 };
char *include[] = { "-I" LCCDIR "include", 0 };
char *com[] = { LCCDIR "rcc", "-target=x86/win32", "$1", "$2", "$3", 0 };
char *as[] = { "ml", "-nologo", "-c", "-Cp", "-coff", "-Fo$3", "$1", "$2", 0 };
char *ld[] = { "link", "-nologo", "", "-subsystem:console", "-entry:mainCRTStartup","$2", "-OUT:$3", "$1", LCCDIR "liblcc.lib", "oldnames.lib", "libc.lib", "kernel32.lib", 0 };
win32.c里只有一个函数int option(char *arg),用来处理路径名。也就是根据环境设置变量设置(lcc安装位置),将程序调用的查找位置设置好(LCCDIR)。
现在来看main.c中各个函数功能。
alloc:
1 static void *alloc(int n) {
2 static char *avail, *limit;
3
4 n = (n + sizeof(char *) - 1)&~(sizeof(char *) - 1);
5 if (n >= limit - avail) {
6 avail = malloc(n + 4*1024);
7 assert(avail);
8 limit = avail + n + 4*1024;
9 }
10 avail += n;
11 return avail - n;
12 }
这是个分配空间的函数。其中有几点需要注意。
1、第4行,实际分配的是一个大于等于传进来参数的空间。而且是一个对齐char*大小的空间。32位机器上,char*是4字节的。空间按照4字节对齐。
2、空间管理也很有趣,不是每次分配向系统申请空间,而是先检查现行空间是不是够分配,够分配,就直接在现行空间中分配,通过第10行,移动avail指针完成。不够分配向系统重新申请空间。每次向系统申请时,多申请4K空间。申请后avail指向新申请空间,用limit指向空间的最后作为界限。
3、这样管理空间,一方面,对于经常需要动态申请小量空间情况,提高了空间分配效率,减少了系统空间碎片。但另一方面,对于申请来的每一块空间末尾,会频繁出现浪费。极端情况是每当需要申请大于4K空间时,都需要重新向系统申请。原来申请的那块空间未使用部分就浪费了。
append:
1 static List append(char *str, List list) {
2 List p = alloc(sizeof *p);
3
4 p->str = str;
5 if (list) {
6 p->link = list->link;
7 list->link = p;
8 } else
9 p->link = p;
10 return p;
11 }
这个是个简单的链表添加节点函数。生成包含参数str内容的节点,参数list指定链表为空,节点的link指向自身,否则,节点插入到list里。返回List p。
这个函数是要被反复使用的函数,main.c中使用的数据结构里,多个链表都是用这个函数建立起来的。