1 /* Part of XPCE --- The SWI-Prolog GUI toolkit
2
3 Author: Jan Wielemaker and Anjo Anjewierden
4 E-mail: jan@swi.psy.uva.nl
5 WWW: http://www.swi.psy.uva.nl/projects/xpce/
6 Copyright (c) 1985-2002, University of Amsterdam
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12
13 1. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <h/kernel.h>
36 #include "../unx/proto.h" /* file operations */
37
38 forwards Cell newCell(Chain, Any);
39 forwards Cell previousCell(Chain, Cell);
40 static status deleteCurrentChain(Chain ch);
41 static Int getCellIndexChain(Chain ch, Cell c);
42
43 #define ChangedChain(ch, op, ctx) \
44 if ( onFlag(ch, F_INSPECT) && notNil(ClassChain->changed_messages) ) \
45 changedObject(ch, op, ctx, EAV)
46
47 /* (JW) Class chain is not a truely object oriented class as its internal
48 representation as cell is no class. assign() is used such that
49 reference counts to other objects are kept, most internal
50 assignments are done with '='.
51 */
52
53 static Cell
newCell(Chain ch,register Any value)54 newCell(Chain ch, register Any value)
55 { Cell cell;
56
57 cell = alloc(sizeof(struct cell));
58 cell->value = NIL;
59 cell->next = NIL;
60 assignField((Instance) ch, &cell->value, value);
61
62 return cell;
63 }
64
65
66 static void
freeCell(Chain ch,Cell cell)67 freeCell(Chain ch, Cell cell)
68 { assignField((Instance) ch, &cell->value, NIL);
69
70 unalloc(sizeof(struct cell), cell);
71 }
72
73
74 static Cell
previousCell(Chain ch,register Cell next)75 previousCell(Chain ch, register Cell next)
76 { register Cell cell;
77
78 for_cell(cell, ch)
79 if (cell->next == next)
80 return cell;
81 fail;
82 }
83
84
85 status
initialiseChainv(Chain ch,int argc,Any * argv)86 initialiseChainv(Chain ch, int argc, Any *argv)
87 { int i;
88
89 assign(ch, size, ZERO);
90 ch->current = ch->head = ch->tail = NIL;
91 for(i=0; i<argc; i++)
92 appendChain(ch, argv[i]);
93
94 succeed;
95 }
96
97
98 static Chain
getConvertChain(Any ctx,Vector v)99 getConvertChain(Any ctx, Vector v)
100 { Chain ch = answerObject(ClassChain, EAV);
101 int n = valInt(v->size);
102 Any *e = v->elements;
103
104 for( ; --n >= 0; e++ )
105 { appendChain(ch, *e);
106 }
107
108 answer(ch);
109 }
110
111
112 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
113 Load/store a chain on a file. Format:
114
115 <chain> ::= {<cell>} 'X'
116
117 <cell> ::= 'e' <object> (cell holding <object>)
118 | 'E' <object> (`current' cell holding <object>)
119 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
120
121 static status
storeChain(Chain ch,FileObj file)122 storeChain(Chain ch, FileObj file)
123 { Cell cell;
124
125 TRY(storeSlotsObject(ch, file));
126 for_cell(cell, ch)
127 { storeCharFile(file, cell == ch->current ? 'E' : 'e');
128 TRY( storeObject(cell->value, file) );
129 }
130 storeCharFile(file, 'X');
131
132 succeed;
133 }
134
135 static status
loadChain(Chain ch,IOSTREAM * fd,ClassDef def)136 loadChain(Chain ch, IOSTREAM *fd, ClassDef def)
137 { Any obj;
138 Cell current;
139 char c;
140
141 if ( restoreVersion != 2 )
142 TRY(loadSlotsObject(ch, fd, def));
143
144 current = ch->current = ch->head = ch->tail = NIL;
145 assign(ch, size, ZERO);
146
147 for(;;)
148 switch( c=Sgetc(fd) )
149 { case 'e':
150 case 'E':
151 TRY( obj=loadObject(fd) );
152 appendChain(ch, obj);
153 if ( c == 'E' )
154 current = ch->tail;
155 continue;
156 case 'X':
157 ch->current = current;
158 succeed;
159 default:
160 errorPce(LoadFile, NAME_illegalCharacter,
161 toInt(c), toInt(Stell(fd)));
162 }
163 }
164
165
166 static status
unlinkChain(Chain ch)167 unlinkChain(Chain ch)
168 { return clearChain(ch);
169 }
170
171
172 static status
cloneChain(Chain ch,Chain clone)173 cloneChain(Chain ch, Chain clone)
174 { Cell cell;
175
176 clonePceSlots(ch, clone);
177 clone->current = clone->head = clone->tail = NIL;
178
179 for_cell(cell, ch)
180 { appendChain(clone, getClone2Object(cell->value));
181 if ( ch->current == cell )
182 clone->current = clone->tail;
183 }
184
185 assign(clone, size, ch->size);
186
187 succeed;
188 }
189
190
191 status
clearChain(Chain ch)192 clearChain(Chain ch)
193 { Cell p, q;
194
195 for_cell_save(p, q, ch)
196 { ch->head = q;
197 freeCell(ch, p);
198 }
199 ch->head = ch->tail = ch->current = NIL;
200 assign(ch, size, ZERO);
201 ChangedChain(ch, NAME_clear, EAV);
202
203 succeed;
204 }
205
206
207 static status
truncateChain(Chain ch,Int to)208 truncateChain(Chain ch, Int to)
209 { int n = valInt(to);
210 int i = 0;
211 Cell p, q;
212
213 if ( n <= 0 )
214 return clearChain(ch);
215
216 for_cell_save(p, q, ch)
217 { if ( i == n-1 )
218 { p->next = NIL;
219 ch->tail = p;
220 assign(ch, size, to);
221 ChangedChain(ch, NAME_truncate, to);
222 } else if ( i >= n )
223 { if ( ch->current == p )
224 ch->current = NIL;
225
226 freeCell(ch, p);
227 }
228
229 i++;
230 }
231
232 succeed;
233 }
234
235
236 Int
getSizeChain(Chain ch)237 getSizeChain(Chain ch)
238 { answer(ch->size);
239 }
240
241
242 status
prependChain(register Chain ch,Any obj)243 prependChain(register Chain ch, Any obj)
244 { Cell cell;
245
246 cell = newCell(ch, obj);
247
248 if (isNil(ch->head))
249 ch->head = ch->tail = cell;
250 else
251 cell->next = ch->head,
252 ch->head = cell;
253
254 assign(ch, size, inc(ch->size));
255 ChangedChain(ch, NAME_insert, ONE);
256
257 succeed;
258 }
259
260
261 status
appendChain(register Chain ch,Any obj)262 appendChain(register Chain ch, Any obj)
263 { Cell cell;
264
265 cell = newCell(ch, obj);
266
267 if (isNil(ch->head))
268 { ch->head = ch->tail = cell;
269 } else
270 { ch->tail->next = cell;
271 ch->tail = cell;
272 }
273
274 assign(ch, size, inc(ch->size));
275 ChangedChain(ch, NAME_insert, getSizeChain(ch));
276
277 succeed;
278 }
279
280
281 status
addChain(register Chain ch,Any obj)282 addChain(register Chain ch, Any obj)
283 { if ( !memberChain(ch, obj) )
284 return prependChain(ch, obj);
285
286 succeed;
287 }
288
289
290 status
insertChain(Chain ch,Any obj)291 insertChain(Chain ch, Any obj)
292 { Cell cell, prev, current = ch->current;
293
294 if ( current == ch->head )
295 return prependChain(ch, obj);
296 if ( isNil(current) )
297 return appendChain(ch, obj);
298
299 cell = newCell(ch, obj);
300 prev = previousCell(ch, current);
301 prev->next = cell;
302 cell->next = current;
303 ch->current = cell;
304
305 assign(ch, size, inc(ch->size));
306 ChangedChain(ch, NAME_insert, getCellIndexChain(ch, cell));
307
308 succeed;
309 }
310
311
312 status
insertAfterChain(Chain ch,Any obj,Any obj2)313 insertAfterChain(Chain ch, Any obj, Any obj2)
314 { int i = 1;
315 Cell cell;
316
317 if ( isNil(obj2) )
318 return prependChain(ch, obj);
319
320 for_cell(cell, ch)
321 { if ( cell->value == obj2 )
322 { if ( ch->tail == cell )
323 { return appendChain(ch, obj);
324 } else
325 { Cell c2 = newCell(ch, obj);
326
327 c2->next = cell->next;
328 cell->next = c2;
329 assign(ch, size, inc(ch->size));
330 ChangedChain(ch, NAME_insert, toInt(i+1));
331
332 succeed;
333 }
334 }
335
336 i++;
337 }
338
339 fail;
340 }
341
342
343 status
insertBeforeChain(Chain ch,Any obj,Any obj2)344 insertBeforeChain(Chain ch, Any obj, Any obj2)
345 { int i = 1;
346 Cell cell, prev = NIL;
347
348 for_cell(cell, ch)
349 { if ( cell->value == obj2 )
350 { if ( isNil(prev) )
351 { return prependChain(ch, obj);
352 } else
353 { Cell c2 = newCell(ch, obj);
354
355 c2->next = prev->next;
356 prev->next = c2;
357 assign(ch, size, inc(ch->size));
358 ChangedChain(ch, NAME_insert, toInt(i));
359
360 succeed;
361 }
362 }
363
364 prev = cell;
365 i++;
366 }
367
368 return appendChain(ch, obj);
369 }
370
371
372 static Cell
findCellChain(Chain ch,Any obj,int * idx)373 findCellChain(Chain ch, Any obj, int *idx)
374 { Cell cell;
375 int i=1;
376
377 for_cell(cell, ch)
378 { if ( cell->value == obj )
379 { if ( idx )
380 *idx = i;
381 return cell;
382 }
383 i++;
384 }
385
386 return NULL;
387 }
388
389
390 status
swapChain(Chain ch,Any obj1,Any obj2)391 swapChain(Chain ch, Any obj1, Any obj2)
392 { Cell c1, c2;
393 int i1, i2;
394
395 if ( !(c1=findCellChain(ch, obj1, &i1)) ||
396 !(c2=findCellChain(ch, obj2, &i2)) )
397 fail;
398
399 c2->value = obj1;
400 c1->value = obj2;
401
402 ChangedChain(ch, NAME_cell, toInt(i1));
403 ChangedChain(ch, NAME_cell, toInt(i2));
404
405 succeed;
406 }
407
408
409 status
deleteHeadChain(Chain ch)410 deleteHeadChain(Chain ch)
411 { EXISTS(ch->head);
412
413 return deleteCellChain(ch, ch->head);
414 }
415
416
417 static status
deleteTailChain(Chain ch)418 deleteTailChain(Chain ch)
419 { EXISTS(ch->tail);
420
421 return deleteCellChain(ch, ch->tail);
422 }
423
424
425 status
deleteChain(Chain ch,register Any obj)426 deleteChain(Chain ch, register Any obj)
427 { register Cell cell, p;
428 int i;
429
430 EXISTS(ch->head);
431
432 if ( notNil(ch->current) && ch->current->value == obj )
433 ch->current = NIL;
434
435 if (ch->head == ch->tail)
436 { Cell head = ch->head;
437
438 if ( head->value != obj )
439 fail;
440 ch->head = ch->tail = NIL;
441 freeCell(ch, head);
442 assign(ch, size, ZERO);
443 ChangedChain(ch, NAME_clear, EAV);
444 succeed;
445 }
446
447 if (ch->head->value == obj)
448 { Cell head = ch->head;
449
450 ch->head = head->next;
451 freeCell(ch, head);
452 assign(ch, size, dec(ch->size));
453 ChangedChain(ch, NAME_delete, ONE);
454 succeed;
455 }
456
457 for(p=ch->head, cell=p->next, i=2;
458 notNil(cell);
459 p=cell, cell=cell->next, i++)
460 { if (cell->value == obj)
461 { p->next = cell->next;
462 if (cell == ch->tail)
463 ch->tail = p;
464 freeCell(ch, cell);
465 assign(ch, size, dec(ch->size));
466 ChangedChain(ch, NAME_delete, toInt(i));
467 succeed;
468 }
469 }
470
471 fail;
472 }
473
474
475 static status
deleteCurrentChain(Chain ch)476 deleteCurrentChain(Chain ch)
477 { if ( notNil(ch->current) )
478 return deleteCellChain(ch, ch->current);
479
480 succeed;
481 }
482
483
484 status
deleteCellChain(Chain ch,Cell cell)485 deleteCellChain(Chain ch, Cell cell)
486 { Cell prev;
487 Int i = ONE;
488
489 if ( cell == ch->head && ch->head == ch->tail )
490 { Cell head = ch->head;
491
492 ch->head = ch->tail = ch->current = NIL;
493 freeCell(ch, head);
494 ChangedChain(ch, NAME_clear, EAV);
495 assign(ch, size, ZERO);
496
497 succeed;
498 }
499
500 if (cell == ch->head)
501 { ch->head = cell->next;
502 } else
503 { if ( notNil(ClassChain->changed_messages) )
504 i = getCellIndexChain(ch, cell);
505 prev = previousCell(ch, cell);
506 prev->next = cell->next;
507 if (cell == ch->tail)
508 ch->tail = prev;
509 }
510 if ( cell == ch->current )
511 ch->current = NIL;
512 freeCell(ch, cell);
513 assign(ch, size, dec(ch->size));
514 ChangedChain(ch, NAME_delete, i);
515
516 succeed;
517 }
518
519
520 static status
deleteAllChain(Chain ch,Any obj)521 deleteAllChain(Chain ch, Any obj)
522 { while( deleteChain(ch, obj) )
523 ; /* can be more efficient */
524
525 succeed;
526 }
527
528
529 status
memberChain(Chain ch,Any obj)530 memberChain(Chain ch, Any obj)
531 { register Cell cell;
532
533 for_cell(cell, ch)
534 { if ( cell->value == obj )
535 succeed;
536 }
537 fail;
538 }
539
540
541 static status
currentChain(Chain ch,Any obj)542 currentChain(Chain ch, Any obj)
543 { if ( isNil(obj) )
544 { ch->current = NIL;
545 succeed;
546 } else
547 { Cell cell;
548
549 for_cell(cell, ch)
550 { if ( cell->value == obj )
551 { ch->current = cell;
552 succeed;
553 }
554 }
555 fail;
556 }
557 }
558
559
560 static status
currentNoChain(Chain ch,Int index)561 currentNoChain(Chain ch, Int index)
562 { register Cell cell;
563 register int i = valInt(index);
564
565 if (i == 0)
566 { ch->current = NIL;
567 succeed;
568 }
569
570 for_cell(cell, ch)
571 { if (--i < 1)
572 { ch->current = cell;
573 succeed;
574 }
575 }
576 fail;
577 }
578
579
580 static Int
getCurrentNoChain(Chain ch)581 getCurrentNoChain(Chain ch)
582 { Cell cell;
583 int n;
584
585 if (isNil(ch->current))
586 fail;
587
588 for(n=1, cell=ch->head; cell != ch->current; cell=cell->next)
589 n++;
590
591 answer(toInt(n));
592 }
593
594
595 static Any
getCurrentChain(Chain ch)596 getCurrentChain(Chain ch)
597 { EXISTS(ch->current);
598 answer(ch->current->value);
599 }
600
601
602 Any
getNextChain(Chain ch,Any val)603 getNextChain(Chain ch, Any val)
604 { if ( isDefault(val) ) /* old code */
605 { Any result;
606
607 EXISTS(ch->current);
608 result = ch->current->value;
609 ch->current = ch->current->next;
610
611 answer(result);
612 } else
613 { Cell cell;
614
615 for_cell(cell, ch)
616 { if ( cell->value == val )
617 { if ( notNil(cell->next) )
618 answer(cell->next->value);
619 break;
620 }
621 }
622
623 fail;
624 }
625 }
626
627
628 Any
getPreviousChain(Chain ch,Any val)629 getPreviousChain(Chain ch, Any val)
630 { Cell cell;
631 Cell prev = NULL;
632
633 for_cell(cell, ch)
634 { if ( cell->value == val )
635 { if ( prev )
636 answer(prev->value);
637 fail;
638 }
639
640 prev = cell;
641 }
642
643 fail;
644 }
645
646
647 status
forAllChain(Chain ch,Code code,BoolObj safe)648 forAllChain(Chain ch, Code code, BoolObj safe)
649 { int i = 1;
650 Any av[2];
651
652 if ( safe == OFF )
653 { Cell cell;
654
655 for_cell(cell, ch)
656 { av[0] = cell->value;
657 av[1] = toInt(i++);
658 if ( !forwardCodev(code, 2, av) )
659 fail;
660 }
661 } else
662 { Any obj;
663
664 for_chain(ch, obj,
665 { av[0] = obj;
666 av[1] = toInt(i++);
667 if ( !forwardCodev(code, 2, av) )
668 fail;
669 });
670 }
671
672 succeed;
673 }
674
675
676 status
forSomeChain(Chain ch,Code code,BoolObj safe)677 forSomeChain(Chain ch, Code code, BoolObj safe)
678 { Any av[2];
679 int i = 1;
680
681 if ( safe == OFF )
682 { Cell cell;
683
684 for_cell(cell, ch)
685 { av[0] = cell->value;
686 av[1] = toInt(i++);
687
688 forwardCodev(code, 2, av);
689 }
690 } else
691 { Any obj;
692
693 for_chain(ch, obj,
694 { av[0] = obj;
695 av[1] = toInt(i++);
696
697 forwardCodev(code, 2, av);
698 });
699 }
700
701 succeed;
702 }
703
704
705 Any
getFindChain(Chain ch,Code code)706 getFindChain(Chain ch, Code code)
707 { Cell cell;
708 Any av[2];
709 int i = 1;
710
711 for_cell(cell, ch)
712 { av[0] = cell->value;
713 av[1] = toInt(i++);
714
715 if ( forwardCodev(code, 2, av) )
716 answer(cell->value);
717 }
718
719 fail;
720 }
721
722
723 Chain
getFindAllChain(Chain ch,Code code)724 getFindAllChain(Chain ch, Code code)
725 { Chain result = answerObject(ClassChain, EAV);
726 Cell cell;
727 Any av[2];
728 int i = 1;
729
730 for_cell(cell, ch)
731 { av[0] = cell->value;
732 av[1] = toInt(i++);
733
734 if ( forwardCodev(code, 2, av) )
735 appendChain(result, cell->value);
736 }
737
738 answer(result);
739 }
740
741
742 static Chain
getMapChain(Chain ch,Function f)743 getMapChain(Chain ch, Function f)
744 { Chain result = answerObject(ClassChain, EAV);
745 Any av[2];
746 int i = 1;
747 Cell cell;
748
749 for_cell(cell, ch)
750 { Any rval;
751
752 av[0] = cell->value;
753 av[1] = toInt(i++);
754 if ( (rval = getForwardFunctionv(f, 2, av)) )
755 appendChain(result, rval);
756 }
757
758 answer(result);
759 }
760
761
762 static status
findChain(Chain ch,Code code)763 findChain(Chain ch, Code code)
764 { Cell cell;
765 Any av[2];
766 int i = 1;
767
768 for_cell(cell, ch)
769 { av[0] = cell->value;
770 av[1] = toInt(i++);
771
772 if ( forwardCodev(code, 2, av) )
773 { ch->current = cell;
774 succeed;
775 }
776 }
777 fail;
778 }
779
780
781 status
mergeChain(Chain ch,Chain ch2)782 mergeChain(Chain ch, Chain ch2)
783 { register Cell cell;
784 register Cell tail = ch->tail;
785
786 for_cell(cell, ch2)
787 { appendChain(ch, cell->value);
788 if ( cell == tail ) /* @ch ->merge @ch */
789 break;
790 }
791
792 succeed;
793 }
794
795
796 static status
unionChain(Chain ch,Chain ch2)797 unionChain(Chain ch, Chain ch2)
798 { register Cell cell;
799
800 for_cell(cell, ch2)
801 { if ( !memberChain(ch, cell->value) )
802 appendChain(ch, cell->value);
803 }
804 succeed;
805 }
806
807
808 static status
intersectionChain(Chain ch,Chain ch2)809 intersectionChain(Chain ch, Chain ch2)
810 { register Cell cell, c2;
811
812 for_cell_save(cell, c2, ch)
813 { if ( !memberChain(ch2, cell->value) )
814 deleteCellChain(ch, cell);
815 }
816 succeed;
817 }
818
819
820 static status
subtractChain(Chain ch,Chain ch2)821 subtractChain(Chain ch, Chain ch2)
822 { Cell cell, c2;
823
824 for_cell_save(cell, c2, ch)
825 { if ( memberChain(ch2, cell->value) )
826 deleteCellChain(ch, cell);
827 }
828 succeed;
829
830 }
831
832
833 status
replaceChain(Chain ch,Any obj1,Any obj2)834 replaceChain(Chain ch, Any obj1, Any obj2)
835 { Cell cell;
836
837 for_cell(cell, ch)
838 { if ( cell->value == obj1 )
839 cellValueChain(ch, PointerToInt(cell), obj2);
840 }
841
842 succeed;
843 }
844
845
846 static status
intersectsChain(Chain ch,Chain ch2)847 intersectsChain(Chain ch, Chain ch2)
848 { Cell cell;
849
850 for_cell(cell, ch)
851 { if ( memberChain(ch2, cell->value) )
852 succeed;
853 }
854
855 fail;
856 }
857
858
859 static status
equalChain(Chain ch,Chain ch2)860 equalChain(Chain ch, Chain ch2)
861 { Cell c1, c2;
862
863 if ( !instanceOfObject(ch2, ClassChain) )
864 fail;
865
866 for(c1 = ch->head, c2 = ch2->head;
867 notNil(c1) && notNil(c2);
868 c1 = c1->next, c2 = c2->next)
869 { if ( c1->value != c2->value )
870 fail;
871 }
872
873 if ( c1 == c2 ) /* should both be NIL */
874 succeed;
875
876 fail;
877 }
878
879
880 status
emptyChain(Chain ch)881 emptyChain(Chain ch)
882 { if ( isNil(ch) || isNil(ch->head) )
883 succeed;
884
885 fail;
886 }
887
888
889 Chain
getCopyChain(Chain ch)890 getCopyChain(Chain ch)
891 { if ( notNil(ch) )
892 { Chain r = answerObject(classOfObject(ch), EAV); /* Same class */
893 Cell cell;
894
895 for_cell(cell, ch)
896 appendChain(r, cell->value);
897
898 answer(r);
899 }
900
901 answer(NIL);
902 }
903
904
905 static Chain
getMergeChain(Chain ch,Chain ch2)906 getMergeChain(Chain ch, Chain ch2)
907 { register Cell cell;
908 Chain r;
909
910 r = answerObject(ClassChain, EAV);
911
912 for_cell(cell, ch)
913 appendChain(r, cell->value);
914 for_cell(cell, ch2)
915 appendChain(r, cell->value);
916
917 answer(r);
918 }
919
920
921 static Chain
getUnionChain(Chain ch,Chain ch2)922 getUnionChain(Chain ch, Chain ch2)
923 { register Cell cell;
924 Chain r;
925
926 r = answerObject(classOfObject(ch), EAV);
927
928 for_cell(cell, ch)
929 { if (memberChain(r, cell->value) != FAIL)
930 continue;
931 appendChain(r, cell->value);
932 }
933
934 for_cell(cell, ch2)
935 { if (memberChain(r, cell->value) != FAIL)
936 continue;
937 appendChain(r, cell->value);
938 }
939
940 answer(r);
941 }
942
943
944 static int
forwardCompareCode(Code c,Any o1,Any o2)945 forwardCompareCode(Code c, Any o1, Any o2)
946 { Any argv[2];
947
948 argv[0] = o1;
949 argv[1] = o2;
950
951 if ( isFunction(c) )
952 { Any r;
953
954 withArgs(2, argv, r = getExecuteFunction((Function)c));
955
956 if ( equalName(r, NAME_smaller) || (isInteger(r) && valInt(r) < 0) )
957 return -1;
958 else if ( r == NAME_equal || r == ZERO )
959 return 0;
960 else
961 return 1;
962 } else
963 { status r;
964
965 withArgs(2, argv, r = executeCode(c));
966
967 return r ? -1 : 1;
968 }
969 }
970
971
972 int
qsortCompareObjects(const void * o1,const void * o2)973 qsortCompareObjects(const void *o1, const void *o2)
974 { int rval = forwardCompareCode(qsortCompareCode, *((Any *) o1), *((Any *)o2));
975
976 DEBUG(NAME_sort, Cprintf("compare %s %s --> %d\n",
977 pp(*((Any *)o1)), pp(*((Any *)o2)), rval));
978
979 return qsortReverse ? -rval : rval;
980 }
981
982
983 status
sortChain(Chain ch,Code msg,BoolObj unique)984 sortChain(Chain ch, Code msg, BoolObj unique)
985 { if ( isDefault(msg) )
986 return sortNamesChain(ch, unique);
987 else
988 { int size = valInt(ch->size);
989 Any *buf = (Any *)alloca(sizeof(Any) * size);
990 Cell cell;
991 int i;
992 Code old = qsortCompareCode; /* make reentrant */
993
994 qsortCompareCode = msg;
995
996 i = 0;
997 for_cell(cell, ch)
998 { buf[i] = cell->value;
999 if ( isObject(buf[i]) )
1000 addRefObj(buf[i]);
1001 i++;
1002 }
1003 qsort(buf, size, sizeof(Any), qsortCompareObjects);
1004 clearChain(ch);
1005 for(i=0; i<size; i++)
1006 { if ( unique != ON ||
1007 i == 0 ||
1008 qsortCompareObjects(&buf[i-1], &buf[i]) != 0 )
1009 appendChain(ch, buf[i]);
1010 }
1011 for(i=0; i<size; i++)
1012 { if ( isObject(buf[i]) )
1013 { delRefObj(buf[i]);
1014 freeableObj(buf[i]);
1015 }
1016 }
1017
1018 qsortCompareCode = old;
1019 succeed;
1020 }
1021 }
1022
1023 typedef struct
1024 { CharArray name; /* name of object */
1025 Any object; /* the object */
1026 } scell, *Scell;
1027
1028
1029 static int
compare_names(const void * p1,const void * p2)1030 compare_names(const void *p1, const void *p2)
1031 { Scell s1 = (Scell)p1;
1032 Scell s2 = (Scell)p2;
1033
1034 return str_cmp(&s1->name->data, &s2->name->data);
1035 }
1036
1037
1038 status
sortNamesChain(Chain ch,BoolObj unique)1039 sortNamesChain(Chain ch, BoolObj unique)
1040 { int size = valInt(ch->size);
1041 Scell buf = (Scell)alloca(sizeof(scell) * size);
1042 Cell cell;
1043 int i;
1044 AnswerMark m;
1045
1046 markAnswerStack(m);
1047
1048 i = 0;
1049 for_cell(cell, ch)
1050 { buf[i].object = cell->value;
1051 if ( isObject(buf[i].object) ) addRefObj(buf[i].object);
1052 if ( instanceOfObject(cell->value, ClassCharArray) )
1053 buf[i].name = cell->value;
1054 else
1055 buf[i].name = getv(cell->value, NAME_printName, 0, NULL);
1056
1057 i++;
1058 }
1059 qsort(buf, size, sizeof(scell), compare_names);
1060 clearChain(ch);
1061 for(i=0; i<size; i++)
1062 { if ( unique != ON ||
1063 i == 0 ||
1064 compare_names(&buf[i-1], &buf[i]) != 0 )
1065 appendChain(ch, buf[i].object);
1066 }
1067 for(i=0; i<size; i++)
1068 { if ( isObject(buf[i].object) )
1069 { delRefObj(buf[i].object);
1070 freeableObj(buf[i].object);
1071 }
1072 }
1073
1074 rewindAnswerStack(m, NIL);
1075
1076 succeed;
1077 }
1078
1079
1080 Tuple
getCompleteNameChain(Chain ch,CharArray prefix,Function map,BoolObj ignore_case)1081 getCompleteNameChain(Chain ch, CharArray prefix, Function map,
1082 BoolObj ignore_case)
1083 { Chain matches = NIL;
1084 LocalString(common, prefix->data.s_iswide, LINESIZE);
1085 Cell cell;
1086
1087 for_cell(cell, ch)
1088 { Any obj = cell->value;
1089 string prt;
1090 status rval;
1091 /* get printable representation */
1092 if ( isNil(map) )
1093 rval = toString(obj, &prt);
1094 else if ( isDefault(map) )
1095 rval = toString(getv(obj, NAME_printName, 0, NULL), &prt);
1096 else
1097 rval = toString(getForwardFunctionv(map, 1, &obj), &prt);
1098
1099 if ( rval )
1100 { if ( ((ignore_case == ON && str_icase_prefix(&prt, &prefix->data)) ||
1101 (ignore_case != ON && str_prefix(&prt, &prefix->data))) &&
1102 prt.s_size < LINESIZE ) /* hit */
1103 { if ( isNil(matches) )
1104 { matches = answerObject(ClassChain, obj, EAV);
1105 str_cpy(common, &prt);
1106 } else
1107 { if ( ignore_case == ON )
1108 common->s_size = str_icase_common_length(&prt, common);
1109 else
1110 common->s_size = str_common_length(&prt, common);
1111
1112 appendChain(matches, obj);
1113 }
1114 }
1115 } else
1116 { errorPce(obj, NAME_noPrintName);
1117 fail;
1118 }
1119 }
1120
1121 if ( notNil(matches) )
1122 { str_pad(common);
1123 answer(answerObject(ClassTuple, matches, StringToString(common), EAV));
1124 } else
1125 fail;
1126 }
1127
1128
1129 Chain
getIntersectionChain(Chain ch,Chain ch2)1130 getIntersectionChain(Chain ch, Chain ch2)
1131 { register Cell cell;
1132 Chain r;
1133
1134 r = answerObject(classOfObject(ch), EAV);
1135
1136 for_cell(cell, ch)
1137 { if (memberChain(ch2, cell->value) != FAIL)
1138 appendChain(r, cell->value);
1139 }
1140
1141 answer(r);
1142 }
1143
1144
1145 Any
getHeadChain(Chain ch)1146 getHeadChain(Chain ch)
1147 { EXISTS(ch->head);
1148
1149 answer(ch->head->value);
1150 }
1151
1152
1153 Any
getDeleteHeadChain(Chain ch)1154 getDeleteHeadChain(Chain ch)
1155 { Any result;
1156
1157 EXISTS(ch->head);
1158 result = ch->head->value;
1159 if ( isObject(result) && !isProtectedObj(result) )
1160 { if ( isFreedObj(result) )
1161 { deleteHeadChain(ch);
1162 errorPce(ch, NAME_freedObject, result);
1163 fail;
1164 }
1165 addCodeReference(result);
1166 deleteHeadChain(ch);
1167 delCodeReference(result);
1168 pushAnswerObject(result);
1169 } else
1170 deleteHeadChain(ch);
1171
1172 answer(result);
1173 }
1174
1175
1176 Any
getTailChain(Chain ch)1177 getTailChain(Chain ch)
1178 { EXISTS(ch->tail);
1179
1180 answer(ch->tail->value);
1181 }
1182
1183
1184 static Chain
getSubChain(Chain ch,Int start,Int end)1185 getSubChain(Chain ch, Int start, Int end)
1186 { int f, t;
1187 Chain r = answerObject(classOfObject(ch), EAV);
1188 int i = 0;
1189 Cell cell;
1190
1191 if ( isDefault(end) )
1192 end = ch->size;
1193 f = valInt(start);
1194 t = valInt(end);
1195
1196 for_cell(cell, ch)
1197 { if ( i>=f )
1198 { if ( i >= t )
1199 break;
1200
1201 appendChain(r, cell->value);
1202 }
1203
1204 i++;
1205 }
1206
1207 answer(r);
1208 }
1209
1210
1211
1212 static status
uniqueChain(Chain ch)1213 uniqueChain(Chain ch)
1214 { Cell cell, cell2;
1215
1216 for_cell(cell, ch)
1217 { Cell next;
1218
1219 for (cell2=cell->next; notNil(cell2); cell2=next)
1220 { next = cell2->next;
1221
1222 if (cell2->value == cell->value)
1223 deleteCellChain(ch, cell2);
1224 }
1225 }
1226 succeed;
1227 }
1228
1229
1230 status
moveBeforeChain(Chain ch,Any obj1,Any obj2)1231 moveBeforeChain(Chain ch, Any obj1, Any obj2)
1232 { Cell cell;
1233
1234 if ( obj1 == obj2 )
1235 fail;
1236
1237 TRY( currentChain(ch, obj2) );
1238 cell = ch->current;
1239 addCodeReference(obj1);
1240 if ( !deleteChain(ch, obj1) )
1241 { delCodeReference(obj1);
1242 fail;
1243 }
1244 ch->current = cell;
1245 insertChain(ch, obj1);
1246 delCodeReference(obj1);
1247
1248 succeed;
1249 }
1250
1251
1252 status
moveAfterChain(Chain ch,Any obj1,Any obj2)1253 moveAfterChain(Chain ch, Any obj1, Any obj2)
1254 { Cell cell;
1255 int is_obj = isObject(obj1);
1256 status rval;
1257
1258 if ( notDefault(obj2) && notNil(obj2) )
1259 { if ( obj1 == obj2 || !currentChain(ch, obj2) )
1260 fail;
1261 cell = ch->current->next;
1262 if ( notNil(cell) && cell->value == obj1 )
1263 succeed; /* already true */
1264 } else
1265 { if ( obj1 == getHeadChain(ch) )
1266 succeed;
1267 cell = ch->head;
1268 }
1269
1270 if ( is_obj )
1271 addCodeReference(obj1);
1272
1273 if ( deleteChain(ch, obj1) )
1274 { ch->current = cell;
1275 insertChain(ch, obj1);
1276
1277 rval = SUCCEED;
1278 } else
1279 rval = FAIL;
1280
1281 if ( is_obj )
1282 delCodeReference(obj1);
1283
1284 return rval;
1285 }
1286
1287
1288 status
beforeChain(Chain ch,Any obj1,Any obj2)1289 beforeChain(Chain ch, Any obj1, Any obj2)
1290 { Cell cell;
1291 int i1 = 0, i2 = 0, i=1;
1292
1293 for_cell(cell, ch)
1294 { if ( cell->value == obj1 )
1295 i1 = i;
1296 if ( cell->value == obj2 )
1297 i2 = i;
1298
1299 if ( i1 && i2 )
1300 return (i1 < i2) ? SUCCEED : FAIL;
1301
1302 i++;
1303 }
1304
1305 return errorPce(NAME_noMember, !i1 ? obj1 : obj2);
1306 }
1307
1308
1309 static status
afterChain(Chain ch,Any obj1,Any obj2)1310 afterChain(Chain ch, Any obj1, Any obj2)
1311 { Cell cell;
1312 int i1 = 0, i2 = 0, i=1;
1313
1314 for_cell(cell, ch)
1315 { if ( cell->value == obj1 )
1316 i1 = i;
1317 if ( cell->value == obj2 )
1318 i2 = i;
1319
1320 if ( i1 && i2 )
1321 return (i1 > i2) ? SUCCEED : FAIL;
1322
1323 i++;
1324 }
1325
1326 return errorPce(NAME_noMember, !i1 ? obj1 : obj2);
1327 }
1328
1329
1330 Any
getNth1Chain(Chain ch,Int index)1331 getNth1Chain(Chain ch, Int index)
1332 { register Cell cell;
1333 register int n = valInt(index);
1334
1335 for_cell(cell, ch)
1336 { if (--n == 0)
1337 answer(cell->value);
1338 }
1339
1340 fail;
1341 }
1342
1343
1344 static status
nth1Chain(Chain ch,Int index,Any value)1345 nth1Chain(Chain ch, Int index, Any value)
1346 { register Cell cell;
1347 register int n = valInt(index);
1348
1349 for_cell(cell, ch)
1350 { if (--n == 0)
1351 return cellValueChain(ch, PointerToInt(cell), value);
1352 }
1353
1354 fail;
1355 }
1356
1357
1358 Any
getNth0Chain(Chain ch,Int index)1359 getNth0Chain(Chain ch, Int index)
1360 { register Cell cell;
1361 register int n = valInt(index);
1362
1363 for_cell(cell, ch)
1364 { if (n-- == 0)
1365 answer(cell->value);
1366 }
1367
1368 fail;
1369 }
1370
1371
1372 static status
nth0Chain(Chain ch,Int index,Any value)1373 nth0Chain(Chain ch, Int index, Any value)
1374 { register Cell cell;
1375 register int n = valInt(index);
1376
1377 for_cell(cell, ch)
1378 { if (n-- == 0)
1379 return cellValueChain(ch, PointerToInt(cell), value);
1380 }
1381
1382 fail;
1383 }
1384
1385
1386 static Int
getHeadCellChain(Chain ch)1387 getHeadCellChain(Chain ch)
1388 { if ( notNil(ch->head) )
1389 answer(PointerToInt(ch->head));
1390 fail;
1391 }
1392
1393
1394 static Int
getNextCellChain(Chain ch,Int c)1395 getNextCellChain(Chain ch, Int c)
1396 { Cell cell = (Cell) IntToPointer(c);
1397
1398 if ( notNil(cell->next) )
1399 answer(PointerToInt(cell->next));
1400
1401 fail;
1402 }
1403
1404
1405 static Any
getCellValueChain(Chain ch,Int c)1406 getCellValueChain(Chain ch, Int c)
1407 { Cell cell = (Cell) IntToPointer(c);
1408
1409 answer(cell->value);
1410 }
1411
1412
1413 status
cellValueChain(Chain ch,Int c,Any obj)1414 cellValueChain(Chain ch, Int c, Any obj)
1415 { Cell cell = (Cell) IntToPointer(c);
1416
1417 if ( cell->value != obj )
1418 { assignField((Instance) ch, &cell->value, obj);
1419 ChangedChain(ch, NAME_cell, getCellIndexChain(ch, cell));
1420 }
1421
1422 succeed;
1423 }
1424
1425
1426 Cell
getNth0CellChain(Chain ch,Int index)1427 getNth0CellChain(Chain ch, Int index)
1428 { register Cell cell;
1429 register int n = valInt(index);
1430
1431 for_cell(cell, ch)
1432 { if ( n-- == 0 )
1433 return cell;
1434 }
1435
1436 fail;
1437 }
1438
1439
1440 static Int
getCellIndexChain(Chain ch,Cell c)1441 getCellIndexChain(Chain ch, Cell c)
1442 { int i = 1;
1443 Cell cell;
1444
1445 for_cell(cell, ch)
1446 { if ( cell == c )
1447 answer(toInt(i));
1448 i++;
1449 }
1450
1451 fail;
1452 }
1453
1454
1455 Int
getIndexChain(Chain ch,Any obj)1456 getIndexChain(Chain ch, Any obj)
1457 { int n = 0;
1458 Cell cell;
1459
1460 for_cell(cell, ch)
1461 { n++;
1462 if (cell->value == obj)
1463 answer(toInt(n));
1464 }
1465
1466 fail;
1467 }
1468
1469
1470 Int
getArityChain(Chain ch)1471 getArityChain(Chain ch)
1472 { answer(getSizeChain(ch));
1473 }
1474
1475
1476 Any
getArgChain(Chain ch,Int arg)1477 getArgChain(Chain ch, Int arg)
1478 { answer(getNth1Chain(ch, arg));
1479 }
1480
1481
1482 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1483 Trapping changes to chains.
1484
1485 The following elementary changes to a chain are recognised and forwarded:
1486 NAME_insert, Index: Element is inserted at cell <Index>
1487 NAME_delete, Index: Element at index <Index> is deleted
1488 NAME_cell, Index: Element at index <Index> changed value
1489 NAME_clear: Chain has been cleared
1490 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1491
1492 static status
changedChain(Chain ch,Any * field)1493 changedChain(Chain ch, Any *field)
1494 { succeed;
1495 }
1496
1497 /*******************************
1498 * CLASS DECLARATION *
1499 *******************************/
1500
1501 /* Type declaractions */
1502
1503 static char *T_actionAcode_safeADboolD[] =
1504 { "action=code", "safe=[bool]" };
1505 static char *T_cellValue[] =
1506 { "cell_reference=int", "value=any" };
1507 static char *T_firstAany_secondAany[] =
1508 { "first=any", "second=any" };
1509 static char *T_indexAint_valueAany[] =
1510 { "index=int", "value=any" };
1511 static char *T_replace[] =
1512 { "old=any", "new=any" };
1513 static char *T_completeName[] =
1514 { "prefix=char_array", "extract_name=[function]*",
1515 "ignore_case=[bool]" };
1516 static char *T_moveAfter[] =
1517 { "value=any", "after=[any]" };
1518 static char *T_insertAfter[] =
1519 { "value=any", "after=any*" };
1520 static char *T_insertBefore[] =
1521 { "value=any", "before=any" };
1522 static char *T_moveBefore[] =
1523 { "value=any", "before=any" };
1524 static char *T_swap[] =
1525 { "value_1=any", "value_2=any" };
1526 static char *T_sort[] =
1527 { "compare=[code|function]", "unique=[bool]" };
1528 static char *T_gsub[] =
1529 { "start=int", "end=[int]" };
1530
1531 /* Instance Variables */
1532
1533 static vardecl var_chain[] =
1534 { IV(NAME_size, "int", IV_GET,
1535 NAME_cardinality, "Number of elements"),
1536 IV(NAME_head, "alien:Cell", IV_NONE,
1537 NAME_internal, "Pointer to first cell"),
1538 IV(NAME_tail, "alien:Cell", IV_NONE,
1539 NAME_internal, "Pointer to last cell"),
1540 IV(NAME_current, "alien:Cell", IV_NONE,
1541 NAME_internal, "Pointer to current cell")
1542 };
1543
1544 /* Send Methods */
1545
1546 static senddecl send_chain[] =
1547 { SM(NAME_initialise, 1, "member=any ...", initialiseChainv,
1548 DEFAULT, "Create a chain with initial elements"),
1549 SM(NAME_unlink, 0, NULL, unlinkChain,
1550 DEFAULT, "Clear the chain"),
1551 SM(NAME_empty, 0, NULL, emptyChain,
1552 NAME_cardinality, "Test if chain has no elements"),
1553 SM(NAME_cellValue, 2, T_cellValue, cellValueChain,
1554 NAME_cell, "Change value of cell"),
1555 SM(NAME_equal, 1, "chain", equalChain,
1556 NAME_compare, "Test if both chains have the same objects"),
1557 SM(NAME_current, 1, "value=any*", currentChain,
1558 NAME_current, "Make cell with `value' the current cell"),
1559 SM(NAME_currentNo, 1, "index=int", currentNoChain,
1560 NAME_current, "Set current cell to nth-1 (0: no current)"),
1561 SM(NAME_deleteCurrent, 0, NULL, deleteCurrentChain,
1562 NAME_current, "Delete current cell"),
1563 SM(NAME_find, 1, "test=code", findChain,
1564 NAME_current, "Set current to first cell accepted by code"),
1565 SM(NAME_insert, 1, "value=any", insertChain,
1566 NAME_current, "Insert argument before current"),
1567 SM(NAME_nth0, 2, T_indexAint_valueAany, nth0Chain,
1568 NAME_index, "Change content of nth (0-based) cell"),
1569 SM(NAME_nth1, 2, T_indexAint_valueAany, nth1Chain,
1570 NAME_index, "Change content of nth (1-based) cell"),
1571 SM(NAME_forAll, 2, T_actionAcode_safeADboolD, forAllChain,
1572 NAME_iterate, "Run code on all elements, demand acceptance ([safe])"),
1573 SM(NAME_forSome, 2, T_actionAcode_safeADboolD, forSomeChain,
1574 NAME_iterate, "Run code on all elements ([safe])"),
1575 SM(NAME_Append, 1, "value=any|function", appendChain,
1576 NAME_list, "Append argument to chain (not expanding obtainers)"),
1577 SM(NAME_append, 1, "value=any", appendChain,
1578 NAME_list, "Append argument to chain"),
1579 SM(NAME_clear, 0, NULL, clearChain,
1580 NAME_list, "Remove all elements from chain"),
1581 SM(NAME_truncate, 1, "keep=0..", truncateChain,
1582 NAME_list, "Keep the first N elements"),
1583 SM(NAME_delete, 1, "value=any", deleteChain,
1584 NAME_list, "Delete first occurrence of argument"),
1585 SM(NAME_deleteAll, 1, "value=any", deleteAllChain,
1586 NAME_list, "Delete all occurrences of argument"),
1587 SM(NAME_deleteHead, 0, NULL, deleteHeadChain,
1588 NAME_list, "Delete first element"),
1589 SM(NAME_deleteTail, 0, NULL, deleteTailChain,
1590 NAME_list, "Delete last element"),
1591 SM(NAME_insertAfter, 2, T_insertAfter, insertAfterChain,
1592 NAME_list, "Insert first after second object (@nil: prepend)"),
1593 SM(NAME_insertBefore, 2, T_insertBefore, insertBeforeChain,
1594 NAME_list, "Insert first before second object"),
1595 SM(NAME_merge, 1, "chain", mergeChain,
1596 NAME_list, "Append all elements from argument"),
1597 SM(NAME_prepend, 1, "value=any", prependChain,
1598 NAME_list, "Add argument as first element"),
1599 SM(NAME_replace, 2, T_replace, replaceChain,
1600 NAME_list, "Replace all occurrences"),
1601 SM(NAME_after, 2, T_firstAany_secondAany, afterChain,
1602 NAME_order, "Test if first argument is after second"),
1603 SM(NAME_before, 2, T_firstAany_secondAany, beforeChain,
1604 NAME_order, "Test if first argument is before second"),
1605 SM(NAME_moveAfter, 2, T_moveAfter, moveAfterChain,
1606 NAME_order, "Move 1st object just after second"),
1607 SM(NAME_moveBefore, 2, T_moveBefore, moveBeforeChain,
1608 NAME_order, "Move 1st object just before second"),
1609 SM(NAME_sort, 2, T_sort, sortChain,
1610 NAME_order, "Sort according to code (or name)"),
1611 SM(NAME_swap, 2, T_swap, swapChain,
1612 NAME_order, "Swap position of arguments"),
1613 SM(NAME_add, 1, "value=any", addChain,
1614 NAME_set, "Prepend object if not already ->member"),
1615 SM(NAME_intersection, 1, "chain", intersectionChain,
1616 NAME_set, "Delete elements not in argument"),
1617 SM(NAME_intersects, 1, "chain", intersectsChain,
1618 NAME_set, "Test if both chains have a common member"),
1619 SM(NAME_member, 1, "value=any", memberChain,
1620 NAME_set, "Test if argument is an element"),
1621 SM(NAME_subtract, 1, "chain", subtractChain,
1622 NAME_set, "Delete all elements in argument"),
1623 SM(NAME_union, 1, "chain", unionChain,
1624 NAME_set, "Append only new elements from argument"),
1625 SM(NAME_unique, 0, NULL, uniqueChain,
1626 NAME_set, "Remove all duplicates from chain")
1627 };
1628
1629 /* Get Methods */
1630
1631 static getdecl get_chain[] =
1632 { GM(NAME_cellValue, 1, "any", "cell_reference=int", getCellValueChain,
1633 NAME_cell, "Value for cell-reference"),
1634 GM(NAME_headCell, 0, "int", NULL, getHeadCellChain,
1635 NAME_cell, "Reference (int) to first cell"),
1636 GM(NAME_nextCell, 1, "cell_reference=int", "cell_reference=int", getNextCellChain,
1637 NAME_cell, "Reference to next cell at reference"),
1638 GM(NAME_completeName, 3, "tuple", T_completeName, getCompleteNameChain,
1639 NAME_completion, "New tuple with matches and common prefix"),
1640 GM(NAME_copy, 0, "chain", NULL, getCopyChain,
1641 NAME_copy, "New chain with same elements"),
1642 GM(NAME_convert, 1, "chain", "vector", getConvertChain,
1643 DEFAULT, "Convert array to linked list"),
1644 GM(NAME_current, 0, "any", NULL, getCurrentChain,
1645 NAME_current, "Value for the current cell"),
1646 GM(NAME_currentNo, 0, "int", NULL, getCurrentNoChain,
1647 NAME_current, "Index number of current cell (1-based)"),
1648 GM(NAME_index, 1, "index=int", "value=any", getIndexChain,
1649 NAME_index, "Index (1-based) at which argument is"),
1650 GM(NAME_next, 1, "any", "[any]", getNextChain,
1651 NAME_index, "Element after given value"),
1652 GM(NAME_nth0, 1, "value=any", "index=int", getNth0Chain,
1653 NAME_index, "Element at 0-based index"),
1654 GM(NAME_nth1, 1, "value=any", "index=int", getNth1Chain,
1655 NAME_index, "Element at 1-based index"),
1656 GM(NAME_previous, 1, "any", "[any]", getPreviousChain,
1657 NAME_index, "Element before given value"),
1658 GM(NAME_find, 1, "any", "test=code", getFindChain,
1659 NAME_iterate, "First element accepted by code"),
1660 GM(NAME_findAll, 1, "chain", "test=code", getFindAllChain,
1661 NAME_iterate, "New chain with elements accepted by code"),
1662 GM(NAME_map, 1, "chain", "function", getMapChain,
1663 NAME_iterate, "New chain with result of applying function"),
1664 GM(NAME_deleteHead, 0, "any", NULL, getDeleteHeadChain,
1665 NAME_list, "First element and delete it"),
1666 GM(NAME_head, 0, "any", NULL, getHeadChain,
1667 NAME_list, "First element"),
1668 GM(NAME_merge, 1, "chain", "chain", getMergeChain,
1669 NAME_list, "New chain holding concatenation"),
1670 GM(NAME_tail, 0, "value=any", NULL, getTailChain,
1671 NAME_list, "Last element"),
1672 GM(NAME_intersection, 1, "chain", "chain", getIntersectionChain,
1673 NAME_set, "New chain holding common elements"),
1674 GM(NAME_union, 1, "chain", "chain", getUnionChain,
1675 NAME_set, "New chain with union of elements"),
1676 GM(NAME_Arg, 1, "any", "index=int", getArgChain,
1677 NAME_term, "Nth-1 argument for object description"),
1678 GM(NAME_Arity, 0, "int", NULL, getArityChain,
1679 NAME_term, "Number of arguments for object description"),
1680 GM(NAME_sub, 2, "chain", T_gsub, getSubChain,
1681 NAME_list, "Get sub-chain from 0-based start and end")
1682 };
1683
1684 /* Resources */
1685
1686 #define rc_chain NULL
1687 /*
1688 static classvardecl rc_chain[] =
1689 {
1690 };
1691 */
1692
1693 /* Class Declaration */
1694
1695 ClassDecl(chain_decls,
1696 var_chain, send_chain, get_chain, rc_chain,
1697 ARGC_UNKNOWN, NULL,
1698 "$Rev$");
1699
1700
1701 status
makeClassChain(Class class)1702 makeClassChain(Class class)
1703 { declareClass(class, &chain_decls);
1704
1705 setLoadStoreFunctionClass(class, loadChain, storeChain);
1706 setCloneFunctionClass(class, cloneChain);
1707 setChangedFunctionClass(class, changedChain);
1708
1709 succeed;
1710 }
1711
1712