Revision | bd1c5672f1056ee58cfe3398d115efaaa21311de (tree) |
---|---|
Time | 2020-02-11 23:34:25 |
Author | dhrname <dhrname@user...> |
Commiter | dhrname |
Modulize orderedpair
@@ -2,8 +2,8 @@ CC = gcc | ||
2 | 2 | DEBUGMODE = -Wall -std=c11 -O0 -g -pg |
3 | 3 | NODEBUGMODE = -Wall -std=c11 -O2 |
4 | 4 | SHELL = /bin/sh |
5 | -HEADERS = shadowstar.h star.h orderedpair/pair.h orderedpair/list/item.h orderedpair/list/tree/btree.h orderedpair/list/tree/nodelist/ntree.h orderedpair/list/tree/nodelist/class/class.h | |
6 | -OBJECT = shadowstar.o exception.o | |
5 | +HEADERS = shadowstar.h star.h orderedpair/list/tree/nodelist/class/class.h | |
6 | +OBJECT = shadowstar.o exception.o pair.o item.o ntree.o | |
7 | 7 | |
8 | 8 | all : startest star |
9 | 9 | .PHONY : all |
@@ -13,6 +13,12 @@ all : startest star | ||
13 | 13 | |
14 | 14 | exception.o: orderedpair/exception.h |
15 | 15 | |
16 | +pair.o: orderedpair/pair.h | |
17 | + | |
18 | +item.o: orderedpair/list/item.h | |
19 | + | |
20 | +ntree.o: orderedpair/list/tree/nodelist/ntree.h | |
21 | + | |
16 | 22 | star.o: $(HEADERS) |
17 | 23 | |
18 | 24 | shadowstar.o: $(HEADERS) |
@@ -24,4 +30,4 @@ startest: startest.o $(OBJECT) | ||
24 | 30 | $(CC) $(NODEBUGMODE) -o ../$@ startest.o $(OBJECT) |
25 | 31 | |
26 | 32 | clean: |
27 | - rm -f shadowstar.o startest.o star.o exception.o | |
33 | + rm -f startest.o star.o $(OBJECT) |
@@ -0,0 +1,30 @@ | ||
1 | +/* | |
2 | + * item.c | |
3 | + * | |
4 | + * Copyright (C) 2017 dhrname <dhrnamesie@joestar.sakura.ne.jp> | |
5 | + * | |
6 | + * | |
7 | + */ | |
8 | +#include "shadowstar.h" | |
9 | + | |
10 | +/*item.cでは、リストの項目を取得するための関数を実装する*/ | |
11 | + | |
12 | +/*ST_setChurchNumber 関数 | |
13 | + * C言語でラムダ計算のchurch数を部分的に再現するための関数*/ | |
14 | +ST_Ordered_Pair *ST_setChurchNumber (uint_fast32_t length, Ord2ST_Ordered_Pair f, ST_Ordered_Pair *list) | |
15 | +{ | |
16 | + int32_t i; | |
17 | + for (i = 0; i < length; i++) | |
18 | + { | |
19 | + /*lengthが4の場合、list = f(f(f(f(list))));*/ | |
20 | + list = (*f)(list); | |
21 | + } | |
22 | + return list; | |
23 | +} | |
24 | + | |
25 | +/*ST_getItem 関数 | |
26 | + * 入力されたリストの最後からnum番目にある項目の最初の値を取り出す(num >= 0)*/ | |
27 | +ST_First_Type ST_getItem (ST_Ordered_Pair *list, uint_fast32_t num) | |
28 | +{ | |
29 | + return ST_first( ST_setChurchNumber(num, ST_second, list) ); | |
30 | +} |
@@ -0,0 +1,395 @@ | ||
1 | +/* | |
2 | + * ntree.c | |
3 | + * | |
4 | + * Copyright (C) 2017 dhrname <dhrnamesie@joestar.sakura.ne.jp> | |
5 | + * | |
6 | + * | |
7 | + */ | |
8 | +#include "shadowstar.h" | |
9 | + | |
10 | +/*N木(N tree)構造*/ | |
11 | + | |
12 | +/*以下では、複数の枝分かれができるN木構造を実装する*/ | |
13 | + | |
14 | +/*ST_getBoundVariable 関数 | |
15 | + * 二分木リストとして表現された関数抽象abstractionの束縛変数(Bound Variable)を数値化したものを取得する | |
16 | + * ここでいう束縛変数とは、λx.Mのときの、変数xを指す*/ | |
17 | +ST_First_Type ST_getBoundVariable (ST_Ordered_Pair *abstraction) | |
18 | +{ | |
19 | + return ST_first(abstraction); | |
20 | +} | |
21 | + | |
22 | + | |
23 | +/*空ノードを表現するポインタ*/ | |
24 | +ST_Node_Tree __ST_EMPTY_NODE = { | |
25 | + NULL, | |
26 | + ST_UNKNOWN_NODE, | |
27 | + NULL, | |
28 | + NULL, | |
29 | + NULL, | |
30 | + NULL, | |
31 | + NULL | |
32 | +}; | |
33 | +ST_Node ST_EMPTY_NODE = &__ST_EMPTY_NODE; | |
34 | + | |
35 | +/*ST_isEmptyNode 関数 | |
36 | + * 引数の値がST_EMPTY_NODEであるかどうかを判別する関数*/ | |
37 | +bool ST_isEmptyNode (ST_Node node) | |
38 | +{ | |
39 | + if (node == ST_EMPTY_NODE) | |
40 | + { | |
41 | + return true; | |
42 | + } | |
43 | + else if (NULL == node) | |
44 | + { | |
45 | + errno = EINVAL; | |
46 | + eprint_log("NULL argument error on the function ST_isEmptyNode:"); | |
47 | + return false; | |
48 | + } | |
49 | + else | |
50 | + { | |
51 | + return false; | |
52 | + } | |
53 | +} | |
54 | + | |
55 | +/*check_null インライン関数 | |
56 | + * ノードでNULLチェックを行う*/ | |
57 | +static inline bool check_null (ST_Node node) | |
58 | +{ | |
59 | + if (NULL == node) | |
60 | + { | |
61 | + errno = EINVAL; | |
62 | + eprint_log("NULL argument error:"); | |
63 | + return true; | |
64 | + } | |
65 | + else | |
66 | + { | |
67 | + return false; | |
68 | + } | |
69 | +} | |
70 | + | |
71 | +/*ST_createNode 関数 | |
72 | + * 引数はフリーリスト用のノード(子ノードは後述するST_freenode 関数でルートノードとして扱われる) | |
73 | + * 返り値が新たに作られるノード*/ | |
74 | +ST_Node ST_createNode(ST_Free_Node freelist) | |
75 | +{ | |
76 | + errno_before_eprint = CREATE_NODE_ERROR; | |
77 | + | |
78 | + if (check_null(freelist)) | |
79 | + { | |
80 | + return ST_EMPTY_NODE; | |
81 | + } | |
82 | + | |
83 | + ST_Node s; | |
84 | + | |
85 | + s = (ST_Node) ST_emalloc(sizeof(ST_Node_Tree)); | |
86 | + s->nodeValue = ST_EMPTY; | |
87 | + s->lastChild = ST_EMPTY_NODE; | |
88 | + s->previousSibling = ST_EMPTY_NODE; | |
89 | + s->nextSibling = ST_EMPTY_NODE; | |
90 | + s->parentNode = ST_EMPTY_NODE; | |
91 | + s->nodeType = ST_UNKNOWN_NODE; | |
92 | + | |
93 | + if (!ST_isEmptyNode(freelist)) | |
94 | + { | |
95 | + /*freelistに、メモリ解放用ルートノードとして追加挿入*/ | |
96 | + ST_Node lastChild = ST_getLastChild(freelist); | |
97 | + s->previousSibling = lastChild; | |
98 | + lastChild->nextSibling = s; | |
99 | + freelist->lastChild = s; | |
100 | + s->parentNode = freelist; | |
101 | + } | |
102 | + | |
103 | + errno_before_eprint = Init_errno_before_eprint; | |
104 | + | |
105 | + return s; | |
106 | +} | |
107 | + | |
108 | +/*ST_setNodeValue 関数 | |
109 | + * 引数にノードの値をセットする*/ | |
110 | +void ST_setNodeValue(ST_Node node, ST_Ordered_Pair *nodeValue) | |
111 | +{ | |
112 | + if (NULL == nodeValue) | |
113 | + { | |
114 | + errno = EINVAL; | |
115 | + eprint_log("argument error on the function ST_setNodeValue:"); | |
116 | + return; | |
117 | + } | |
118 | + node->nodeValue = nodeValue; | |
119 | +} | |
120 | + | |
121 | +/*ST_removeChild 関数 | |
122 | + * 一番目の引数を親ノードparentとして、二番目の引数である子ノードchildをparentから引き離す | |
123 | + * 返り値はchild、ただし、エラーの時はST_EMPTY_NODE*/ | |
124 | +ST_Node ST_removeChild(ST_Node parent, ST_Node child) | |
125 | +{ | |
126 | + errno_before_eprint = REMOVE_CHILD_ERROR; | |
127 | + | |
128 | + /*エラーのパターンとしては、 | |
129 | + * parentか、nodeの値がNULL、あるいはST_EMPTY_NODEのとき*/ | |
130 | + | |
131 | + if ( (NULL == parent) || ST_isEmptyNode(parent)) | |
132 | + { | |
133 | + errno = EINVAL; | |
134 | + eprint_log("ST_EMPTY_NODE parent argument error on the function ST_removeChild:"); | |
135 | + return ST_EMPTY_NODE; | |
136 | + } | |
137 | + | |
138 | + if ( (NULL == child) || ST_isEmptyNode(child)) | |
139 | + { | |
140 | + errno = EINVAL; | |
141 | + eprint_log("ST_EMPTY_NODE argument error on the function ST_removeChild:"); | |
142 | + return ST_EMPTY_NODE; | |
143 | + } | |
144 | + | |
145 | + child->parentNode = ST_EMPTY_NODE; | |
146 | + | |
147 | + /*nodeが抜けた後、隣接ノードに関するメンバは書き換えておく*/ | |
148 | + if (!ST_isEmptyNode(child->previousSibling)) | |
149 | + { | |
150 | + child->previousSibling->nextSibling = child->nextSibling; | |
151 | + } | |
152 | + if (!ST_isEmptyNode(child->nextSibling)) | |
153 | + { | |
154 | + child->nextSibling->previousSibling = child->previousSibling; | |
155 | + } | |
156 | + | |
157 | + if (ST_getLastChild(parent) == child) | |
158 | + { | |
159 | + /*末尾ノードがnodeである場合はparentノードのメンバを書きかえておく*/ | |
160 | + parent->lastChild = ST_getPreviousNode(child); | |
161 | + } | |
162 | + | |
163 | + child->nextSibling = ST_EMPTY_NODE; | |
164 | + child->previousSibling = ST_EMPTY_NODE; | |
165 | + | |
166 | + errno_before_eprint = Init_errno_before_eprint; | |
167 | + | |
168 | + return child; | |
169 | +} | |
170 | + | |
171 | +/*ST_insertBefore 関数 | |
172 | + * 副作用がある関数なので、扱いには注意を要する | |
173 | + * 一番目の引数parentが親ノード。三番目の引数ノードprevの前隣りに、二番目の引数ノードnodeを挿入 | |
174 | + * 三番目の引数が空ノードであれば、親ノードに末子ノードとして登録される | |
175 | + * 返り値は、挿入に成功したとき引数node、失敗したときは空ノードを返す*/ | |
176 | +ST_Node ST_insertBefore(ST_Node parent, ST_Node node, ST_Node prev) | |
177 | +{ | |
178 | + errno_before_eprint = INSERT_BEFORE_ERROR; | |
179 | + | |
180 | + /*挿入に失敗するパターンとしては、 | |
181 | + * parentか、nodeの値がNULL、あるいはST_EMPTY_NODEのとき*/ | |
182 | + if ( (NULL == parent) || ST_isEmptyNode(parent)) | |
183 | + { | |
184 | + errno = EINVAL; | |
185 | + eprint_log("ST_EMPTY_NODE parent argument error on the function ST_insertBefore:"); | |
186 | + return ST_EMPTY_NODE; | |
187 | + } | |
188 | + | |
189 | + if ( (NULL == node) || ST_isEmptyNode(node)) | |
190 | + { | |
191 | + errno = EINVAL; | |
192 | + eprint_log("ST_EMPTY_NODE argument error on the function ST_insertBefore:"); | |
193 | + return ST_EMPTY_NODE; | |
194 | + } | |
195 | + | |
196 | + /*祖先ノードの中に、今挿入しつつあるnodeと一致するものがあれば、参照エラー | |
197 | + * というのは、循環参照を引き起こすため*/ | |
198 | + ST_Node p = parent; | |
199 | + | |
200 | + while (!ST_isEmptyNode(p)) | |
201 | + { | |
202 | + if (p == node) | |
203 | + { | |
204 | + eprint_log("Reference error on the function ST_insertBefore:"); | |
205 | + return ST_EMPTY_NODE; | |
206 | + } | |
207 | + | |
208 | + p = ST_getParentNode(p); | |
209 | + } | |
210 | + | |
211 | + ST_Node pnode = ST_getParentNode(node); | |
212 | + | |
213 | + if (!ST_isEmptyNode(pnode)) | |
214 | + { | |
215 | + /*nodeがすでに、他の枝に挿入されていた場合*/ | |
216 | + ST_removeChild(pnode, node); | |
217 | + } | |
218 | + | |
219 | + node->parentNode = parent; | |
220 | + | |
221 | + if (ST_isEmptyNode(prev)) | |
222 | + { | |
223 | + /*末尾ノードが存在するときは、そのノードのメンバも書きかえておく*/ | |
224 | + ST_Node lastChild = ST_getLastChild(parent); | |
225 | + if (!ST_isEmptyNode(lastChild)) | |
226 | + { | |
227 | + lastChild->nextSibling = node; | |
228 | + node->previousSibling = lastChild; | |
229 | + } | |
230 | + /*末尾ノードとして挿入*/ | |
231 | + parent->lastChild = node; | |
232 | + } | |
233 | + else if (NULL != prev) | |
234 | + { | |
235 | + ST_Node prevOfPrev = prev->previousSibling; | |
236 | + if (!ST_isEmptyNode(prevOfPrev)) | |
237 | + { | |
238 | + /*prevの隣接ノードのnextSiblingメンバを書きかえておく*/ | |
239 | + prevOfPrev->nextSibling = node; | |
240 | + } | |
241 | + node->previousSibling = prevOfPrev; | |
242 | + prev->previousSibling = node; | |
243 | + node->nextSibling = prev; | |
244 | + } | |
245 | + | |
246 | + errno_before_eprint = Init_errno_before_eprint; | |
247 | + | |
248 | + return node; | |
249 | +} | |
250 | + | |
251 | +/*ST_getNodeValue 関数 | |
252 | + * 引数で指定されたノードの値を取得*/ | |
253 | +ST_Ordered_Pair *ST_getNodeValue(ST_Node node) | |
254 | +{ | |
255 | + errno_before_eprint = GET_NODE_VALUE_ERROR; | |
256 | + | |
257 | + if (check_null(node)) | |
258 | + { | |
259 | + return ST_EMPTY; | |
260 | + } | |
261 | + | |
262 | + if (ST_isEmptyNode(node) || (NULL == node->nodeValue)) | |
263 | + { | |
264 | + return ST_EMPTY; | |
265 | + } | |
266 | + | |
267 | + errno_before_eprint = Init_errno_before_eprint; | |
268 | + | |
269 | + return node->nodeValue; | |
270 | +} | |
271 | + | |
272 | +/*ST_getLastChild 関数 | |
273 | + * 引数で指定されたノードの子リストの最後尾を取得*/ | |
274 | +ST_Node ST_getLastChild(ST_Node node) | |
275 | +{ | |
276 | + errno_before_eprint = GET_LAST_CHILD_ERROR; | |
277 | + | |
278 | + if (check_null(node)) | |
279 | + { | |
280 | + return ST_EMPTY_NODE; | |
281 | + } | |
282 | + | |
283 | + if (ST_isEmptyNode(node) || (NULL == node->lastChild)) | |
284 | + { | |
285 | + return node; | |
286 | + } | |
287 | + | |
288 | + errno_before_eprint = Init_errno_before_eprint; | |
289 | + | |
290 | + return node->lastChild; | |
291 | +} | |
292 | + | |
293 | +/*ST_getPreviousNode 関数 | |
294 | + * 引数で指定されたノードにとって、前隣りのノードを取得*/ | |
295 | +ST_Node ST_getPreviousNode(ST_Node node) | |
296 | +{ | |
297 | + errno_before_eprint = GET_PREVIOUS_NODE_ERROR; | |
298 | + | |
299 | + if (check_null(node)) | |
300 | + { | |
301 | + return ST_EMPTY_NODE; | |
302 | + } | |
303 | + | |
304 | + if (ST_isEmptyNode(node) || (NULL == node->previousSibling)) | |
305 | + { | |
306 | + return node; | |
307 | + } | |
308 | + | |
309 | + errno_before_eprint = Init_errno_before_eprint; | |
310 | + | |
311 | + return node->previousSibling; | |
312 | +} | |
313 | + | |
314 | +/*ST_getParentNode 関数 | |
315 | + * 引数の親ノードを取得*/ | |
316 | +ST_Node ST_getParentNode(ST_Node node) | |
317 | +{ | |
318 | + errno_before_eprint = GET_PARENT_NODE_ERROR; | |
319 | + | |
320 | + if (check_null(node)) | |
321 | + { | |
322 | + errno_before_eprint = Init_errno_before_eprint; | |
323 | + return ST_EMPTY_NODE; | |
324 | + } | |
325 | + | |
326 | + if (ST_isEmptyNode(node) || (NULL == node->parentNode)) | |
327 | + { | |
328 | + errno_before_eprint = Init_errno_before_eprint; | |
329 | + return ST_EMPTY_NODE; | |
330 | + } | |
331 | + | |
332 | + errno_before_eprint = Init_errno_before_eprint; | |
333 | + | |
334 | + return node->parentNode; | |
335 | +} | |
336 | + | |
337 | +/*ST_copyNode 関数 | |
338 | + * 二番目の引数で指定されたノードのコピーを作成して、返す | |
339 | + * 子ノードも含めて深くコピーするが、隣接ノードはコピーしない | |
340 | + * 一番目の引数はST_freenodeで使うためのフリーリスト*/ | |
341 | +ST_Node ST_copyNode(ST_Free_Node freelist, ST_Node node) | |
342 | +{ | |
343 | + errno_before_eprint = COPY_NODE_ERROR; | |
344 | + | |
345 | + if ((NULL == node) || ST_isEmptyNode(node)) | |
346 | + { | |
347 | + /*nodeが無効値、NULLである場合はエラー | |
348 | + *ST_EMPTY_NODEを返す*/ | |
349 | + errno = EINVAL; | |
350 | + eprint_log("Argument error on the function ST_copyNode:"); | |
351 | + return ST_EMPTY_NODE; | |
352 | + } | |
353 | + | |
354 | + ST_Node copy = ST_createNode(freelist); | |
355 | + ST_setNodeValue(copy, ST_getNodeValue(node)); | |
356 | + copy->nodeType = node->nodeType; | |
357 | + | |
358 | + /*コピーしたい子ノードにおける現在のノード*/ | |
359 | + ST_Node current = ST_EMPTY_NODE; | |
360 | + /*コピーしたい子ノード*/ | |
361 | + ST_Node child = ST_getLastChild(node); | |
362 | + /*nodeの子ノードを次々とコピーしていく*/ | |
363 | + while (!ST_isEmptyNode(child)) | |
364 | + { | |
365 | + /*currentにはST_copyNode(child)の値が代入される*/ | |
366 | + current = ST_insertBefore(copy, ST_copyNode(ST_EMPTY_NODE, child), current); | |
367 | + child = ST_getPreviousNode(child); | |
368 | + } | |
369 | + | |
370 | + errno_before_eprint = Init_errno_before_eprint; | |
371 | + | |
372 | + return copy; | |
373 | +} | |
374 | + | |
375 | +/*ST_freenode 関数 | |
376 | + * 引数freelistに登録されたノードを、子ノードも含めて、全て深く解放していく | |
377 | + * その際、ノード値そのものも解放する*/ | |
378 | +void ST_freenode (ST_Free_Node freelist) | |
379 | +{ | |
380 | + if ( (NULL == freelist) || ST_isEmptyNode(freelist)) | |
381 | + { | |
382 | + return; | |
383 | + } | |
384 | + | |
385 | + ST_Node prev = ST_getLastChild(freelist); | |
386 | + | |
387 | + while (!ST_isEmptyNode(prev)) | |
388 | + { | |
389 | + ST_Node node = prev; | |
390 | + prev = ST_getPreviousNode(node); | |
391 | + ST_freenode(node); | |
392 | + } | |
393 | + free(freelist); | |
394 | + freelist = NULL; | |
395 | +} |
@@ -0,0 +1,156 @@ | ||
1 | +/* | |
2 | + * exception.c | |
3 | + * | |
4 | + * Copyright (C) 2017 dhrname <dhrnamesie@joestar.sakura.ne.jp> | |
5 | + * | |
6 | + * | |
7 | + */ | |
8 | +#include "shadowstar.h" | |
9 | + | |
10 | +/*以下の連結リスト構造については数学の集合とラムダ計算と操作的意味論を参照のこと | |
11 | + * 集合モデル ( | |
12 | + * ここでは、:=を定義とする(任意の対象a, b, cに対して常に成立する) | |
13 | + * 空集合 := {} | |
14 | + * 対、あるいはNo Ordered Pair := {a, b} | |
15 | + * 集合の性質として{a, b} = {b, a} | |
16 | + * 順序対 あるいは、Ordered Pair := (a, b)とおいて、 | |
17 | + * (a, b) := {a, {a, b}} | |
18 | + * 順序対の定義より、 | |
19 | + * (a, b) ≠ (b, a) | |
20 | + * n項組 あるいは、n組、n-tupples := [a, b, c, ... ]とすると、 | |
21 | + * [a, b, c] := (a, ( b, (c, {}) ) )で表せる | |
22 | + * | |
23 | + * isEmpty(a) 引数aが空集合であれば、true、そうでなければ、false | |
24 | + * pair(a, b) 順序対(a, b)を作成 | |
25 | + * first(c) cが順序対(a, b)ならば、そのうち、aを返す | |
26 | + * second(c) cが順序対(a, b)ならば、そのうち、bを返す | |
27 | + * pair(a, pair(b, pair(c, 空集合)は連結リストとなる*/ | |
28 | + | |
29 | +/*ST_EMPTY | |
30 | + * 空リストを表現する構造体のconstポインタ | |
31 | + * クロージャのある他の言語では、関数で実装する*/ | |
32 | + | |
33 | +/*構造体__ST_EMPTYを作っておく*/ | |
34 | +ST_Ordered_Pair __STEMPTY = { | |
35 | + 0.0, | |
36 | + NULL, | |
37 | + 0 | |
38 | +}; | |
39 | + | |
40 | +/*ST_EMPTY | |
41 | + * 空リストを表現する構造体のポインタ | |
42 | + * クロージャのある他の言語では、関数で実装する*/ | |
43 | +ST_Ordered_Pair *ST_EMPTY = &__STEMPTY; | |
44 | + | |
45 | +/*ST_isEmpty 関数 | |
46 | + * 引数のlistがST_EMPTYかどうかをチェックするときに使う。ST_EMPTYならばtrue( = 1) | |
47 | + * NULLは不具合が起きるので、入力すればエラーを報告してtrueを返す*/ | |
48 | +bool ST_isEmpty (ST_Ordered_Pair *list) | |
49 | +{ | |
50 | + if (NULL == list) | |
51 | + { | |
52 | + errno = EINVAL; | |
53 | + eprint_log("NULL argument error on the function ST_isEmpty:"); | |
54 | + return true; | |
55 | + } | |
56 | + else if (list == ST_EMPTY) | |
57 | + { | |
58 | + return true; | |
59 | + } | |
60 | + else | |
61 | + { | |
62 | + return false; | |
63 | + } | |
64 | +} | |
65 | + | |
66 | +/*ST_first 関数 | |
67 | + * 順序対の一番目を返す | |
68 | + * ST_pair関数で指定された第一引数(例えば、ST_pair(a,b)ならばa)を返す)*/ | |
69 | +ST_First_Type ST_first (ST_Ordered_Pair *list) | |
70 | +{ | |
71 | + if (ST_isEmpty(list)) | |
72 | + { | |
73 | + return 0.0; | |
74 | + } else | |
75 | + { | |
76 | + return list->first; | |
77 | + } | |
78 | +} | |
79 | + | |
80 | +/*ST_second 関数 | |
81 | + * 順序対の二番目を返す | |
82 | + * ST_pair関数で指定された第二引数(例えば、ST_pair(a,b)ならばb)を返す)*/ | |
83 | +ST_Ordered_Pair *ST_second (ST_Ordered_Pair *list) | |
84 | +{ | |
85 | + if ( ST_isEmpty(list) || (list->second == NULL) ) | |
86 | + { | |
87 | + /*ペアの二番目を取得できない場合は、自分自身を返す*/ | |
88 | + return ST_EMPTY; | |
89 | + } | |
90 | + else | |
91 | + { | |
92 | + return list->second; | |
93 | + } | |
94 | +} | |
95 | + | |
96 | +/*メモリ割り当てを呼び出す関数 | |
97 | + * 引数nはメモリのサイズ*/ | |
98 | +void *ST_emalloc(size_t n) | |
99 | +{ | |
100 | + void *p; | |
101 | + p = calloc(1, n); | |
102 | + if (p == NULL) | |
103 | + { | |
104 | + errno = ENOBUFS; | |
105 | + eprintf("%u bytes failed on the function ST_emalloc:", n); | |
106 | + } | |
107 | + return p; | |
108 | +} | |
109 | + | |
110 | +/*ST_freelist関数 | |
111 | + * 引数のlistを解放させる | |
112 | + * 他から参照されていない限り、ST_EMPTY以外のリストすべてが対象*/ | |
113 | +void ST_freelist (ST_Ordered_Pair *list) | |
114 | +{ | |
115 | + if (ST_isEmpty(list)) | |
116 | + { | |
117 | + return; | |
118 | + } | |
119 | + | |
120 | + ST_Ordered_Pair *next; | |
121 | + | |
122 | + for (;!ST_isEmpty(list) || (list->lifepoint >= 1);list = next) | |
123 | + { | |
124 | + next = ST_second(list); | |
125 | + if (ST_isEmpty(next)) | |
126 | + { | |
127 | + break; | |
128 | + } | |
129 | + else | |
130 | + { | |
131 | + free(list); | |
132 | + /*参照カウンタを減らしておく*/ | |
133 | + next->lifepoint--; | |
134 | + list = NULL; | |
135 | + } | |
136 | + } | |
137 | +} | |
138 | + | |
139 | +/*ST_pair関数 | |
140 | + * 第一引数と第二引数とで順序対を作る*/ | |
141 | +ST_Ordered_Pair *ST_pair (ST_First_Type n, ST_Ordered_Pair *p) | |
142 | +{ | |
143 | + ST_Ordered_Pair *s; | |
144 | + | |
145 | + s = (ST_Ordered_Pair *) ST_emalloc(sizeof(ST_Ordered_Pair)); | |
146 | + s->first = n; | |
147 | + s->second = p; | |
148 | + s->lifepoint = 0; | |
149 | + | |
150 | + if (!ST_isEmpty(p)) | |
151 | + { | |
152 | + p->lifepoint++; | |
153 | + } | |
154 | + return s; | |
155 | +} | |
156 | + |
@@ -671,556 +671,10 @@ ST_Node ST_eval(ST_Ordered_Pair *list, ST_Node blist) | ||
671 | 671 | return ST_copyNode(ST_EMPTY_NODE, blist); |
672 | 672 | } |
673 | 673 | |
674 | -/*以下の連結リスト構造については数学の集合とラムダ計算と操作的意味論を参照のこと | |
675 | - * 集合モデル ( | |
676 | - * ここでは、:=を定義とする(任意の対象a, b, cに対して常に成立する) | |
677 | - * 空集合 := {} | |
678 | - * 対、あるいはNo Ordered Pair := {a, b} | |
679 | - * 集合の性質として{a, b} = {b, a} | |
680 | - * 順序対 あるいは、Ordered Pair := (a, b)とおいて、 | |
681 | - * (a, b) := {a, {a, b}} | |
682 | - * 順序対の定義より、 | |
683 | - * (a, b) ≠ (b, a) | |
684 | - * n項組 あるいは、n組、n-tupples := [a, b, c, ... ]とすると、 | |
685 | - * [a, b, c] := (a, ( b, (c, {}) ) )で表せる | |
686 | - * | |
687 | - * isEmpty(a) 引数aが空集合であれば、true、そうでなければ、false | |
688 | - * pair(a, b) 順序対(a, b)を作成 | |
689 | - * first(c) cが順序対(a, b)ならば、そのうち、aを返す | |
690 | - * second(c) cが順序対(a, b)ならば、そのうち、bを返す | |
691 | - * pair(a, pair(b, pair(c, 空集合)は連結リストとなる*/ | |
692 | 674 | |
693 | -/*ST_EMPTY | |
694 | - * 空リストを表現する構造体のconstポインタ | |
695 | - * クロージャのある他の言語では、関数で実装する*/ | |
696 | 675 | |
697 | -/*構造体__ST_EMPTYを作っておく*/ | |
698 | -ST_Ordered_Pair __STEMPTY = { | |
699 | - 0.0, | |
700 | - NULL, | |
701 | - 0 | |
702 | -}; | |
703 | - | |
704 | -/*ST_EMPTY | |
705 | - * 空リストを表現する構造体のポインタ | |
706 | - * クロージャのある他の言語では、関数で実装する*/ | |
707 | -ST_Ordered_Pair *ST_EMPTY = &__STEMPTY; | |
708 | - | |
709 | -/*ST_isEmpty 関数 | |
710 | - * 引数のlistがST_EMPTYかどうかをチェックするときに使う。ST_EMPTYならばtrue( = 1) | |
711 | - * NULLは不具合が起きるので、入力すればエラーを報告してtrueを返す*/ | |
712 | -bool ST_isEmpty (ST_Ordered_Pair *list) | |
713 | -{ | |
714 | - if (NULL == list) | |
715 | - { | |
716 | - errno = EINVAL; | |
717 | - eprint_log("NULL argument error on the function ST_isEmpty:"); | |
718 | - return true; | |
719 | - } | |
720 | - else if (list == ST_EMPTY) | |
721 | - { | |
722 | - return true; | |
723 | - } | |
724 | - else | |
725 | - { | |
726 | - return false; | |
727 | - } | |
728 | -} | |
729 | - | |
730 | -/*ST_first 関数 | |
731 | - * 順序対の一番目を返す | |
732 | - * ST_pair関数で指定された第一引数(例えば、ST_pair(a,b)ならばa)を返す)*/ | |
733 | -ST_First_Type ST_first (ST_Ordered_Pair *list) | |
734 | -{ | |
735 | - if (ST_isEmpty(list)) | |
736 | - { | |
737 | - return 0.0; | |
738 | - } else | |
739 | - { | |
740 | - return list->first; | |
741 | - } | |
742 | -} | |
743 | - | |
744 | -/*ST_second 関数 | |
745 | - * 順序対の二番目を返す | |
746 | - * ST_pair関数で指定された第二引数(例えば、ST_pair(a,b)ならばb)を返す)*/ | |
747 | -ST_Ordered_Pair *ST_second (ST_Ordered_Pair *list) | |
748 | -{ | |
749 | - if ( ST_isEmpty(list) || (list->second == NULL) ) | |
750 | - { | |
751 | - /*ペアの二番目を取得できない場合は、自分自身を返す*/ | |
752 | - return ST_EMPTY; | |
753 | - } | |
754 | - else | |
755 | - { | |
756 | - return list->second; | |
757 | - } | |
758 | -} | |
759 | - | |
760 | -/*メモリ割り当てを呼び出す関数 | |
761 | - * 引数nはメモリのサイズ*/ | |
762 | -void *ST_emalloc(size_t n) | |
763 | -{ | |
764 | - void *p; | |
765 | - p = calloc(1, n); | |
766 | - if (p == NULL) | |
767 | - { | |
768 | - errno = ENOBUFS; | |
769 | - eprintf("%u bytes failed on the function ST_emalloc:", n); | |
770 | - } | |
771 | - return p; | |
772 | -} | |
773 | - | |
774 | -/*ST_freelist関数 | |
775 | - * 引数のlistを解放させる | |
776 | - * 他から参照されていない限り、ST_EMPTY以外のリストすべてが対象*/ | |
777 | -void ST_freelist (ST_Ordered_Pair *list) | |
778 | -{ | |
779 | - if (ST_isEmpty(list)) | |
780 | - { | |
781 | - return; | |
782 | - } | |
783 | - | |
784 | - ST_Ordered_Pair *next; | |
785 | - | |
786 | - for (;!ST_isEmpty(list) || (list->lifepoint >= 1);list = next) | |
787 | - { | |
788 | - next = ST_second(list); | |
789 | - if (ST_isEmpty(next)) | |
790 | - { | |
791 | - break; | |
792 | - } | |
793 | - else | |
794 | - { | |
795 | - free(list); | |
796 | - /*参照カウンタを減らしておく*/ | |
797 | - next->lifepoint--; | |
798 | - list = NULL; | |
799 | - } | |
800 | - } | |
801 | -} | |
802 | - | |
803 | -/*ST_pair関数 | |
804 | - * 第一引数と第二引数とで順序対を作る*/ | |
805 | -ST_Ordered_Pair *ST_pair (ST_First_Type n, ST_Ordered_Pair *p) | |
806 | -{ | |
807 | - ST_Ordered_Pair *s; | |
808 | - | |
809 | - s = (ST_Ordered_Pair *) ST_emalloc(sizeof(ST_Ordered_Pair)); | |
810 | - s->first = n; | |
811 | - s->second = p; | |
812 | - s->lifepoint = 0; | |
813 | - | |
814 | - if (!ST_isEmpty(p)) | |
815 | - { | |
816 | - p->lifepoint++; | |
817 | - } | |
818 | - return s; | |
819 | -} | |
820 | - | |
821 | -/*ST_setChurchNumber 関数 | |
822 | - * C言語でラムダ計算のchurch数を部分的に再現するための関数*/ | |
823 | -ST_Ordered_Pair *ST_setChurchNumber (uint_fast32_t length, Ord2ST_Ordered_Pair f, ST_Ordered_Pair *list) | |
824 | -{ | |
825 | - int32_t i; | |
826 | - for (i = 0; i < length; i++) | |
827 | - { | |
828 | - /*lengthが4の場合、list = f(f(f(f(list))));*/ | |
829 | - list = (*f)(list); | |
830 | - } | |
831 | - return list; | |
832 | -} | |
833 | - | |
834 | -/*ST_getItem 関数 | |
835 | - * 入力されたリストの最後からnum番目にある項目の最初の値を取り出す(num >= 0)*/ | |
836 | -ST_First_Type ST_getItem (ST_Ordered_Pair *list, uint_fast32_t num) | |
837 | -{ | |
838 | - return ST_first( ST_setChurchNumber(num, ST_second, list) ); | |
839 | -} | |
840 | - | |
841 | - | |
842 | -/*ST_getBoundVariable 関数 | |
843 | - * 二分木リストとして表現された関数抽象abstractionの束縛変数(Bound Variable)を数値化したものを取得する | |
844 | - * ここでいう束縛変数とは、λx.Mのときの、変数xを指す*/ | |
845 | -ST_First_Type ST_getBoundVariable (ST_Ordered_Pair *abstraction) | |
846 | -{ | |
847 | - return ST_first(abstraction); | |
848 | -} | |
849 | - | |
850 | - | |
851 | -/*空ノードを表現するポインタ*/ | |
852 | -ST_Node_Tree __ST_EMPTY_NODE = { | |
853 | - NULL, | |
854 | - ST_UNKNOWN_NODE, | |
855 | - NULL, | |
856 | - NULL, | |
857 | - NULL, | |
858 | - NULL, | |
859 | - NULL | |
860 | -}; | |
861 | -ST_Node ST_EMPTY_NODE = &__ST_EMPTY_NODE; | |
862 | - | |
863 | -/*ST_isEmptyNode 関数 | |
864 | - * 引数の値がST_EMPTY_NODEであるかどうかを判別する関数*/ | |
865 | -bool ST_isEmptyNode (ST_Node node) | |
866 | -{ | |
867 | - if (node == ST_EMPTY_NODE) | |
868 | - { | |
869 | - return true; | |
870 | - } | |
871 | - else if (NULL == node) | |
872 | - { | |
873 | - errno = EINVAL; | |
874 | - eprint_log("NULL argument error on the function ST_isEmptyNode:"); | |
875 | - return false; | |
876 | - } | |
877 | - else | |
878 | - { | |
879 | - return false; | |
880 | - } | |
881 | -} | |
882 | - | |
883 | -/*check_null インライン関数 | |
884 | - * ノードでNULLチェックを行う*/ | |
885 | -static inline bool check_null (ST_Node node) | |
886 | -{ | |
887 | - if (NULL == node) | |
888 | - { | |
889 | - errno = EINVAL; | |
890 | - eprint_log("NULL argument error:"); | |
891 | - return true; | |
892 | - } | |
893 | - else | |
894 | - { | |
895 | - return false; | |
896 | - } | |
897 | -} | |
898 | - | |
899 | -/*ST_createNode 関数 | |
900 | - * 引数はフリーリスト用のノード(子ノードは後述するST_freenode 関数でルートノードとして扱われる) | |
901 | - * 返り値が新たに作られるノード*/ | |
902 | -ST_Node ST_createNode(ST_Free_Node freelist) | |
903 | -{ | |
904 | - errno_before_eprint = CREATE_NODE_ERROR; | |
905 | - | |
906 | - if (check_null(freelist)) | |
907 | - { | |
908 | - return ST_EMPTY_NODE; | |
909 | - } | |
910 | - | |
911 | - ST_Node s; | |
912 | - | |
913 | - s = (ST_Node) ST_emalloc(sizeof(ST_Node_Tree)); | |
914 | - s->nodeValue = ST_EMPTY; | |
915 | - s->lastChild = ST_EMPTY_NODE; | |
916 | - s->previousSibling = ST_EMPTY_NODE; | |
917 | - s->nextSibling = ST_EMPTY_NODE; | |
918 | - s->parentNode = ST_EMPTY_NODE; | |
919 | - s->nodeType = ST_UNKNOWN_NODE; | |
920 | - | |
921 | - if (!ST_isEmptyNode(freelist)) | |
922 | - { | |
923 | - /*freelistに、メモリ解放用ルートノードとして追加挿入*/ | |
924 | - ST_Node lastChild = ST_getLastChild(freelist); | |
925 | - s->previousSibling = lastChild; | |
926 | - lastChild->nextSibling = s; | |
927 | - freelist->lastChild = s; | |
928 | - s->parentNode = freelist; | |
929 | - } | |
930 | - | |
931 | - errno_before_eprint = Init_errno_before_eprint; | |
932 | - | |
933 | - return s; | |
934 | -} | |
935 | - | |
936 | -/*ST_setNodeValue 関数 | |
937 | - * 引数にノードの値をセットする*/ | |
938 | -void ST_setNodeValue(ST_Node node, ST_Ordered_Pair *nodeValue) | |
939 | -{ | |
940 | - if (NULL == nodeValue) | |
941 | - { | |
942 | - errno = EINVAL; | |
943 | - eprint_log("argument error on the function ST_setNodeValue:"); | |
944 | - return; | |
945 | - } | |
946 | - node->nodeValue = nodeValue; | |
947 | -} | |
948 | - | |
949 | -/*ST_removeChild 関数 | |
950 | - * 一番目の引数を親ノードparentとして、二番目の引数である子ノードchildをparentから引き離す | |
951 | - * 返り値はchild、ただし、エラーの時はST_EMPTY_NODE*/ | |
952 | -ST_Node ST_removeChild(ST_Node parent, ST_Node child) | |
953 | -{ | |
954 | - errno_before_eprint = REMOVE_CHILD_ERROR; | |
955 | - | |
956 | - /*エラーのパターンとしては、 | |
957 | - * parentか、nodeの値がNULL、あるいはST_EMPTY_NODEのとき*/ | |
958 | - | |
959 | - if ( (NULL == parent) || ST_isEmptyNode(parent)) | |
960 | - { | |
961 | - errno = EINVAL; | |
962 | - eprint_log("ST_EMPTY_NODE parent argument error on the function ST_removeChild:"); | |
963 | - return ST_EMPTY_NODE; | |
964 | - } | |
965 | - | |
966 | - if ( (NULL == child) || ST_isEmptyNode(child)) | |
967 | - { | |
968 | - errno = EINVAL; | |
969 | - eprint_log("ST_EMPTY_NODE argument error on the function ST_removeChild:"); | |
970 | - return ST_EMPTY_NODE; | |
971 | - } | |
972 | - | |
973 | - child->parentNode = ST_EMPTY_NODE; | |
974 | - | |
975 | - /*nodeが抜けた後、隣接ノードに関するメンバは書き換えておく*/ | |
976 | - if (!ST_isEmptyNode(child->previousSibling)) | |
977 | - { | |
978 | - child->previousSibling->nextSibling = child->nextSibling; | |
979 | - } | |
980 | - if (!ST_isEmptyNode(child->nextSibling)) | |
981 | - { | |
982 | - child->nextSibling->previousSibling = child->previousSibling; | |
983 | - } | |
984 | - | |
985 | - if (ST_getLastChild(parent) == child) | |
986 | - { | |
987 | - /*末尾ノードがnodeである場合はparentノードのメンバを書きかえておく*/ | |
988 | - parent->lastChild = ST_getPreviousNode(child); | |
989 | - } | |
990 | - | |
991 | - child->nextSibling = ST_EMPTY_NODE; | |
992 | - child->previousSibling = ST_EMPTY_NODE; | |
993 | - | |
994 | - errno_before_eprint = Init_errno_before_eprint; | |
995 | - | |
996 | - return child; | |
997 | -} | |
998 | - | |
999 | -/*ST_insertBefore 関数 | |
1000 | - * 副作用がある関数なので、扱いには注意を要する | |
1001 | - * 一番目の引数parentが親ノード。三番目の引数ノードprevの前隣りに、二番目の引数ノードnodeを挿入 | |
1002 | - * 三番目の引数が空ノードであれば、親ノードに末子ノードとして登録される | |
1003 | - * 返り値は、挿入に成功したとき引数node、失敗したときは空ノードを返す*/ | |
1004 | -ST_Node ST_insertBefore(ST_Node parent, ST_Node node, ST_Node prev) | |
1005 | -{ | |
1006 | - errno_before_eprint = INSERT_BEFORE_ERROR; | |
1007 | - | |
1008 | - /*挿入に失敗するパターンとしては、 | |
1009 | - * parentか、nodeの値がNULL、あるいはST_EMPTY_NODEのとき*/ | |
1010 | - if ( (NULL == parent) || ST_isEmptyNode(parent)) | |
1011 | - { | |
1012 | - errno = EINVAL; | |
1013 | - eprint_log("ST_EMPTY_NODE parent argument error on the function ST_insertBefore:"); | |
1014 | - return ST_EMPTY_NODE; | |
1015 | - } | |
1016 | - | |
1017 | - if ( (NULL == node) || ST_isEmptyNode(node)) | |
1018 | - { | |
1019 | - errno = EINVAL; | |
1020 | - eprint_log("ST_EMPTY_NODE argument error on the function ST_insertBefore:"); | |
1021 | - return ST_EMPTY_NODE; | |
1022 | - } | |
1023 | - | |
1024 | - /*祖先ノードの中に、今挿入しつつあるnodeと一致するものがあれば、参照エラー | |
1025 | - * というのは、循環参照を引き起こすため*/ | |
1026 | - ST_Node p = parent; | |
1027 | 676 | |
1028 | - while (!ST_isEmptyNode(p)) | |
1029 | - { | |
1030 | - if (p == node) | |
1031 | - { | |
1032 | - eprint_log("Reference error on the function ST_insertBefore:"); | |
1033 | - return ST_EMPTY_NODE; | |
1034 | - } | |
1035 | - | |
1036 | - p = ST_getParentNode(p); | |
1037 | - } | |
1038 | - | |
1039 | - ST_Node pnode = ST_getParentNode(node); | |
1040 | - | |
1041 | - if (!ST_isEmptyNode(pnode)) | |
1042 | - { | |
1043 | - /*nodeがすでに、他の枝に挿入されていた場合*/ | |
1044 | - ST_removeChild(pnode, node); | |
1045 | - } | |
1046 | - | |
1047 | - node->parentNode = parent; | |
1048 | - | |
1049 | - if (ST_isEmptyNode(prev)) | |
1050 | - { | |
1051 | - /*末尾ノードが存在するときは、そのノードのメンバも書きかえておく*/ | |
1052 | - ST_Node lastChild = ST_getLastChild(parent); | |
1053 | - if (!ST_isEmptyNode(lastChild)) | |
1054 | - { | |
1055 | - lastChild->nextSibling = node; | |
1056 | - node->previousSibling = lastChild; | |
1057 | - } | |
1058 | - /*末尾ノードとして挿入*/ | |
1059 | - parent->lastChild = node; | |
1060 | - } | |
1061 | - else if (NULL != prev) | |
1062 | - { | |
1063 | - ST_Node prevOfPrev = prev->previousSibling; | |
1064 | - if (!ST_isEmptyNode(prevOfPrev)) | |
1065 | - { | |
1066 | - /*prevの隣接ノードのnextSiblingメンバを書きかえておく*/ | |
1067 | - prevOfPrev->nextSibling = node; | |
1068 | - } | |
1069 | - node->previousSibling = prevOfPrev; | |
1070 | - prev->previousSibling = node; | |
1071 | - node->nextSibling = prev; | |
1072 | - } | |
1073 | - | |
1074 | - errno_before_eprint = Init_errno_before_eprint; | |
1075 | - | |
1076 | - return node; | |
1077 | -} | |
1078 | 677 | |
1079 | -/*ST_getNodeValue 関数 | |
1080 | - * 引数で指定されたノードの値を取得*/ | |
1081 | -ST_Ordered_Pair *ST_getNodeValue(ST_Node node) | |
1082 | -{ | |
1083 | - errno_before_eprint = GET_NODE_VALUE_ERROR; | |
1084 | - | |
1085 | - if (check_null(node)) | |
1086 | - { | |
1087 | - return ST_EMPTY; | |
1088 | - } | |
1089 | - | |
1090 | - if (ST_isEmptyNode(node) || (NULL == node->nodeValue)) | |
1091 | - { | |
1092 | - return ST_EMPTY; | |
1093 | - } | |
1094 | - | |
1095 | - errno_before_eprint = Init_errno_before_eprint; | |
1096 | - | |
1097 | - return node->nodeValue; | |
1098 | -} | |
1099 | - | |
1100 | -/*ST_getLastChild 関数 | |
1101 | - * 引数で指定されたノードの子リストの最後尾を取得*/ | |
1102 | -ST_Node ST_getLastChild(ST_Node node) | |
1103 | -{ | |
1104 | - errno_before_eprint = GET_LAST_CHILD_ERROR; | |
1105 | - | |
1106 | - if (check_null(node)) | |
1107 | - { | |
1108 | - return ST_EMPTY_NODE; | |
1109 | - } | |
1110 | - | |
1111 | - if (ST_isEmptyNode(node) || (NULL == node->lastChild)) | |
1112 | - { | |
1113 | - return node; | |
1114 | - } | |
1115 | - | |
1116 | - errno_before_eprint = Init_errno_before_eprint; | |
1117 | - | |
1118 | - return node->lastChild; | |
1119 | -} | |
1120 | - | |
1121 | -/*ST_getPreviousNode 関数 | |
1122 | - * 引数で指定されたノードにとって、前隣りのノードを取得*/ | |
1123 | -ST_Node ST_getPreviousNode(ST_Node node) | |
1124 | -{ | |
1125 | - errno_before_eprint = GET_PREVIOUS_NODE_ERROR; | |
1126 | - | |
1127 | - if (check_null(node)) | |
1128 | - { | |
1129 | - return ST_EMPTY_NODE; | |
1130 | - } | |
1131 | - | |
1132 | - if (ST_isEmptyNode(node) || (NULL == node->previousSibling)) | |
1133 | - { | |
1134 | - return node; | |
1135 | - } | |
1136 | - | |
1137 | - errno_before_eprint = Init_errno_before_eprint; | |
1138 | - | |
1139 | - return node->previousSibling; | |
1140 | -} | |
1141 | - | |
1142 | -/*ST_getParentNode 関数 | |
1143 | - * 引数の親ノードを取得*/ | |
1144 | -ST_Node ST_getParentNode(ST_Node node) | |
1145 | -{ | |
1146 | - errno_before_eprint = GET_PARENT_NODE_ERROR; | |
1147 | - | |
1148 | - if (check_null(node)) | |
1149 | - { | |
1150 | - errno_before_eprint = Init_errno_before_eprint; | |
1151 | - return ST_EMPTY_NODE; | |
1152 | - } | |
1153 | - | |
1154 | - if (ST_isEmptyNode(node) || (NULL == node->parentNode)) | |
1155 | - { | |
1156 | - errno_before_eprint = Init_errno_before_eprint; | |
1157 | - return ST_EMPTY_NODE; | |
1158 | - } | |
1159 | - | |
1160 | - errno_before_eprint = Init_errno_before_eprint; | |
1161 | - | |
1162 | - return node->parentNode; | |
1163 | -} | |
1164 | - | |
1165 | -/*ST_copyNode 関数 | |
1166 | - * 二番目の引数で指定されたノードのコピーを作成して、返す | |
1167 | - * 子ノードも含めて深くコピーするが、隣接ノードはコピーしない | |
1168 | - * 一番目の引数はST_freenodeで使うためのフリーリスト*/ | |
1169 | -ST_Node ST_copyNode(ST_Free_Node freelist, ST_Node node) | |
1170 | -{ | |
1171 | - errno_before_eprint = COPY_NODE_ERROR; | |
1172 | - | |
1173 | - if ((NULL == node) || ST_isEmptyNode(node)) | |
1174 | - { | |
1175 | - /*nodeが無効値、NULLである場合はエラー | |
1176 | - *ST_EMPTY_NODEを返す*/ | |
1177 | - errno = EINVAL; | |
1178 | - eprint_log("Argument error on the function ST_copyNode:"); | |
1179 | - return ST_EMPTY_NODE; | |
1180 | - } | |
1181 | - | |
1182 | - ST_Node copy = ST_createNode(freelist); | |
1183 | - ST_setNodeValue(copy, ST_getNodeValue(node)); | |
1184 | - copy->nodeType = node->nodeType; | |
1185 | - | |
1186 | - /*コピーしたい子ノードにおける現在のノード*/ | |
1187 | - ST_Node current = ST_EMPTY_NODE; | |
1188 | - /*コピーしたい子ノード*/ | |
1189 | - ST_Node child = ST_getLastChild(node); | |
1190 | - /*nodeの子ノードを次々とコピーしていく*/ | |
1191 | - while (!ST_isEmptyNode(child)) | |
1192 | - { | |
1193 | - /*currentにはST_copyNode(child)の値が代入される*/ | |
1194 | - current = ST_insertBefore(copy, ST_copyNode(ST_EMPTY_NODE, child), current); | |
1195 | - child = ST_getPreviousNode(child); | |
1196 | - } | |
1197 | - | |
1198 | - errno_before_eprint = Init_errno_before_eprint; | |
1199 | - | |
1200 | - return copy; | |
1201 | -} | |
1202 | - | |
1203 | -/*ST_freenode 関数 | |
1204 | - * 引数freelistに登録されたノードを、子ノードも含めて、全て深く解放していく | |
1205 | - * その際、ノード値そのものも解放する*/ | |
1206 | -void ST_freenode (ST_Free_Node freelist) | |
1207 | -{ | |
1208 | - if ( (NULL == freelist) || ST_isEmptyNode(freelist)) | |
1209 | - { | |
1210 | - return; | |
1211 | - } | |
1212 | - | |
1213 | - ST_Node prev = ST_getLastChild(freelist); | |
1214 | - | |
1215 | - while (!ST_isEmptyNode(prev)) | |
1216 | - { | |
1217 | - ST_Node node = prev; | |
1218 | - prev = ST_getPreviousNode(node); | |
1219 | - ST_freenode(node); | |
1220 | - } | |
1221 | - free(freelist); | |
1222 | - freelist = NULL; | |
1223 | -} | |
1224 | 678 | |
1225 | 679 | |
1226 | 680 | /*ST_readFile 関数 |