initinputs函数将环境变量和include环境变量中内容(以分号或者冒号分割的字符串),进行一些字符替换后,逐项添加上“-I”后插入到 ilist。也就是建立一个include文件查询列表。
suffix:
1 int suffix(char *name, char *tails[], int n) {
2 int i, len = strlen(name);
3
4 for (i = 0; i < n; i++) {
5 char *s = tails[i], *t;
6 for ( ; t = strchr(s, ';'); s = t + 1) {
7 int m = t - s;
8 if (len > m && strncmp(&name[len-m], s, m) == 0)
9 return i;
10 }
11 if (*s) {
12 int m = strlen(s);
13 if (len > m && strncmp(&name[len-m], s, m) == 0)
14 return i;
15 }
16 }
17 return -1;
18 }
在字符串数组tails的每一个元素中,存放的是以分号分割的尾部字符串。例如前面说过的win32.c里的一个字符串数组就是这样。
char *suffixes[] = { ".c;.C", ".i;.I", ".asm;.ASM;.s;.S", ".obj;.OBJ", ".exe", 0 }; 其第一个元素是".c;.C"。代表以.c结尾或者以.C结尾的字符串都会被匹配成功。
整个函数功能就是,查找name字符串尾部是否跟tails字符串数组的前n项(0到n-1)里表示的那些尾部串匹配,如果匹配,返回对应的数组下标索引,不匹配返回-1。例如mystring.c就跟第一项匹配成功,返回0。
opt: 函数是处理命令行中各种编译选择项(编译开关)的。针对不同开关,分别添加到对预处理、编译、汇编、装入文件(库)链表,也就是前面介绍过的文件win32.c中plist、clist、alist、llist。由于lcc使用的编译开关较多,这里就不一一分析了,后面分析中若用到,再进行介绍。
exists:
1 static char *exists(char *name) {
2 List b;
3
4 if ( (name[0] == '/' || name[0] == '\\' || name[2] == ':')&& access(name, 4) == 0)
5 return name;
6 if (!(name[0] == '/' || name[0] == '\\' || name[2] == ':')&& (b = lccinputs))
7 do {
8 b = b->link;
9 if (b->str[0]) {
10 char buf[1024];
11 sprintf(buf, "%s/%s", b->str, name);
12 if (access(buf, 4) == 0)
13 return strsave(buf);
14 } else if (access(name, 4) == 0)
15 return name;
16 } while (b != lccinputs);
17 if (verbose > 1)
18 return name;
19 return 0;
20 }
这个函数是判断文件是否可读。实际上也是个文件的查找函数。如果name是带绝对路径的文件,直接测试该文件是否可读。否则,将逐个在lccinputs链表中带的目录下查找是否有可读的name这个文件。文件可读,返回带绝对路径的文件名,否则返回空串。
注意:1、access(name,4),中间的参数4是判断文件是否可读。其他参数还有0:是否存在;2:是否可写;6:是否可读写。
2、name[2]==':' ,此处怀疑是程序的一个bug。应该是name[1]==':' ,匹配象 c:\lcc\main.c 这样的文件名。
rm:
1 static void rm(List list) {
2 if (list) {
3 List b = list;
4 if (verbose)
5 fprintf(stderr, "rm");
6 do {
7 if (verbose)
8 fprintf(stderr, " %s", b->str);
9 if (verbose < 2)
10 remove(b->str);
11 } while ((b = b->link) != list);
12 if (verbose)
13 fprintf(stderr, "\n");
14 }
15 }
这又是一个简单函数,调用remove将list链表中的文件逐个删除。