前面我们说过了 listmake1其实是特殊的 lcons,
而lcons 函数位于 list.c 中。
00259 lcons(void *datum, List *list) 00260 { 00261 Assert(IsPointerList(list)); 00262 00263 if (list == NIL) 00264 list = new_list(T_List); 00265 else 00266 new_head_cell(list); 00267 00268 lfirst(list->head) = datum; 00269 check_list_invariants(list); 00270 return list; 00271 }
看 gram.y 中的 target_list 的定义:
target_list: target_el { $$ = list_make1($1); } | target_list ',' target_el { $$ = lappend($1, $3); } ;
listmake1($1) 就是,通过 lcons来建立一个空的List, 其head 指向 $1。
我们可以看到 ,当 lcons的第二个参数为空的时候,会执行 new_list 操作,创建一个只有头的list
00063 new_list(NodeTag type) 00064 { 00065 List *new_list; 00066 ListCell *new_head; 00067 00068 new_head = (ListCell *) palloc(sizeof(*new_head)); 00069 new_head->next = NULL; 00070 /* new_head->data is left undefined! */ 00071 00072 new_list = (List *) palloc(sizeof(*new_list)); 00073 new_list->type = type; 00074 new_list->length = 1; 00075 new_list->head = new_head; 00076 new_list->tail = new_head; 00077 00078 return new_list; 00079 }
从上面 new_list里,可以看到,它创建了一个 ListCell(虽然是空的)。
然后,new_list 的头和尾首先都指向这个 ListCell。
再然后,这个新生成的 list, 其 尾部指向 datum 。
也就是 指向了 makeNode(ResTarget)的 ResTarget类型
也就是下图:
今后,再进一步分析更复杂的情形。