* gcc.c (getenv_spec_function): New function.
[official-gcc.git] / gcc / ada / a-rbtgso.adb
blobfc0c706304aedf138804de1315af5e572e5d364d
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S . --
6 -- G E N E R I C _ S E T _ O P E R A T I O N S --
7 -- --
8 -- B o d y --
9 -- --
10 -- Copyright (C) 2004-2006, Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
21 -- Boston, MA 02110-1301, USA. --
22 -- --
23 -- As a special exception, if other files instantiate generics from this --
24 -- unit, or you link this unit with other files to produce an executable, --
25 -- this unit does not by itself cause the resulting executable to be --
26 -- covered by the GNU General Public License. This exception does not --
27 -- however invalidate any other reasons why the executable file might be --
28 -- covered by the GNU Public License. --
29 -- --
30 -- This unit was originally developed by Matthew J Heaney. --
31 ------------------------------------------------------------------------------
33 with System; use type System.Address;
35 package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
37 -----------------------
38 -- Local Subprograms --
39 -----------------------
41 procedure Clear (Tree : in out Tree_Type);
43 function Copy (Source : Tree_Type) return Tree_Type;
45 -----------
46 -- Clear --
47 -----------
49 procedure Clear (Tree : in out Tree_Type) is
50 pragma Assert (Tree.Busy = 0);
51 pragma Assert (Tree.Lock = 0);
53 Root : Node_Access := Tree.Root;
55 begin
56 Tree.Root := null;
57 Tree.First := null;
58 Tree.Last := null;
59 Tree.Length := 0;
61 Delete_Tree (Root);
62 end Clear;
64 ----------
65 -- Copy --
66 ----------
68 function Copy (Source : Tree_Type) return Tree_Type is
69 Target : Tree_Type;
71 begin
72 if Source.Length = 0 then
73 return Target;
74 end if;
76 Target.Root := Copy_Tree (Source.Root);
77 Target.First := Tree_Operations.Min (Target.Root);
78 Target.Last := Tree_Operations.Max (Target.Root);
79 Target.Length := Source.Length;
81 return Target;
82 end Copy;
84 ----------------
85 -- Difference --
86 ----------------
88 procedure Difference (Target : in out Tree_Type; Source : Tree_Type) is
89 Tgt : Node_Access := Target.First;
90 Src : Node_Access := Source.First;
92 begin
93 if Target'Address = Source'Address then
94 if Target.Busy > 0 then
95 raise Program_Error with
96 "attempt to tamper with cursors (container is busy)";
97 end if;
99 Clear (Target);
100 return;
101 end if;
103 if Source.Length = 0 then
104 return;
105 end if;
107 if Target.Busy > 0 then
108 raise Program_Error with
109 "attempt to tamper with cursors (container is busy)";
110 end if;
112 loop
113 if Tgt = null then
114 return;
115 end if;
117 if Src = null then
118 return;
119 end if;
121 if Is_Less (Tgt, Src) then
122 Tgt := Tree_Operations.Next (Tgt);
124 elsif Is_Less (Src, Tgt) then
125 Src := Tree_Operations.Next (Src);
127 else
128 declare
129 X : Node_Access := Tgt;
130 begin
131 Tgt := Tree_Operations.Next (Tgt);
132 Tree_Operations.Delete_Node_Sans_Free (Target, X);
133 Free (X);
134 end;
136 Src := Tree_Operations.Next (Src);
137 end if;
138 end loop;
139 end Difference;
141 function Difference (Left, Right : Tree_Type) return Tree_Type is
142 Tree : Tree_Type;
144 L_Node : Node_Access := Left.First;
145 R_Node : Node_Access := Right.First;
147 Dst_Node : Node_Access;
149 begin
150 if Left'Address = Right'Address then
151 return Tree; -- Empty set
152 end if;
154 if Left.Length = 0 then
155 return Tree; -- Empty set
156 end if;
158 if Right.Length = 0 then
159 return Copy (Left);
160 end if;
162 loop
163 if L_Node = null then
164 return Tree;
165 end if;
167 if R_Node = null then
168 while L_Node /= null loop
169 Insert_With_Hint
170 (Dst_Tree => Tree,
171 Dst_Hint => null,
172 Src_Node => L_Node,
173 Dst_Node => Dst_Node);
175 L_Node := Tree_Operations.Next (L_Node);
177 end loop;
179 return Tree;
180 end if;
182 if Is_Less (L_Node, R_Node) then
183 Insert_With_Hint
184 (Dst_Tree => Tree,
185 Dst_Hint => null,
186 Src_Node => L_Node,
187 Dst_Node => Dst_Node);
189 L_Node := Tree_Operations.Next (L_Node);
191 elsif Is_Less (R_Node, L_Node) then
192 R_Node := Tree_Operations.Next (R_Node);
194 else
195 L_Node := Tree_Operations.Next (L_Node);
196 R_Node := Tree_Operations.Next (R_Node);
197 end if;
198 end loop;
200 exception
201 when others =>
202 Delete_Tree (Tree.Root);
203 raise;
204 end Difference;
206 ------------------
207 -- Intersection --
208 ------------------
210 procedure Intersection
211 (Target : in out Tree_Type;
212 Source : Tree_Type)
214 Tgt : Node_Access := Target.First;
215 Src : Node_Access := Source.First;
217 begin
218 if Target'Address = Source'Address then
219 return;
220 end if;
222 if Target.Busy > 0 then
223 raise Program_Error with
224 "attempt to tamper with cursors (container is busy)";
225 end if;
227 if Source.Length = 0 then
228 Clear (Target);
229 return;
230 end if;
232 while Tgt /= null
233 and then Src /= null
234 loop
235 if Is_Less (Tgt, Src) then
236 declare
237 X : Node_Access := Tgt;
238 begin
239 Tgt := Tree_Operations.Next (Tgt);
240 Tree_Operations.Delete_Node_Sans_Free (Target, X);
241 Free (X);
242 end;
244 elsif Is_Less (Src, Tgt) then
245 Src := Tree_Operations.Next (Src);
247 else
248 Tgt := Tree_Operations.Next (Tgt);
249 Src := Tree_Operations.Next (Src);
250 end if;
251 end loop;
253 while Tgt /= null loop
254 declare
255 X : Node_Access := Tgt;
256 begin
257 Tgt := Tree_Operations.Next (Tgt);
258 Tree_Operations.Delete_Node_Sans_Free (Target, X);
259 Free (X);
260 end;
261 end loop;
262 end Intersection;
264 function Intersection (Left, Right : Tree_Type) return Tree_Type is
265 Tree : Tree_Type;
267 L_Node : Node_Access := Left.First;
268 R_Node : Node_Access := Right.First;
270 Dst_Node : Node_Access;
272 begin
273 if Left'Address = Right'Address then
274 return Copy (Left);
275 end if;
277 loop
278 if L_Node = null then
279 return Tree;
280 end if;
282 if R_Node = null then
283 return Tree;
284 end if;
286 if Is_Less (L_Node, R_Node) then
287 L_Node := Tree_Operations.Next (L_Node);
289 elsif Is_Less (R_Node, L_Node) then
290 R_Node := Tree_Operations.Next (R_Node);
292 else
293 Insert_With_Hint
294 (Dst_Tree => Tree,
295 Dst_Hint => null,
296 Src_Node => L_Node,
297 Dst_Node => Dst_Node);
299 L_Node := Tree_Operations.Next (L_Node);
300 R_Node := Tree_Operations.Next (R_Node);
301 end if;
302 end loop;
304 exception
305 when others =>
306 Delete_Tree (Tree.Root);
307 raise;
308 end Intersection;
310 ---------------
311 -- Is_Subset --
312 ---------------
314 function Is_Subset
315 (Subset : Tree_Type;
316 Of_Set : Tree_Type) return Boolean
318 begin
319 if Subset'Address = Of_Set'Address then
320 return True;
321 end if;
323 if Subset.Length > Of_Set.Length then
324 return False;
325 end if;
327 declare
328 Subset_Node : Node_Access := Subset.First;
329 Set_Node : Node_Access := Of_Set.First;
331 begin
332 loop
333 if Set_Node = null then
334 return Subset_Node = null;
335 end if;
337 if Subset_Node = null then
338 return True;
339 end if;
341 if Is_Less (Subset_Node, Set_Node) then
342 return False;
343 end if;
345 if Is_Less (Set_Node, Subset_Node) then
346 Set_Node := Tree_Operations.Next (Set_Node);
347 else
348 Set_Node := Tree_Operations.Next (Set_Node);
349 Subset_Node := Tree_Operations.Next (Subset_Node);
350 end if;
351 end loop;
352 end;
353 end Is_Subset;
355 -------------
356 -- Overlap --
357 -------------
359 function Overlap (Left, Right : Tree_Type) return Boolean is
360 L_Node : Node_Access := Left.First;
361 R_Node : Node_Access := Right.First;
363 begin
364 if Left'Address = Right'Address then
365 return Left.Length /= 0;
366 end if;
368 loop
369 if L_Node = null
370 or else R_Node = null
371 then
372 return False;
373 end if;
375 if Is_Less (L_Node, R_Node) then
376 L_Node := Tree_Operations.Next (L_Node);
378 elsif Is_Less (R_Node, L_Node) then
379 R_Node := Tree_Operations.Next (R_Node);
381 else
382 return True;
383 end if;
384 end loop;
385 end Overlap;
387 --------------------------
388 -- Symmetric_Difference --
389 --------------------------
391 procedure Symmetric_Difference
392 (Target : in out Tree_Type;
393 Source : Tree_Type)
395 Tgt : Node_Access := Target.First;
396 Src : Node_Access := Source.First;
398 New_Tgt_Node : Node_Access;
400 begin
401 if Target.Busy > 0 then
402 raise Program_Error with
403 "attempt to tamper with cursors (container is busy)";
404 end if;
406 if Target'Address = Source'Address then
407 Clear (Target);
408 return;
409 end if;
411 loop
412 if Tgt = null then
413 while Src /= null loop
414 Insert_With_Hint
415 (Dst_Tree => Target,
416 Dst_Hint => null,
417 Src_Node => Src,
418 Dst_Node => New_Tgt_Node);
420 Src := Tree_Operations.Next (Src);
421 end loop;
423 return;
424 end if;
426 if Src = null then
427 return;
428 end if;
430 if Is_Less (Tgt, Src) then
431 Tgt := Tree_Operations.Next (Tgt);
433 elsif Is_Less (Src, Tgt) then
434 Insert_With_Hint
435 (Dst_Tree => Target,
436 Dst_Hint => Tgt,
437 Src_Node => Src,
438 Dst_Node => New_Tgt_Node);
440 Src := Tree_Operations.Next (Src);
442 else
443 declare
444 X : Node_Access := Tgt;
445 begin
446 Tgt := Tree_Operations.Next (Tgt);
447 Tree_Operations.Delete_Node_Sans_Free (Target, X);
448 Free (X);
449 end;
451 Src := Tree_Operations.Next (Src);
452 end if;
453 end loop;
454 end Symmetric_Difference;
456 function Symmetric_Difference (Left, Right : Tree_Type) return Tree_Type is
457 Tree : Tree_Type;
459 L_Node : Node_Access := Left.First;
460 R_Node : Node_Access := Right.First;
462 Dst_Node : Node_Access;
464 begin
465 if Left'Address = Right'Address then
466 return Tree; -- Empty set
467 end if;
469 if Right.Length = 0 then
470 return Copy (Left);
471 end if;
473 if Left.Length = 0 then
474 return Copy (Right);
475 end if;
477 loop
478 if L_Node = null then
479 while R_Node /= null loop
480 Insert_With_Hint
481 (Dst_Tree => Tree,
482 Dst_Hint => null,
483 Src_Node => R_Node,
484 Dst_Node => Dst_Node);
485 R_Node := Tree_Operations.Next (R_Node);
486 end loop;
488 return Tree;
489 end if;
491 if R_Node = null then
492 while L_Node /= null loop
493 Insert_With_Hint
494 (Dst_Tree => Tree,
495 Dst_Hint => null,
496 Src_Node => L_Node,
497 Dst_Node => Dst_Node);
499 L_Node := Tree_Operations.Next (L_Node);
500 end loop;
502 return Tree;
503 end if;
505 if Is_Less (L_Node, R_Node) then
506 Insert_With_Hint
507 (Dst_Tree => Tree,
508 Dst_Hint => null,
509 Src_Node => L_Node,
510 Dst_Node => Dst_Node);
512 L_Node := Tree_Operations.Next (L_Node);
514 elsif Is_Less (R_Node, L_Node) then
515 Insert_With_Hint
516 (Dst_Tree => Tree,
517 Dst_Hint => null,
518 Src_Node => R_Node,
519 Dst_Node => Dst_Node);
521 R_Node := Tree_Operations.Next (R_Node);
523 else
524 L_Node := Tree_Operations.Next (L_Node);
525 R_Node := Tree_Operations.Next (R_Node);
526 end if;
527 end loop;
529 exception
530 when others =>
531 Delete_Tree (Tree.Root);
532 raise;
533 end Symmetric_Difference;
535 -----------
536 -- Union --
537 -----------
539 procedure Union (Target : in out Tree_Type; Source : Tree_Type)
541 Hint : Node_Access;
543 procedure Process (Node : Node_Access);
544 pragma Inline (Process);
546 procedure Iterate is new Tree_Operations.Generic_Iteration (Process);
548 -------------
549 -- Process --
550 -------------
552 procedure Process (Node : Node_Access) is
553 begin
554 Insert_With_Hint
555 (Dst_Tree => Target,
556 Dst_Hint => Hint,
557 Src_Node => Node,
558 Dst_Node => Hint);
559 end Process;
561 -- Start of processing for Union
563 begin
564 if Target'Address = Source'Address then
565 return;
566 end if;
568 if Target.Busy > 0 then
569 raise Program_Error with
570 "attempt to tamper with cursors (container is busy)";
571 end if;
573 Iterate (Source);
574 end Union;
576 function Union (Left, Right : Tree_Type) return Tree_Type is
577 begin
578 if Left'Address = Right'Address then
579 return Copy (Left);
580 end if;
582 if Left.Length = 0 then
583 return Copy (Right);
584 end if;
586 if Right.Length = 0 then
587 return Copy (Left);
588 end if;
590 declare
591 Tree : Tree_Type := Copy (Left);
593 Hint : Node_Access;
595 procedure Process (Node : Node_Access);
596 pragma Inline (Process);
598 procedure Iterate is
599 new Tree_Operations.Generic_Iteration (Process);
601 -------------
602 -- Process --
603 -------------
605 procedure Process (Node : Node_Access) is
606 begin
607 Insert_With_Hint
608 (Dst_Tree => Tree,
609 Dst_Hint => Hint,
610 Src_Node => Node,
611 Dst_Node => Hint);
612 end Process;
614 -- Start of processing for Union
616 begin
617 Iterate (Right);
618 return Tree;
620 exception
621 when others =>
622 Delete_Tree (Tree.Root);
623 raise;
624 end;
626 end Union;
628 end Ada.Containers.Red_Black_Trees.Generic_Set_Operations;