1 /* nl-liststr.c --- newLISP primitives handling lists and strings
4 Copyright (C) 2008 Lutz Mueller
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 extern CELL
* lastCellCopied
;
26 extern SYMBOL
* sysSymbol
[];
28 /* used only on string indices */
29 size_t adjustNegativeIndex(ssize_t index
, size_t length
)
31 if(index
< 0) index
= length
+ index
;
32 else if((index
+1) > length
) errorProc(ERR_STRING_INDEX_OUTOF_BOUNDS
);
34 if(index
< 0) errorProc(ERR_STRING_INDEX_OUTOF_BOUNDS
);
39 size_t adjustCount(ssize_t count
, ssize_t length
)
41 if(length
<= 1 || count
== 0 || length
== count
)
45 count
= count
% length
;
48 count
= -count
% length
;
49 count
= length
- count
;
55 extern char * strcasestr(char * haystack
, char * needle
);
57 CELL
* p_member(CELL
* params
)
66 key
= evaluateExpression(params
);
68 params
= params
->next
;
69 list
= evaluateExpression(params
);
71 if(params
->next
!= nilCell
)
72 getInteger(params
->next
, (UINT
*)&options
);
74 if(isList(list
->type
))
75 list
= (CELL
*)list
->contents
;
76 else if (list
->type
== CELL_STRING
)
78 if(key
->type
!= CELL_STRING
)
79 return(errorProcExt(ERR_STRING_EXPECTED
, params
));
82 ptr
= strstr((char *)list
->contents
, (char *) key
->contents
);
83 if(ptr
) return(stuffString(ptr
));
87 pos
= searchBufferRegex((char*)list
->contents
, 0, (char *)key
->contents
, list
->aux
- 1, options
, 0);
88 if(pos
!= -1) return(stuffString((char *)list
->contents
+ pos
));
93 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, params
->next
));
95 while(list
!= nilCell
)
97 if(compareCells(key
, list
) == 0) break;
101 if(list
== nilCell
) return(nilCell
);
102 member
= getCell(CELL_EXPRESSION
);
103 member
->contents
= (UINT
)copyList(list
);
107 CELL
* p_length(CELL
* params
)
112 params
= evaluateExpression(params
);
117 length
= sizeof(UINT
); break;
120 length
= sizeof(INT64
); break;
123 length
= sizeof(double); break;
125 length
= params
->aux
- 1; break;
128 symbol
= (SYMBOL
*)params
->contents
;
129 length
= strlen(symbol
->name
);
131 case CELL_DYN_SYMBOL
:
132 length
= strlen((char *)params
->contents
);
134 case CELL_EXPRESSION
:
137 length
= listlen((CELL
*)params
->contents
);
140 length
= (params
->aux
- 1) / sizeof(UINT
);
144 return(stuffInteger(length
));
148 CELL
* p_append(CELL
* params
)
151 CELL
* firstCell
= NULL
;
155 while(params
!= nilCell
)
157 cell
= evaluateExpression(params
);
158 if(!isList(cell
->type
))
162 if(cell
->type
== CELL_STRING
)
163 return(appendString(cell
, params
->next
, NULL
, 0, FALSE
, TRUE
));
164 else if(cell
->type
== CELL_ARRAY
)
165 return(appendArray(cell
, params
->next
));
166 return(errorProcExt(ERR_ARRAY_LIST_OR_STRING_EXPECTED
, params
));
169 return(errorProcExt(ERR_LIST_EXPECTED
, params
));
173 list
= getCell(cell
->type
);
175 copy
= copyList((CELL
*)cell
->contents
);
177 params
= params
->next
;
178 if(copy
== nilCell
) continue;
180 if(firstCell
== NULL
) list
->contents
= (UINT
)copy
;
181 else firstCell
->next
= copy
;
183 firstCell
= lastCellCopied
;
187 return(getCell(CELL_EXPRESSION
));
193 CELL
* appendString(CELL
* cell
, CELL
* list
, char * joint
, size_t jointLen
, int trailJoint
, int evalFlag
)
200 openStrStream(&stream
, MAX_LINE
, 0);
201 writeStreamStr(&stream
, (char *)cell
->contents
, cell
->aux
- 1);
202 while(list
!= nilCell
)
206 list
= getStringSize(list
, &sPtr
, &len
, evalFlag
);
207 writeStreamStr(&stream
, sPtr
, len
);
211 list
= getStringSize(list
, &sPtr
, &len
, FALSE
);
212 if(jointLen
) writeStreamStr(&stream
, joint
, jointLen
);
213 writeStreamStr(&stream
, sPtr
, len
);
218 writeStreamStr(&stream
, joint
, jointLen
);
220 result
= getCell(CELL_STRING
);
221 result
->contents
= (UINT
)allocMemory(stream
.position
+ 1);
222 *((char *)result
->contents
+ stream
.position
) = 0;
223 result
->aux
= stream
.position
+ 1;
224 memcpy((void *)result
->contents
, stream
.buffer
, stream
.position
);
226 closeStrStream(&stream
);
232 CELL
* p_chop(CELL
* params
)
242 params
= evaluateExpression(params
);
245 getInteger(next
, (UINT
*)&number
);
247 if(params
->type
== CELL_STRING
)
250 length
= params
->aux
- 1;
251 if(number
> length
) number
= length
;
252 length
= length
- number
;
253 return stuffStringN((char *)params
->contents
, length
);
255 length
= utf8_wlen((char *)params
->contents
);
256 if(number
> length
) number
= length
;
257 length
= length
- number
;
258 ptr
= (char *)params
->contents
;
260 ptr
+= utf8_1st_len(ptr
);
261 return stuffStringN((char *)params
->contents
, ptr
- (char *)params
->contents
);
265 if(!isList(params
->type
))
266 return(errorProc(ERR_LIST_OR_STRING_EXPECTED
));
268 length
= listlen((CELL
*)params
->contents
);
269 if(number
> length
) number
= length
;
271 return(sublist((CELL
*)params
->contents
, 0, length
- number
));
274 CELL
* setNthStr(CELL
* cellStr
, CELL
* new, ssize_t index
, int typeFlag
);
275 CELL
* setNth(CELL
* params
, int typeFlag
);
277 CELL
* p_nth(CELL
* params
) {return setNth(params
, 0);}
278 CELL
* p_nthSet(CELL
* params
) {return setNth(params
, 1);}
279 CELL
* p_setNth(CELL
* params
) {return setNth(params
, 2);}
281 CELL
* setNth(CELL
* params
, int typeFlag
)
288 /* new syntax, distinguished by type of first arg and number of args */
290 if( (params
->type
== CELL_EXPRESSION
) &&
291 ( (!typeFlag
&& next
== nilCell
) || (typeFlag
&& next
->next
== nilCell
) ))
293 params
= getList(params
, &list
, typeFlag
);
296 if(isList(list
->type
))
299 return(copyCell(implicitIndexList(list
, params
)));
300 else if(typeFlag
== 1)
301 return(updateCell(implicitIndexList(list
, params
), next
));
304 deleteList(updateCell(implicitIndexList(list
, params
), next
));
305 return(copyCell(list
));
309 else if(list
->type
== CELL_ARRAY
)
312 return(copyCell(implicitIndexArray(list
, params
)));
313 else if(typeFlag
== 1)
314 return(updateCell(implicitIndexArray(list
, params
), next
));
317 deleteList(updateCell(implicitIndexArray(list
, params
), next
));
318 return(copyCell(list
));
322 else if(list
->type
== CELL_STRING
)
324 getInteger(params
, (UINT
*)&index
);
325 return(setNthStr(list
, next
, index
, typeFlag
));
328 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, list
));
331 list
= evaluateExpression(params
);
332 if(!isNumber(list
->type
))
333 return(errorProcExt(ERR_NUMBER_EXPECTED
, params
));
335 while(isNumber(list
->type
))
339 cell
= getCell(CELL_EXPRESSION
);
340 cell
->contents
= (UINT
)copyCell(list
);
341 next
= (CELL
*)cell
->contents
;
345 next
->next
= copyCell(list
);
349 params
= params
->next
;
351 list
= evalCheckProtected(params
, NULL
);
353 list
= evaluateExpression(params
);
358 if(list
->type
== CELL_STRING
)
360 getInteger((CELL
*)cell
->contents
, (UINT
*)&index
);
362 return(setNthStr(list
, next
, index
, typeFlag
));
365 params
= getCell(CELL_QUOTE
);
366 params
->contents
= (UINT
)cell
;
370 goto NTH_EVAL_IMPLICIT
;
374 #define INSERT_BEFORE 0
375 #define INSERT_AFTER 1
377 CELL
* p_push(CELL
* params
)
383 int insert
= 0, evalFlag
= 0;
386 newCell
= evaluateExpression(params
);
387 params
= params
->next
;
389 if(isSymbol(params
->type
))
391 if(params
->type
== CELL_SYMBOL
)
392 sPtr
= (SYMBOL
*)params
->contents
;
394 sPtr
= getDynamicSymbol(params
);
396 if(isProtected(sPtr
->flags
))
397 return(errorProcExt(ERR_SYMBOL_PROTECTED
, params
));
399 if(!isList(((CELL
*)sPtr
->contents
)->type
))
401 if(isNil((CELL
*)sPtr
->contents
))
403 deleteList((CELL
*)sPtr
->contents
);
404 list
= getCell(CELL_EXPRESSION
);
405 sPtr
->contents
= (UINT
)list
; }
407 list
= (CELL
*)sPtr
->contents
;
410 list
= evalCheckProtected(params
, NULL
);
412 if(!isList(list
->type
))
414 if(list
->type
== CELL_STRING
)
415 return(pushOnString(newCell
, list
, params
->next
));
417 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, params
));
420 if(params
->next
== nilCell
)
422 params
= params
->next
;
427 cell
= ((CELL
*)params
->next
)->next
;
428 params
= evaluateExpression(params
->next
);
429 if(isList(params
->type
))
432 params
= getIntegerExt((CELL
*)params
->contents
, (UINT
*)&index
, FALSE
);
437 getIntegerExt(params
, (UINT
*)&index
, FALSE
);
444 if(params
== nilCell
)
446 newCell
= copyCell(newCell
);
447 cell
= (CELL
*)list
->aux
;
448 list
->aux
= (UINT
)newCell
;
449 if(cell
!= nilCell
&& cell
!= trueCell
)
451 cell
->next
= newCell
;
452 return(copyCell(newCell
));
455 if(list
->contents
== (UINT
)nilCell
)
457 list
->contents
= (UINT
)newCell
;
458 return(copyCell(newCell
));
461 list
= (CELL
*)list
->contents
;
462 while(list
->next
!= nilCell
)
464 list
->next
= newCell
;
465 return(copyCell(newCell
));
468 /* index = MAX_LONG; */
471 list
->aux
= (UINT
)nilCell
; /* undo last element optimization */
473 while(isList(list
->type
))
476 list
= (CELL
*)list
->contents
;
480 index
= listlen(list
) + index
;
481 if(index
== -1) index
= 0;
482 if(index
== 0) insert
= INSERT_BEFORE
;
483 else if(index
> 0) insert
= INSERT_AFTER
;
484 else errorProc(ERR_LIST_INDEX_OUTOF_BOUNDS
);
486 else insert
= INSERT_BEFORE
;
492 if(index
>= 0) errorProc(ERR_LIST_INDEX_OUTOF_BOUNDS
);
500 if(params
== nilCell
|| !isList(list
->type
)) break;
501 params
= getIntegerExt(params
, (UINT
*)&index
, evalFlag
);
504 newCell
= copyCell(newCell
);
505 if(insert
== INSERT_BEFORE
|| list
== nilCell
)
507 if(list
== (CELL
*)cell
->contents
)
509 cell
->contents
= (UINT
)newCell
;
510 newCell
->next
= list
;
514 cell
->next
= newCell
;
515 newCell
->next
= list
;
519 else if(insert
== INSERT_AFTER
|| insert
== INSERT_END
)
522 list
->next
= newCell
;
523 newCell
->next
= cell
;
526 return(copyCell(newCell
));
530 CELL
* p_pop(CELL
* params
)
535 int evalFlag
= FALSE
;
537 list
= evalCheckProtected(params
, NULL
);
539 if(!isList(list
->type
))
541 if(list
->type
== CELL_STRING
)
542 return(popString(list
, params
->next
));
544 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, params
));
547 /* leave last element optimization if popping first for queues */
548 if(params
->next
== nilCell
)
550 cell
= (CELL
*)list
->contents
;
551 list
->contents
= (UINT
)cell
->next
;
552 if(cell
->next
== nilCell
) /* check if only one element in list */
553 list
->aux
= (UINT
)nilCell
; /* undo last element optimization */
554 cell
->next
= nilCell
;
559 list
->aux
= (UINT
)nilCell
; /* undo last element optimization */
560 cell
= ((CELL
*)params
->next
)->next
;
561 params
= evaluateExpression(params
->next
);
562 if(isList(params
->type
))
565 params
= getIntegerExt((CELL
*)params
->contents
, (UINT
*)&index
, FALSE
);
570 getIntegerExt(params
, (UINT
*)&index
, FALSE
);
575 while(isList(list
->type
))
578 list
= (CELL
*)list
->contents
;
580 if(index
< 0) index
= convertNegativeOffset(index
, list
);
588 errorProc(ERR_LIST_INDEX_OUTOF_BOUNDS
);
590 if(params
== nilCell
|| !isList(list
->type
)) break;
591 params
= getIntegerExt(params
, (UINT
*)&index
, evalFlag
);
594 if(list
== (CELL
*)cell
->contents
)
595 cell
->contents
= (UINT
)list
->next
;
597 cell
->next
= list
->next
;
599 list
->next
= nilCell
;
604 CELL
* setNthStr(CELL
* cellStr
, CELL
* new, ssize_t index
, int typeFlag
)
608 size_t newLen
, oldLen
, len
;
611 oldStr
= (char*)cellStr
->contents
;
612 oldLen
= cellStr
->aux
- 1;
614 if(oldLen
== 0) return(copyCell(cellStr
));
618 index
= adjustNegativeIndex(index
, oldLen
);
621 return(stuffStringN(oldStr
+ index
, 1));
623 deleteList((CELL
*)sysSymbol
[0]->contents
);
624 sysSymbol
[0]->contents
= (UINT
)stuffStringN(oldStr
+ index
, 1);
629 index
= adjustNegativeIndex(index
, utf8_wlen((char *)cellStr
->contents
));
634 len
= utf8_1st_len(str
);
637 len
= utf8_1st_len(str
);
640 return(stuffStringN(str
, len
));
642 deleteList((CELL
*)sysSymbol
[0]->contents
);
643 sysSymbol
[0]->contents
= (UINT
)stuffStringN(str
, len
);
644 index
= str
- oldStr
;
648 getStringSize(new, &newStr
, &newLen
, TRUE
);
649 /* get back oldStr in case it changed during eval of replacement */
650 oldStr
= (char *)cellStr
->contents
;
651 oldLen
= cellStr
->aux
- 1;
652 if(oldLen
== 0) return(copyCell(cellStr
));
653 index
= adjustNegativeIndex(index
, oldLen
);
655 str
= allocMemory(oldLen
+ newLen
- len
+ 1);
656 *(str
+ oldLen
+ newLen
- len
) = 0;
658 memcpy(str
, oldStr
, index
);
659 memcpy(str
+ index
, newStr
, newLen
);
660 memcpy(str
+ index
+ newLen
, oldStr
+ index
+ len
, oldLen
- index
- len
);
662 cellStr
->contents
= (UINT
)str
;
663 cellStr
->aux
= oldLen
+ newLen
- len
+ 1;
667 new = stuffStringN(oldStr
+ index
, len
);
673 return(copyCell(cellStr
));
677 CELL
* popString(CELL
* str
, CELL
* params
)
686 return(stuffString(""));
688 if(params
!= nilCell
)
690 params
= getInteger(params
, (UINT
*)&index
);
691 if(params
!= nilCell
)
693 getInteger(params
, (UINT
*)&len
);
698 ptr
= (char *)str
->contents
;
701 index
= adjustNegativeIndex(index
, str
->aux
- 1);
703 index
= adjustNegativeIndex(index
, utf8_wlen(ptr
));
706 if((index
+ len
) > (str
->aux
- 2))
707 len
= str
->aux
- 1 - index
;
709 newPtr
= callocMemory(str
->aux
- len
);
711 memcpy(newPtr
, ptr
, index
);
712 memcpy(newPtr
+ index
, ptr
+ index
+ len
, str
->aux
- len
- index
);
713 str
->aux
= str
->aux
- len
;
714 str
->contents
= (UINT
)newPtr
;
715 result
= stuffStringN(ptr
+ index
, len
);
721 CELL
* pushOnString(CELL
* newStr
, CELL
* str
, CELL
* idx
)
733 if(idx
!= nilCell
) getInteger(idx
, (UINT
*)&index
);
734 ptr
= (char *)str
->contents
;
736 if(newStr
->type
!= CELL_STRING
)
737 return(errorProcExt(ERR_STRING_EXPECTED
, newStr
));
741 appendCellString(str
, (char *)newStr
->contents
, newStr
->aux
- 1);
742 return(copyCell(newStr
));
745 minusFlag
= (index
< 0);
750 len
= utf8_wlen(ptr
);
753 /* convert index into characters to skip before the new one is inserted */
754 if(index
< 0) index
= len
+ index
+ 1;
755 else if(index
> len
) index
= len
;
756 if(index
< 0) index
= 0;
758 newPtr
= callocMemory(str
->aux
+ newStr
->aux
- 1);
760 memcpy(newPtr
, ptr
, index
);
761 memcpy(newPtr
+ index
, (char*)newStr
->contents
, newStr
->aux
- 1);
762 memcpy(newPtr
+ index
+ newStr
->aux
- 1, ptr
+ index
, str
->aux
- index
);
765 while(index
--) /* skip characters to split point) */
766 sptr
= utf8_wchar(sptr
, &wChar
);
767 memcpy(newPtr
, ptr
, sptr
- ptr
);
768 memcpy(newPtr
+ (sptr
- ptr
), (char*)newStr
->contents
, newStr
->aux
- 1);
769 memcpy(newPtr
+ (sptr
- ptr
) + newStr
->aux
- 1, sptr
, str
->aux
- (sptr
- ptr
) );
772 str
->contents
= (UINT
)newPtr
;
773 str
->aux
= str
->aux
+ newStr
->aux
- 1;
774 *(newPtr
+ str
->aux
- 1) = 0;
777 return(copyCell(newStr
));
781 CELL
* p_select(CELL
* params
)
783 size_t n
= 0, idx
= 0;
786 CELL
* result
= NULL
;
789 char * str
, * newStr
;
796 head
= evaluateExpression(params
);
797 params
= params
->next
;
798 cell
= evaluateExpression(params
);
799 if(isList(cell
->type
))
802 cell
= params
= (CELL
*)cell
->contents
;
805 if(head
->type
== CELL_STRING
)
807 if((n
= listlen(params
)) == 0) return(stuffString(""));
809 str
= (char *)head
->contents
;
811 newStr
= (char *)allocMemory(n
+ 1);
813 while(params
->type
!= CELL_NIL
)
817 getIntegerExt(cell
, (UINT
*)&index
, FALSE
);
818 params
= params
->next
;
821 params
= getIntegerExt(params
, (UINT
*)&index
, evalFlag
);
822 index
= adjustNegativeIndex(index
, head
->aux
-1);
823 *(newStr
+ idx
++) = *(str
+ index
);
827 wstr
= allocMemory(head
->aux
* sizeof(int));
828 len
= utf8_wstr(wstr
, str
, head
->aux
- 1);
829 wnewStr
= allocMemory((n
+ 1) * sizeof(int));
831 while(params
->type
!= CELL_NIL
)
835 getIntegerExt(cell
, (UINT
*)&index
, FALSE
);
836 params
= params
->next
;
839 params
= getIntegerExt(params
, (UINT
*)&index
, evalFlag
);
840 index
= adjustNegativeIndex(index
, len
);
841 *(wnewStr
+ idx
++) = *(wstr
+ index
);
844 newStr
= allocMemory(UTF8_MAX_BYTES
* n
+ 1);
845 n
= wstr_utf8(newStr
, wnewStr
, UTF8_MAX_BYTES
* n
);
846 newStr
= reallocMemory(newStr
, n
+ 1);
848 result
= getCell(CELL_STRING
);
850 result
->contents
= (UINT
)newStr
;
854 if(!isList(head
->type
))
855 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, head
));
856 head
= (CELL
*)head
->contents
;
859 while(params
->type
!= CELL_NIL
)
863 getIntegerExt(cell
, (UINT
*)&index
, FALSE
);
864 params
= params
->next
;
867 params
= getIntegerExt(params
, (UINT
*)&index
, evalFlag
);
868 if(index
< 0) index
= convertNegativeOffset(index
, head
);
869 if(index
< idx
) list
= head
, idx
= 0;
870 while(idx
< index
&& list
->next
!= nilCell
) list
= list
->next
, idx
++;
873 result
= getCell(CELL_EXPRESSION
);
874 cell
= copyCell(list
);
875 result
->contents
= (UINT
)cell
;
879 cell
->next
= copyCell(list
);
884 return((result
== NULL
) ? getCell(CELL_EXPRESSION
) : result
);
888 CELL
* p_slice(CELL
* params
)
894 cell
= evaluateExpression(params
);
895 params
= getInteger(params
->next
, (UINT
*)&offset
);
896 if(params
!= nilCell
)
897 getInteger(params
, (UINT
*)&length
);
901 if(isList(cell
->type
))
902 return(sublist((CELL
*)cell
->contents
, offset
, length
));
903 else if(cell
->type
== CELL_STRING
)
904 return(substring((char *)cell
->contents
, cell
->aux
- 1, offset
, length
));
905 else if(cell
->type
== CELL_ARRAY
)
906 return(subarray(cell
, offset
, length
));
908 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, params
));
912 CELL
* sublist(CELL
* list
, ssize_t offset
, ssize_t length
)
918 offset
= convertNegativeOffset(offset
, list
);
922 length
= listlen(list
) - offset
+ length
;
923 if(length
< 0) length
= 0;
926 subList
= getCell(CELL_EXPRESSION
);
927 if(length
== 0) return(subList
);
929 while(offset
-- && list
!= nilCell
)
932 if(list
== nilCell
) return(subList
);
934 cell
= copyCell(list
);
935 subList
->contents
= (UINT
)cell
;
940 if(list
== nilCell
) break;
941 cell
->next
= copyCell(list
);
949 CELL
* p_reverse(CELL
* params
)
960 params
= evalCheckProtected(params
, NULL
);
963 if(isList(params
->type
))
965 params
->aux
= (UINT
)nilCell
; /* undo last element optimization */
967 previous
= cell
= (CELL
*)params
->contents
;
969 cell
->next
= nilCell
;
970 while(cell
!= nilCell
)
975 if(cell
!= nilCell
) cell
->next
= previous
;
977 params
->contents
= (UINT
)previous
;
980 else if(params
->type
== CELL_STRING
)
982 str
= (char *)params
->contents
;
983 len
= params
->aux
- 1;
985 right
= left
+ len
- 1;
995 else return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, cell
));
997 return(copyCell(params
));
1001 CELL
* p_join(CELL
* params
)
1003 char * joint
= NULL
;
1005 size_t jointLen
= 0;
1008 params
= getListHead(params
, &list
);
1010 return(stuffString(""));
1012 if(list
->type
!= CELL_STRING
)
1013 return(errorProcExt(ERR_STRING_EXPECTED
, list
));
1015 if(params
!= nilCell
)
1017 params
= getStringSize(params
, &joint
, &jointLen
, TRUE
);
1018 trailJoint
= getFlag(params
);
1021 return(appendString(list
, list
->next
, joint
, jointLen
, trailJoint
, FALSE
));
1025 CELL
* p_find(CELL
* params
)
1036 keyCell
= evaluateExpression(params
);
1037 params
= params
->next
;
1038 next
= evaluateExpression(params
);
1040 if(keyCell
->type
== CELL_STRING
&& next
->type
== CELL_STRING
)
1042 key
= (char *)keyCell
->contents
;
1043 second
= (char *)next
->contents
;
1044 size
= next
->aux
- 1;
1046 if(params
->next
!= nilCell
)
1048 params
= getInteger(params
->next
, (UINT
*)&options
);
1049 found
= searchBufferRegex(second
, 0, key
, (int)size
, options
, NULL
);
1050 if(found
== -1) return(nilCell
);
1054 found
= searchBuffer(second
, size
, key
, keyCell
->aux
- 1, TRUE
);
1055 if(found
== -1) return(nilCell
);
1060 /* list mode with optional functor */
1062 if(!isList(next
->type
)) return(nilCell
);
1063 next
= (CELL
*)next
->contents
;
1066 if(params
->next
!= nilCell
)
1067 funcCell
= evaluateExpression(params
->next
);
1068 else funcCell
= NULL
;
1070 /* do regex when first arg is string and option# is present */
1071 if(funcCell
&& isNumber(funcCell
->type
) && keyCell
->type
== CELL_STRING
)
1073 getIntegerExt(funcCell
, (UINT
*)&options
, FALSE
);
1074 key
= (char *)keyCell
->contents
;
1075 while(next
!= nilCell
)
1077 if(next
->type
== CELL_STRING
)
1079 second
= (char *)next
->contents
;
1080 if(searchBufferRegex(second
, 0, key
, next
->aux
- 1 , options
, NULL
) != -1)
1086 if(next
== nilCell
) return(nilCell
);
1087 else return(stuffInteger(found
));
1090 while(next
!= nilCell
)
1092 if(compareFunc(keyCell
, next
, funcCell
) == 0)
1096 deleteList((CELL
*)sysSymbol
[0]->contents
);
1097 sysSymbol
[0]->contents
= (UINT
)copyCell(next
);
1104 if(next
== nilCell
) return(nilCell
);
1107 return(stuffInteger(found
));
1110 /* ------- find-all ---- finds all strings matching a pattern in a list ----- */
1112 CELL
* findAllString(char * pattern
, char * str
, size_t size
, CELL
* params
)
1115 ssize_t findPos
= -1;
1118 CELL
* result
= nilCell
;
1125 params
= params
->next
;
1126 if(params
!= nilCell
)
1127 getInteger(params
, (UINT
*)&options
);
1129 while( (findPos
= searchBufferRegex(str
, offset
, pattern
, (int)size
, options
, &len
)) != -1)
1131 if(exprCell
!= nilCell
)
1133 if((exprRes
= evaluateExpressionSafe(exprCell
, &errNo
)) == NULL
)
1135 pushResult(result
); /* push for later deletion */
1136 longjmp(errorJump
, errNo
);
1138 exprRes
= copyCell(exprRes
);
1141 exprRes
= stuffStringN(str
+ findPos
, len
);
1143 if(findPos
== offset
&& len
== 0) break;
1145 if(result
== nilCell
)
1147 result
= getCell(CELL_EXPRESSION
);
1149 result
->contents
= (UINT
)cell
;
1153 cell
->next
= exprRes
;
1157 offset
= (findPos
+ len
);
1160 if(result
== nilCell
)
1161 return(getCell(CELL_EXPRESSION
));
1167 CELL
* findAllList(CELL
* pattern
, CELL
* list
, CELL
* exprCell
)
1169 CELL
* result
= nilCell
;
1177 funcCell
= evaluateExpression(exprCell
->next
);
1178 resultIdxSave
= resultStackIdx
;
1180 if(funcCell
== nilCell
&& !isList(pattern
->type
))
1181 return(errorProcExt(ERR_LIST_EXPECTED
, pattern
));
1183 while(list
!= nilCell
)
1185 if(funcCell
== nilCell
)
1187 /* match only takes lists*/
1188 if(!isList(list
->type
))
1191 match
= patternMatchL((CELL
*)pattern
->contents
, (CELL
*)list
->contents
, TRUE
);
1193 if(match
== NULL
|| match
== nilCell
)
1200 cleanupResults(resultIdxSave
);
1201 if(compareFunc(pattern
, list
, funcCell
) != 0)
1205 deleteList((CELL
*)sysSymbol
[0]->contents
);
1206 sysSymbol
[0]->contents
= (UINT
)copyCell(list
);
1208 if(exprCell
!= nilCell
)
1210 if((exprRes
= evaluateExpressionSafe(exprCell
, &errNo
)) == NULL
)
1212 pushResult(result
); /* push for later deletion */
1213 longjmp(errorJump
, errNo
);
1219 exprRes
= copyCell(exprRes
);
1222 if(result
== nilCell
)
1224 result
= getCell(CELL_EXPRESSION
);
1226 result
->contents
= (UINT
)cell
;
1230 cell
->next
= exprRes
;
1238 if(result
== nilCell
)
1239 return(getCell(CELL_EXPRESSION
));
1245 CELL
* p_findAll(CELL
* params
)
1250 key
= evaluateExpression(params
);
1251 params
= params
->next
;
1252 space
= evaluateExpression(params
);
1254 if(key
->type
== CELL_STRING
&& space
->type
== CELL_STRING
)
1255 return(findAllString((char *)key
->contents
,
1256 (char *)space
->contents
, (size_t) space
->aux
- 1, params
->next
));
1258 if(!isList(space
->type
))
1259 return(errorProcExt(ERR_LIST_EXPECTED
, space
));
1261 return(findAllList(key
, (CELL
*)space
->contents
, params
->next
));
1265 void swap(UINT
* left
, UINT
* right
)
1274 SYMBOL
* getSymbolCheckProtected(CELL
* params
)
1276 SYMBOL
* sPtr
= NULL
;
1278 if(params
->type
== CELL_DYN_SYMBOL
)
1279 sPtr
= getDynamicSymbol(params
);
1280 else if(params
->type
== CELL_SYMBOL
)
1281 sPtr
= (SYMBOL
*)params
->contents
;
1282 else fatalError(ERR_SYMBOL_EXPECTED
, params
, FALSE
);
1284 if(isProtected(sPtr
->flags
))
1285 fatalError(ERR_SYMBOL_PROTECTED
, params
, FALSE
);
1290 CELL
* p_swap(CELL
* params
)
1292 size_t first
, second
, num
;
1301 if(((CELL
*)params
->next
)->next
== nilCell
)
1303 lsym
= getSymbolCheckProtected(params
);
1304 rsym
= getSymbolCheckProtected(params
->next
);
1305 swap(&lsym
->contents
, &rsym
->contents
);
1306 return(copyCell((CELL
*)rsym
->contents
));
1309 params
= getInteger(params
, (UINT
*)&first
);
1310 params
= getInteger(params
, (UINT
*)&second
);
1312 envelope
= evalCheckProtected(params
, NULL
);
1314 if(envelope
->type
== CELL_STRING
)
1316 first
= adjustNegativeIndex(first
, envelope
->aux
- 1);
1317 second
= adjustNegativeIndex(second
, envelope
->aux
- 1);
1318 str
= (char *)envelope
->contents
;
1320 str
[first
] = str
[second
];
1322 return(copyCell(envelope
));
1325 if(!isList(envelope
->type
))
1326 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, params
));
1328 envelope
->aux
= (UINT
)nilCell
; /* undo last element optimization */
1330 list
= (CELL
*)envelope
->contents
;
1332 if(first
< 0) first
= convertNegativeOffset(first
, list
);
1333 if(second
< 0) second
= convertNegativeOffset(second
, list
);
1335 if(first
> second
) swap((UINT
*)&first
, (UINT
*)&second
);
1336 second
= second
- first
;
1341 if(firstCell
->next
== nilCell
) break;
1342 firstCell
= firstCell
->next
;
1344 secondCell
= firstCell
;
1348 if(secondCell
->next
== nilCell
) break;
1349 secondCell
= secondCell
->next
;
1352 swap(&firstCell
->type
, &secondCell
->type
);
1353 swap(&firstCell
->contents
, &secondCell
->contents
);
1354 swap(&firstCell
->aux
, &secondCell
->aux
);
1356 return(copyCell(envelope
));
1360 CELL
* p_dup(CELL
* params
)
1367 expr
= evaluateExpression(params
);
1368 params
= params
->next
;
1369 if(params
!= nilCell
)
1370 getInteger(params
, (UINT
*)&n
);
1375 if(expr
->type
== CELL_STRING
&& !getFlag(params
->next
) )
1377 len
= expr
->aux
- 1;
1378 list
= getCell(CELL_STRING
);
1379 str
= allocMemory(len
* n
+ 1);
1380 list
->contents
= (UINT
)str
;
1381 list
->aux
= (len
* n
+ 1);
1382 *(str
+ len
* n
) = 0;
1385 memcpy(str
, (char *)expr
->contents
, len
);
1391 list
= getCell(CELL_EXPRESSION
);
1394 list
->contents
= (UINT
)copyCell(expr
);
1396 params
= (CELL
*)list
->contents
;
1399 params
->next
= copyCell(expr
);
1400 params
= params
->next
;
1408 #define STARTS_WITH 0
1411 CELL
* startsEndsWith(CELL
* params
, int type
)
1419 CELL
* cell
, * list
;
1421 cell
= params
->next
;
1422 list
= evaluateExpression(params
);
1423 if(list
->type
== CELL_STRING
)
1425 string
= (char *)list
->contents
;
1426 getString(cell
, &key
);
1430 if(!isList(list
->type
))
1431 errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, params
);
1432 cell
= evaluateExpression(cell
);
1433 list
= (CELL
*)list
->contents
;
1435 if(type
== ENDS_WITH
)
1436 while(list
->next
!= nilCell
) list
= list
->next
;
1438 if(compareCells(list
, cell
) == 0) return(trueCell
);
1439 else return(nilCell
);
1442 if(cell
->next
!= nilCell
)
1444 if(evaluateExpression(cell
->next
)->type
== CELL_NIL
)
1447 getIntegerExt(cell
->next
, (UINT
*)&options
, FALSE
);
1451 slen
= strlen(string
);
1453 if(type
== STARTS_WITH
)
1457 if(strncmp(string
, key
, (size_t)klen
) == 0)
1462 if(searchBufferRegex(string
, 0, key
, slen
, options
, 0) == 0)
1469 if((options
== -1) && (klen
> slen
)) return(nilCell
);
1473 if(strncmp(string
+ slen
- klen
, key
, klen
) == 0)
1478 /* append $ to the pattern for anchoring at the end */
1479 keydollar
= malloc(klen
+ 4);
1481 memcpy(keydollar
+ 1, key
, klen
);
1482 memcpy(keydollar
+ 1 + klen
, ")$", 2);
1483 *(keydollar
+ klen
+ 3) = 0;
1485 if((pos
= searchBufferRegex(string
, 0, keydollar
, slen
, options
, &klen
)) != -1)
1488 if(pos
+ klen
== slen
)
1497 CELL
* p_startsWith(CELL
* params
) { return startsEndsWith(params
, STARTS_WITH
); }
1498 CELL
* p_endsWith(CELL
* params
) { return startsEndsWith(params
, ENDS_WITH
); }
1500 CELL
* p_replace(CELL
* params
)
1504 CELL
* funcCell
= NULL
;
1516 keyCell
= evaluateExpression(params
);
1517 params
= params
->next
;
1519 newList
= cell
= evalCheckProtected(params
, NULL
);
1523 resultIdxSave
= resultStackIdx
;
1524 if(isList(cell
->type
))
1526 cell
->aux
= (UINT
)nilCell
; /* undo last element optimization */
1528 list
= (CELL
*)cell
->contents
;
1530 if(params
->next
!= nilCell
)
1532 params
= params
->next
;
1534 if(params
->next
!= nilCell
)
1535 funcCell
= evaluateExpression(params
->next
);
1540 if(compareFunc(keyCell
, list
, funcCell
) == 0)
1544 deleteList((CELL
*)sysSymbol
[0]->contents
);
1545 sysSymbol
[0]->contents
= (UINT
)copyCell(list
);
1546 cell
->contents
= (UINT
)copyCell(evaluateExpression(repCell
));
1547 cell
= (CELL
*)cell
->contents
;
1548 cell
->next
= list
->next
;
1550 else /* remove mode */
1551 cell
->contents
= (UINT
)list
->next
;
1553 list
->next
= nilCell
;
1559 else /* remove mode */
1561 list
= (CELL
*)cell
->contents
;
1566 while(list
->next
!= nilCell
)
1568 if(compareFunc(keyCell
, list
->next
, funcCell
) == 0)
1570 cell
= list
->next
; /* cell = old elmnt */
1573 deleteList((CELL
*)sysSymbol
[0]->contents
);
1574 sysSymbol
[0]->contents
= (UINT
)copyCell(cell
);
1575 list
->next
= copyCell(evaluateExpression(repCell
));
1578 list
->next
= cell
->next
;
1579 cell
->next
= nilCell
;
1585 cleanupResults(resultIdxSave
);
1588 deleteList((CELL
*)sysSymbol
[0]->contents
);
1589 sysSymbol
[0]->contents
= (UINT
)stuffInteger(cnt
);
1590 return(copyCell(newList
));
1593 if(cell
->type
== CELL_STRING
)
1595 if(keyCell
->type
!= CELL_STRING
)
1596 return(errorProc(ERR_STRING_EXPECTED
));
1597 keyStr
= (char *)keyCell
->contents
;
1598 buff
= (char *)cell
->contents
;
1599 repCell
= params
->next
;
1601 if(repCell
== nilCell
)
1602 return(errorProc(ERR_MISSING_ARGUMENT
));
1605 if(repCell
->next
!= nilCell
)
1606 getInteger(repCell
->next
, (UINT
*)&options
);
1608 newBuff
= replaceString(keyStr
, keyCell
->aux
- 1,
1609 buff
, (size_t)cell
->aux
-1, repCell
, &cnt
, options
, &newLen
);
1613 cell
->contents
= (UINT
)newBuff
;
1614 cell
->aux
= newLen
+ 1;
1617 deleteList((CELL
*)sysSymbol
[0]->contents
);
1618 sysSymbol
[0]->contents
= (UINT
)stuffInteger(cnt
);
1619 return(copyCell(cell
));
1622 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, params
));
1627 CELL
* p_rotate(CELL
* params
)
1632 size_t length
, index
;
1637 if(cell
->next
!= nilCell
) getInteger(cell
->next
, (UINT
*)&count
);
1640 params
= evalCheckProtected(params
, NULL
);
1642 if(params
->type
== CELL_STRING
)
1644 cell
= copyCell(params
);
1645 length
= params
->aux
- 1;
1646 if((count
= adjustCount(count
, length
)) == 0) return(cell
);
1647 memcpy((char*)cell
->contents
, (char *)(params
->contents
+ length
- count
), count
);
1648 memcpy((char*)(cell
->contents
+ count
), (char *)params
->contents
, length
- count
);
1649 memcpy((char*)params
->contents
, (char*)cell
->contents
, length
);
1653 if(!isList(params
->type
))
1654 return(errorProcExt(ERR_LIST_EXPECTED
, cell
));
1656 params
->aux
= (UINT
)nilCell
; /* undo last element optimization */
1658 cell
= (CELL
*)params
->contents
;
1660 while(cell
!= nilCell
)
1667 if((count
= adjustCount(count
, length
))== 0)
1668 return(copyCell(params
));
1669 index
= length
- count
;
1671 previous
= cell
= (CELL
*)params
->contents
;
1678 previous
->next
= nilCell
;
1679 last
->next
= (CELL
*)params
->contents
;
1680 params
->contents
= (UINT
)cell
;
1682 return(copyCell(params
));