YAP 7.1.0
atomic.c
Go to the documentation of this file.
1/*************************************************************************
2 * *
3 * YAP Prolog *
4 * *
5 * Yap Prolog was developed at NCCUP - Universidade do Porto *
6 * *
7 * Copyright L.Damas, V. Santos Costa and Universidade do Porto 1985-- *
8 * *
9 **************************************************************************
10 * *
11 * File: atoms.c *
12 * comments: General-purpose C implemented system predicates *
13 * *
14 * Last rev: $Date: 2008-07-24 16:02:00 $,$Author: vsc $ *
15 * *
16 *************************************************************************/
17#ifdef SCCS
18static char SccsId[] = "%W% %G%";
19#endif
20
39#define HAS_CACHE_REGS 1
40
41#include "Yap.h"
42#include "YapEval.h"
43#include "YapHeap.h"
44#include "YapText.h"
45#include "Yatom.h"
46#include "yapio.h"
47#ifdef TABLING
48#include "tab.macros.h"
49#endif /* TABLING */
50#include <stdio.h>
51#if HAVE_STRING_H
52#include <string.h>
53#endif
54#if HAVE_MALLOC_H
55#include <malloc.h>
56#endif
57#include <wchar.h>
58
59static Int name(USES_REGS1);
60static Int atom_chars(USES_REGS1);
61static Int atom_codes(USES_REGS1);
62static Int atom_length(USES_REGS1);
63static Int string_length(USES_REGS1);
64static Int atom_split(USES_REGS1);
65static Int number_chars(USES_REGS1);
66static Int number_codes(USES_REGS1);
67static Int current_atom(USES_REGS1);
68static Int cont_current_atom(USES_REGS1);
69static int AlreadyHidden(unsigned char *);
70static Int hide_atom(USES_REGS1);
71static Int hidden_atom(USES_REGS1);
72static Int unhide_atom(USES_REGS1);
73
74static Int det_atom_concat3(USES_REGS1);
75
76static int AlreadyHidden(unsigned char *name) {
77 AtomEntry *chain;
78
79 READ_LOCK(INVISIBLECHAIN.AERWLock);
80 chain = RepAtom(INVISIBLECHAIN.Entry);
81 READ_UNLOCK(INVISIBLECHAIN.AERWLock);
82 while (!EndOfPAEntr(chain) &&
83 strcmp((char *)chain->StrOfAE, (char *)name) != 0)
84 chain = RepAtom(chain->NextOfAE);
85 if (EndOfPAEntr(chain))
86 return false;
87 return true;
88}
89
98static Int hide_atom(USES_REGS1) { /* hide(+Atom) */
99 Atom atomToInclude;
100 Term t1 = Deref(ARG1);
101
102 if (!Yap_IsGroundTerm(t1)) {
103 Yap_ThrowError(INSTANTIATION_ERROR, t1, "hide_atom/1");
104 return (FALSE);
105 }
106 if (!IsAtomTerm(t1)) {
107 Yap_ThrowError(TYPE_ERROR_ATOM, t1, "hide_atom/1");
108 return (FALSE);
109 }
110 atomToInclude = AtomOfTerm(t1);
111 if (AlreadyHidden(RepAtom(atomToInclude)->UStrOfAE)) {
112 Yap_ThrowError(SYSTEM_ERROR_INTERNAL, t1,
113 "an atom of name %s was already hidden",
114 RepAtom(atomToInclude)->StrOfAE);
115 return (FALSE);
116 }
117 AtomEntry *ae = RepAtom(atomToInclude);
118 Prop p = ae->PropsOfAE;
119 while (p) {
120 if (IsPredProperty(p->KindOfPE) || IsDBProperty(p->KindOfPE)) {
121 RepPredProp(p)->PredFlags |= HiddenPredFlag;
122
123 } else if (p->KindOfPE == FunctorProperty) {
124 Prop q = RepFunctorProp(p)->PropsOfFE;
125 while (q) {
126 if (IsPredProperty(q->KindOfPE) || IsDBProperty(q->KindOfPE)) {
127 RepPredProp(q)->PredFlags |= HiddenPredFlag;
128 }
129 q = q->NextOfPE;
130 }
131 }
132 p = p->NextOfPE;
133 }
134 Yap_ReleaseAtom(atomToInclude);
135 WRITE_LOCK(INVISIBLECHAIN.AERWLock);
136 WRITE_LOCK(RepAtom(atomToInclude)->ARWLock);
137 RepAtom(atomToInclude)->NextOfAE = INVISIBLECHAIN.Entry;
138 WRITE_UNLOCK(RepAtom(atomToInclude)->ARWLock);
139 INVISIBLECHAIN.Entry = atomToInclude;
140 WRITE_UNLOCK(INVISIBLECHAIN.AERWLock);
141 return (TRUE);
142}
143
148static Int hidden_atom(USES_REGS1) { /* '$hidden_atom'(+F) */
149 Atom at;
150 AtomEntry *chain;
151 Term t1 = Deref(ARG1);
152
153 if (!Yap_IsGroundTerm(t1))
154 return (FALSE);
155 if (IsAtomTerm(t1))
156 at = AtomOfTerm(t1);
157 else if (IsApplTerm(t1))
158 at = NameOfFunctor(FunctorOfTerm(t1));
159 else
160 return (FALSE);
161 READ_LOCK(INVISIBLECHAIN.AERWLock);
162 chain = RepAtom(INVISIBLECHAIN.Entry);
163 while (!EndOfPAEntr(chain) && AbsAtom(chain) != at)
164 chain = RepAtom(chain->NextOfAE);
165 READ_UNLOCK(INVISIBLECHAIN.AERWLock);
166 if (EndOfPAEntr(chain))
167 return (FALSE);
168 return (TRUE);
169}
170
178static Int unhide_atom(USES_REGS1) { /* unhide_atom(+Atom) */
179 AtomEntry *atom, *old, *chain;
180 Term t1 = Deref(ARG1);
181
182 if (!Yap_IsGroundTerm(t1)) {
183 Yap_ThrowError(INSTANTIATION_ERROR, t1, "unhide_atom/1");
184 return (FALSE);
185 }
186 if (!IsAtomTerm(t1)) {
187 Yap_ThrowError(TYPE_ERROR_ATOM, t1, "unhide_atom/1");
188 return (FALSE);
189 }
190 atom = RepAtom(AtomOfTerm(t1));
191 WRITE_LOCK(atom->ARWLock);
192 if (atom->PropsOfAE != NIL) {
193 Yap_ThrowError(SYSTEM_ERROR_INTERNAL, t1, "cannot unhide_atom an atom in use");
194 return (FALSE);
195 }
196 WRITE_LOCK(INVISIBLECHAIN.AERWLock);
197 chain = RepAtom(INVISIBLECHAIN.Entry);
198 old = NIL;
199 while (!EndOfPAEntr(chain) &&
200 strcmp((char *)chain->StrOfAE, (char *)atom->StrOfAE) != 0) {
201 old = chain;
202 chain = RepAtom(chain->NextOfAE);
203 }
204 if (EndOfPAEntr(chain))
205 return (FALSE);
206 atom->PropsOfAE = chain->PropsOfAE;
207 if (old == NIL)
208 INVISIBLECHAIN.Entry = chain->NextOfAE;
209 else
210 old->NextOfAE = chain->NextOfAE;
211 WRITE_UNLOCK(INVISIBLECHAIN.AERWLock);
212 WRITE_UNLOCK(atom->ARWLock);
213 return (TRUE);
214}
215
226static Int char_code(USES_REGS1) {
227 Int t0 = Deref(ARG1);
228 if (!Yap_IsGroundTerm(t0)) {
229 Term t1 = Deref(ARG2);
230 if (!Yap_IsGroundTerm(t1)) {
231 Yap_ThrowError(INSTANTIATION_ERROR, t0, "char_code/2");
232 return (FALSE);
233 } else if (!IsIntegerTerm(t1)) {
234 if (!IsBigIntTerm(t1)) {
235 Yap_ThrowError(REPRESENTATION_ERROR_INT, t1, "char_code/2");
236 return (FALSE);
237 }
238 Yap_ThrowError(TYPE_ERROR_INTEGER, t1, "char_code/2");
239 return (FALSE);
240 } else {
241 Int code = IntegerOfTerm(t1);
242 Term tout;
243
244 if (code < 0) {
245 Yap_ThrowError(REPRESENTATION_ERROR_CHARACTER_CODE, t1, "char_code/2");
246 return (FALSE);
247 }
248 if (code > MAX_ISO_LATIN1) {
249 unsigned char codes[10];
250
251 if (code > CHARCODE_MAX) {
252 Yap_ThrowError(REPRESENTATION_ERROR_INT, t1, "char_code/2");
253 return (FALSE);
254 }
255 size_t n = put_utf8(codes, code);
256 codes[n] = code;
257 tout = MkAtomTerm(Yap_ULookupAtom(codes));
258 } else {
259 char codes[2];
260
261 codes[0] = code;
262 codes[1] = '\0';
263 tout = MkAtomTerm(Yap_LookupAtom(codes));
264 }
265 return Yap_unify(ARG1, tout);
266 }
267 } else if (!IsAtomTerm(t0)) {
268 do_cut(true);
269 Yap_ThrowError(TYPE_ERROR_CHARACTER, t0, "char_code/2");
270 return (FALSE);
271 } else {
272 Atom at = AtomOfTerm(t0);
273 Term tf;
274 unsigned char *c = RepAtom(at)->UStrOfAE;
275 int32_t v = IntegerOfTerm(ARG1);
276
277 get_utf8(c, -1, &v);
278 if (!v)
279 return false;
280 tf = MkIntTerm(v);
281 return Yap_unify(ARG2, tf);
282 }
283}
284
314static Int name(USES_REGS1) { /* name(?Atomic,?String) */
315 Term t2 = Deref(ARG2), NewT, t1 = Deref(ARG1);
316 LOCAL_MAX_SIZE = 1024;
317 int l = push_text_stack();
318
319restart_aux:
320 if (Yap_IsGroundTerm(t1)) {
321 if (!!Yap_IsGroundTerm(t2) && !IsPairTerm(t2) && t2 != TermNil) {
322 Yap_ThrowError(TYPE_ERROR_LIST, ARG2, "name/2");
323 pop_text_stack(l);
324 return false;
325 }
326 // verify if an atom, int, float or bi§gnnum
327 NewT = Yap_AtomicToListOfCodes(t1 PASS_REGS);
328 if (NewT) {
329 pop_text_stack(l);
330 return Yap_unify(NewT, ARG2);
331 }
332 // else
333 } else if (!Yap_IsGroundTerm(t2)) {
334 Yap_ThrowError(INSTANTIATION_ERROR, t2, "name/2");
335 pop_text_stack(l);
336 return false;
337 } else {
338 Term at = Yap_ListToAtomic(t2 PASS_REGS);
339 if (at) {
340 pop_text_stack(l);
341 return Yap_unify(at, ARG1);
342 }
343 }
344 if (LOCAL_Error_TYPE) {
345 Yap_ThrowError(LOCAL_Error_TYPE,ARG1,"atom/2");
346 t1 = Deref(ARG1);
347 t2 = Deref(ARG2);
348 goto restart_aux;
349 }
350 pop_text_stack(l);
351 return false;
352}
353
363static Int string_to_atomic(
364 USES_REGS1) { /* string_to_atom(?String,?Atom) */
365 Term t1, t2;
366 bool v1, v2;
367 int l = push_text_stack();
368 t1 = Deref(ARG1);
369 t2 = Deref(ARG2);
370 v1 = !Yap_IsGroundTerm(t1);
371 v2 = !Yap_IsGroundTerm(t2);
372 if (v1 && v2)
373 {
374 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_c");
375 return false;
376 }
377 if (!v1) {
378 // ARG1 unbound: convert second argument to atom
379 if (!(t2 = Yap_AtomicToString(t2 PASS_REGS))) {
380 pop_text_stack(l);
381 return false;
382 }
383 }
384 if (!v1) {
385 // ARG1 unbound: convert second argument to atom
386 if (!IsStringTerm(t1)) {
387
388 pop_text_stack(l);
389 return false;
390 }
391 }
392 bool rc = Yap_unify(t1,t2);
393
394
395 pop_text_stack(l);
396 return rc;
397 }
398
399
401//
402// reverse to string_to_atomic(_Atomic_, _String_).
403// The second argument may be a sequence of codes or atoms.
404//
405static Int atomic_to_string(USES_REGS1) {
406 Term t1 = ARG1;
407 ARG1 = ARG2, ARG2 = t1;
408 return string_to_atomic(PASS_REGS1);
409}
410
412//
413// Verifies if (a) at least one of the argument is bound. If
414// _String_ is bound it must be a string term, list if codes, or
415// list of atoms, and _Atom_ musr be bound to a symbol with the
416// same text. Otherwise, _Atom_ must be an _Atom_ and _String_
417// will unify with a string term of the same text.
418//
419//
420static Int string_to_atom(USES_REGS1) { /* string_to_atom(?String,?Atom)
421 */
422 Term t1, t2;
423 bool v1, v2;
424 int l = push_text_stack();
425 t1 = Deref(ARG1);
426 t2 = Deref(ARG2);
427 v1 = !Yap_IsGroundTerm(t1);
428 v2 = !Yap_IsGroundTerm(t2);
429 if (v1 && v2)
430 {
431 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_codes");
432 return false;
433 }
434 if (v1) {
435 // ARG1 unbound: convert second argument to atom
436 t2 = (Yap_AtomSWIToString(t2 PASS_REGS));
437 pop_text_stack(l);
438 if (!t2) {
439 return false;
440 }
441 } else if (v2) {
442 t1 = MkAtomTerm(Yap_StringSWIToAtom(t1 PASS_REGS));
443 pop_text_stack(l);
444 if (!t1) {
445 return false;
446 }
447 } else {
448 // v1 bound
449 t1 = MkAtomTerm(Yap_AtomicToAtom(t1 PASS_REGS));
450 t2= MkAtomTerm(Yap_AtomicToAtom(t2 PASS_REGS));
451 pop_text_stack(l);
452 if (!t1 || !t2) {
453 return false;
454 }
455 }
456 return Yap_unify(t1,t2);
457}
458
460//
461// reverse to string_to_atom(_Atom_, _String_).
462// The second argument may be a sequence of codes or
463// atoms.
464//
465static Int atom_to_string(USES_REGS1) { /* string_to_atom(?String,?Atom)
466 */
467 Term t2 = ARG1;
468 ARG1 = ARG2;
469 ARG2 = t2;
470 return string_to_atom(PASS_REGS1);
471}
472
473static Int string_to_list(USES_REGS1) {
474 Term list = Deref(ARG2), string = Deref(ARG1);
475 LOCAL_MAX_SIZE = 1024;
476 int l = push_text_stack();
477
478restart_aux:
479 if (IsVarTerm(string)) {
480 Term t1 = Yap_ListToString(list PASS_REGS);
481 if (t1) {
482 pop_text_stack(l);
483 return Yap_unify(ARG1, t1);
484 }
485 } else if (IsStringTerm(string)) {
486 Term tf = Yap_StringToListOfCodes(string PASS_REGS);
487 {
488 pop_text_stack(l);
489 return Yap_unify(ARG2, tf);
490 }
491 } else {
492 LOCAL_Error_TYPE = TYPE_ERROR_STRING;
493 }
494 if (LOCAL_Error_TYPE && Yap_HandleError("string_to_list/2")) {
495 string = Deref(ARG1);
496 list = Deref(ARG2);
497 goto restart_aux;
498 }
499 {
500 pop_text_stack(l);
501 return false;
502 }
503}
504
506//
507// reverse to string_to_atom(_Atom_, _String_).
508// The second argument may be a sequence of codes or
509// atoms.
510//
511static Int atom_string(USES_REGS1) {
512 Term t1, t2;
513 bool v1, v2;
514 int l = push_text_stack();
515 t1 = Deref(ARG1);
516 t2 = Deref(ARG2);
517 v1 = !Yap_IsGroundTerm(t1);
518 v2 = !Yap_IsGroundTerm(t2);
519 if (v1 && v2)
520 {
521 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_codes");
522 return false;
523 }
524 if (v1) {
525 // ARG1 unbound: convert second argument to atom
526 t2 = MkAtomTerm(Yap_StringSWIToAtom(t2 PASS_REGS));
527 pop_text_stack(l);
528 if (!t2) {
529 return false;
530 }
531 } else if (v2) {
532 t1 = Yap_AtomicToString(t1 PASS_REGS);
533 pop_text_stack(l);
534 if (!t1) {
535 return false;
536 }
537 } else {
538 // v1 bound
539 t1 = Yap_AtomicToString(t1 PASS_REGS);
540 t2= MkAtomTerm(Yap_StringSWIToAtom(t2 PASS_REGS));
541 pop_text_stack(l);
542 if (!t1 || !t2) {
543 return false;
544 }
545 }
546 return Yap_unify(t1,t2);
547}
548
549// The second argument may be a sequence of codes or
550// atoms.
551//
552static Int string_atom(USES_REGS1) { /* string_to_atom(?String,?Atom)
553 */
554 Term t2 = ARG1;
555 ARG1 = ARG2;
556 ARG2 = t2;
557 return atom_string(PASS_REGS1);
558}
559
570static Int atom_chars(USES_REGS1) {
571 Term t1;
572 LOCAL_MAX_SIZE = 1024;
573 int l = push_text_stack();
574
575restart_aux:
576 t1 = Deref(ARG1);
577 if (IsAtomTerm(t1)) {
578 Term tf = Yap_AtomSWIToListOfAtoms(t1 PASS_REGS);
579 if (tf) {
580 pop_text_stack(l);
581 return Yap_unify(ARG2, tf);
582 }
583 } else if (!Yap_IsGroundTerm(t1)) {
584 /* ARG1 unbound */
585 Term t = Deref(ARG2);
586 Atom af = Yap_ListOfAtomsToAtom(t PASS_REGS);
587 if (af) {
588 pop_text_stack(l);
589 return Yap_unify(ARG1, MkAtomTerm(af));
590 }
591 /* error handling */
592 } else {
593 LOCAL_Error_TYPE = TYPE_ERROR_ATOM;
594 }
595 if (LOCAL_Error_TYPE && Yap_HandleError("atom_chars/2")) {
596 goto restart_aux;
597 }
598 {
599 pop_text_stack(l);
600 return false;
601 }
602}
603
628static Int atom_codes(USES_REGS1) {
629 Term t1, t2;
630 bool rc, v1, v2;
631 int l = push_text_stack();
632 t1 = Deref(ARG1);
633 t2 = Deref(ARG2);
634 v1 = !Yap_IsGroundTerm(t1);
635 v2 = !Yap_IsGroundTerm(t2);
636 if (v1 && v2)
637 {
638 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_codes");
639 return false;
640 }
641 if (v1) {
642 // ARG1 unbound: convert second argument to atom
643 rc = Yap_unify(t1,MkAtomTerm(Yap_ListToAtom(t2 PASS_REGS)));
644 } else if (v2) {
645 if (!(t1=Yap_AtomSWIToListOfCodes(t1 PASS_REGS)))
646 return false;
647 rc = Yap_unify(t1,t2);
648 } else {
649 Atom a1;
650 // v1 bound
651 if (!(a1=Yap_AtomicToAtom(t1 PASS_REGS)))
652 return false;
653 rc = a1 == Yap_ListToAtom(t2 PASS_REGS);
654
655 }
656 pop_text_stack(l);
657 return rc;
658}
659
660static Int string_codes(USES_REGS1) {
661 Term t1, t2;
662 bool rc, v1, v2;
663 int l = push_text_stack();
664 t1 = Deref(ARG1);
665 t2 = Deref(ARG2);
666 v1 = !Yap_IsGroundTerm(t1);
667 v2 = !Yap_IsGroundTerm(t2);
668 if (v1 && v2)
669 {
670 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_codes");
671 return false;
672 }
673 if (v1) {
674 // ARG1 unbound: convert second argument to atom
675 t2 = Yap_ListSWIToString(t2 PASS_REGS);
676 pop_text_stack(l);
677 if (!t2) {
678 return false;
679 }
680 } else if (v2) {
681 t1 = Yap_StringSWIToListOfCodes(t1 PASS_REGS);
682 pop_text_stack(l);
683 if (!t1) {
684 return false;
685 }
686 } else {
687 // v1 bound
688 t1 = Yap_AtomicToString(t1 PASS_REGS);
689 t2= Yap_ListSWIToString(t2 PASS_REGS);
690 pop_text_stack(l);
691 if (!t1 || !t2) {
692 return false;
693 }
694 }
695 rc = Yap_unify(t1,t2);
696 return rc;
697}
698
699static Int string_chars(USES_REGS1) {
700 Term t1, t2;
701 bool v1, v2;
702 int l = push_text_stack();
703 t1 = Deref(ARG1);
704 t2 = Deref(ARG2);
705 v1 = !Yap_IsGroundTerm(t1);
706 v2 = !Yap_IsGroundTerm(t2);
707 if (v1 && v2)
708 {
709 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_codes");
710 return false;
711 }
712 if (v1) {
713 // ARG1 unbound: convert second argument to atom
714 t2 = Yap_ListSWIToString(t2 PASS_REGS);
715 pop_text_stack(l);
716 if (!t2) {
717 return false;
718 }
719 } else if (v2) {
720 t1 = Yap_StringSWIToListOfAtoms(t1 PASS_REGS);
721 pop_text_stack(l);
722 if (!t1) {
723 return false;
724 }
725 } else {
726 // v1 bound
727 t1 = Yap_AtomicToString(t1 PASS_REGS);
728 t2= Yap_ListSWIToString(t2 PASS_REGS);
729 pop_text_stack(l);
730 if (!t1 || !t2) {
731 return false;
732 }
733
734 }
735
736 return Yap_unify(t1,t2);
737}
738
748static Int number_chars(USES_REGS1) {
749 Term t1, t2;
750 bool v1, v2;
751 int l = push_text_stack();
752 t1 = Deref(ARG1);
753 t2 = Deref(ARG2);
754 v1 = !Yap_IsGroundTerm(t1);
755 v2 = !Yap_IsGroundTerm(t2);
756 if (v1 && v2)
757 {
758 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_codes");
759 return false;
760 }
761 if (v1) {
762 // ARG1 unbound: convert second argument to atom
763 t2 = Yap_ListToNumber(t2 PASS_REGS);
764 pop_text_stack(l);
765 if (!t2) {
766 Yap_ThrowError(SYNTAX_ERROR, t2, "atom_codes");
767 return false;
768 }
769 } else if (v2) {
770 t1 = Yap_NumberToListOfAtoms(t1 PASS_REGS);
771 pop_text_stack(l);
772 if (!t1) {
773 return false;
774 }
775 } else {
776 // v1 bound
777 t2= Yap_ListToNumber(t2 PASS_REGS);
778 pop_text_stack(l);
779 if (!t1 || !t2) {
780 return false;
781 }
782 }
783 return Yap_unify(t1,t2);
784}
785
797static Int number_codes(USES_REGS1) {
798 Term t1, t2;
799 bool v1, v2;
800 int l = push_text_stack();
801 t1 = Deref(ARG1);
802 t2 = Deref(ARG2);
803 v1 = !Yap_IsGroundTerm(t1);
804 v2 = !Yap_IsGroundTerm(t2);
805 if (v1 && v2)
806 {
807 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_codes");
808 return false;
809 }
810 if (v1) {
811 // ARG1 unbound: convert second argument to atom
812 t2 = Yap_ListToNumber(t2 PASS_REGS);
813 pop_text_stack(l);
814 if (!t2) {
815 return false;
816 }
817 } else if (v2) {
818 t1 = Yap_NumberToListOfCodes(t1 PASS_REGS);
819 pop_text_stack(l);
820 if (!t1) {
821 return false;
822 }
823 } else {
824 // v1 bound
825 t2= Yap_ListToNumber(t2 PASS_REGS);
826 pop_text_stack(l);
827 if (!t1 || !t2) {
828 return false;
829 }
830 }
831 return Yap_unify(t1,t2);
832}
833
834
835
848static Int number_atom(USES_REGS1) {
849 Term t1, t2;
850 bool v1, v2;
851 int l = push_text_stack();
852 t1 = Deref(ARG1);
853 t2 = Deref(ARG2);
854 v1 = !Yap_IsGroundTerm(t1);
855 v2 = !Yap_IsGroundTerm(t2);
856 if (v1 && v2)
857 {
858 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_codes");
859 return false;
860 }
861
862 if (v1) {
863 // ARG1 unbound: convert second argument to atom
864 t2 = Yap_AtomToNumber(t2 PASS_REGS);
865 pop_text_stack(l);
866 if (!t2) {
867 return false;
868 }
869 } else if (v2) {
870 t1 = Yap_NumberToString(t1 PASS_REGS);
871 pop_text_stack(l);
872 if (!t1) {
873 return false;
874 }
875 } else {
876 // v1 bound
877 t2= Yap_AtomToNumber(t2 PASS_REGS);
878 pop_text_stack(l);
879 if (!t1 || !t2) {
880 return false;
881 }
882 }
883 return Yap_unify(t1,t2);
884 }
885
897static Int number_string(USES_REGS1) {
898 Term t1, t2;
899 bool v1, v2;
900 int l = push_text_stack();
901 t1 = Deref(ARG1);
902 t2 = Deref(ARG2);
903 v1 = !Yap_IsGroundTerm(t1);
904 v2 = !Yap_IsGroundTerm(t2);
905 if (v1 && v2)
906 {
907 Yap_ThrowError(INSTANTIATION_ERROR, t1, "atom_codes");
908 return false;
909 }
910 if (v1) {
911 // ARG1 unbound: convert second argument to atom
912 t2 =( Yap_AtomToNumber(t2 PASS_REGS) );
913 pop_text_stack(l);
914 if (!t2) {
915 return false;
916 }
917 } else if (v2) {
918 t1 = MkAtomTerm(Yap_NumberToAtom(t1 PASS_REGS));
919 pop_text_stack(l);
920 if (!t1) {
921 return false;
922 }
923 } else {
924 // v1 bound
925 t2=
926 ( Yap_AtomToNumber(t2 PASS_REGS) );
927 pop_text_stack(l);
928 if (!t1 || !t2) {
929 return false;
930 }
931 }
932 return Yap_unify(t1,t2);
933}
934
935
936static Int cont_atom_concat3(USES_REGS1) {
937 Term t3;
938 Atom ats[2];
939 Int i, max;
940restart_aux:
941 t3 = Deref(ARG3);
942 i = IntOfTerm(EXTRA_CBACK_ARG(3, 1));
943 max = IntOfTerm(EXTRA_CBACK_ARG(3, 2));
944 EXTRA_CBACK_ARG(3, 1) = MkIntTerm(i + 1);
945
946 int l = push_text_stack();
947 bool rc = Yap_SpliceAtom(t3, ats, i, max PASS_REGS);
948 pop_text_stack(l);
949 if (LOCAL_Error_TYPE == YAP_NO_ERROR) {
950 if (rc) {
951 if (i < max) {
952 return (Yap_unify(ARG1, MkAtomTerm(ats[0])) &&
953 Yap_unify(ARG2, MkAtomTerm(ats[1])));
954 }
955 return do_cut(Yap_unify(ARG1, MkAtomTerm(ats[0])) &&
956 Yap_unify(ARG2, MkAtomTerm(ats[1])));
957 } else {
958 cut_fail();
959 }
960 }
961 /* Error handling */
962 if (LOCAL_Error_TYPE) {
963 if (Yap_HandleError("atom_concat/3")) {
964 goto restart_aux;
965 }
966 cut_fail();
967 }
968 cut_fail();
969}
970
971static Int det_atom_concat3(USES_REGS1) {
972 Term t1;
973 Term t2, t3, o;
974 Atom at;
975 bool g1, g2, g3;
976 t1 = Deref(ARG1);
977 t2 = Deref(ARG2);
978 t3 = Deref(ARG3);
979 g1 = IsAtomTerm(t1) ? 1: 0;
980 if (!g1) {
981 if (IsNumTerm(t1)) {
982 t1 = MkAtomTerm(Yap_NumberToAtom(t1));
983 g1=1;
984 }
985 }
986 g2 = IsAtomTerm(t2) ? 1: 0;
987 if (!g2) {
988 if (IsNumTerm(t2)) {
989 t2 = MkAtomTerm(Yap_NumberToAtom(t2));
990 g2=1;
991 }
992 }
993 g3 = IsAtomTerm(t3) ? 1: 0;
994 int l = push_text_stack();
995 if (g1 && g2) {
996 if ((at=Yap_ConcatAtoms(t1, t2 PASS_REGS))) {
997 o = Yap_unify(t3,MkAtomTerm(at));
998 } else {
999 o = false;
1000 }
1001
1002 } else if (g1 && g3) {
1003 if ((at=Yap_SubtractHeadAtom(t3, t1 PASS_REGS))) {
1004 o = Yap_unify(t2,MkAtomTerm(at));
1005 } else {
1006 o = false;
1007 }
1008 } else if (g2 && g3) {
1009 if ((at=Yap_SubtractTailAtom(t3, t2 PASS_REGS))) {
1010 o = Yap_unify(t1,MkAtomTerm(at));
1011 } else {
1012 o = false;
1013 }
1014 } else {
1015 pop_text_stack(l);
1016 return false;
1017 }
1018 pop_text_stack(l);
1019 (o == true ? Yap_unify(ARG4,TermTrue) : Yap_unify(ARG4,TermFalse) );
1020 return true;
1021 }
1022
1023static Int non_det_atom_concat3(USES_REGS1) {
1024 Term t1;
1025 Term t2, t3, ot;
1026 Atom at;
1027
1028 int g1, g2, g3;
1029 int v1, v2, v3;
1030 t1 = Deref(ARG1);
1031 t2 = Deref(ARG2);
1032 t3 = Deref(ARG3);
1033 g1 = IsAtomTerm(t1) ? 1: 0;
1034 if (!g1) {
1035 if (IsNumTerm(t1)) {
1036 t1 = MkAtomTerm(Yap_NumberToAtom(t1));
1037 g1=1;
1038 }
1039 }
1040 g2 = IsAtomTerm(t2) ? 1: 0;
1041 if (!g2) {
1042 if (IsNumTerm(t2)) {
1043 t2 = MkAtomTerm(Yap_NumberToAtom(t2));
1044 g2=1;
1045 }
1046 }
1047 g3 = IsAtomTerm(t3) ? 1: 0;
1048 if (!g3) {
1049 if (IsNumTerm(t3)) {
1050 t3 = MkAtomTerm(Yap_NumberToAtom(t3));
1051 g3=1;
1052 }
1053 }
1054 v1 = !Yap_IsGroundTerm(t1) ? 1: 0;
1055 v2 = !Yap_IsGroundTerm(t2) ? 1: 0;
1056 v3 = !Yap_IsGroundTerm(t3) ? 1: 0;
1057 if (g3) {
1058 Int len = Yap_AtomToUnicodeLength(t3 PASS_REGS);
1059 if (len <= 0) {
1060 cut_fail();
1061 }
1062 EXTRA_CBACK_ARG(3, 1) = MkIntTerm(0);
1063 EXTRA_CBACK_ARG(3, 2) = MkIntTerm(len);
1064 { return cont_atom_concat3(PASS_REGS1); }
1065 } else {
1066 do_cut(true);
1067 if (g1+g2+g3+v1+v2+v3 == 3)
1068 Yap_ThrowError(INSTANTIATION_ERROR, v1 ? t1 : t2, "atom_concat");
1069 if (g1+v1 == 0)
1070 Yap_ThrowError(TYPE_ERROR_ATOM, t1, "atom_concat");
1071 if (g2+v2 == 0)
1072 Yap_ThrowError(TYPE_ERROR_ATOM, t2, "atom_concat");
1073 return false;
1074 }
1075 ot = ARG5;
1076 bool rc = at && Yap_unify(ot, MkAtomTerm(at));
1077 return rc;
1078}
1079
1080#define CastToNumeric(x) CastToNumeric__(x PASS_REGS)
1081
1082static Term CastToNumeric__(Atom at USES_REGS) {
1083 Term t;
1084 if ((t = Yap_AtomToNumber(MkAtomTerm(at) PASS_REGS))) {
1085 return t;
1086 } else {
1087 return MkAtomTerm(at);
1088 }
1089}
1090
1091static Int cont_atomic_concat3(USES_REGS1) {
1092 Term t3;
1093 Atom ats[2];
1094 size_t i, max;
1095restart_aux:
1096 t3 = Deref(ARG3);
1097 i = IntOfTerm(EXTRA_CBACK_ARG(3, 1));
1098 max = IntOfTerm(EXTRA_CBACK_ARG(3, 2));
1099 EXTRA_CBACK_ARG(3, 1) = MkIntTerm(i + 1);
1100 int l = push_text_stack();
1101 bool rc = Yap_SpliceAtom(t3, ats, i, max PASS_REGS);
1102 pop_text_stack(l);
1103 if (!rc) {
1104 cut_fail();
1105 } else {
1106 Term t1 = CastToNumeric(ats[0]);
1107 Term t2 = CastToNumeric(ats[1]);
1108 if (i < max) {
1109 return Yap_unify(ARG1, t1) && Yap_unify(ARG2, t2);
1110 }
1111 if (Yap_unify(ARG1, t1) && Yap_unify(ARG2, t2))
1112 cut_succeed();
1113 cut_fail();
1114 }
1115 /* Error handling */
1116 if (LOCAL_Error_TYPE) {
1117 if (Yap_HandleError("string_concat/3")) {
1118 goto restart_aux;
1119 } else {
1120 return false;
1121 }
1122 }
1123 cut_fail();
1124}
1125
1126static Int atomic_concat3(USES_REGS1) {
1127 Term t1;
1128 Term t2, t3, ot;
1129 Atom at = NULL;
1130 bool g1, g2, g3;
1131restart_aux:
1132 t1 = Deref(ARG1);
1133 t2 = Deref(ARG2);
1134 t3 = Deref(ARG3);
1135 g1 = Yap_IsGroundTerm(t1);
1136 g2 = Yap_IsGroundTerm(t2);
1137 g3 = Yap_IsGroundTerm(t3);
1138 if (g1 && g2) {
1139 int l = push_text_stack();
1140 at = Yap_ConcatAtomics(t1, t2 PASS_REGS);
1141 pop_text_stack(l);
1142 ot = ARG3;
1143 } else if (g1 && g3) {
1144 int l = push_text_stack();
1145 at = Yap_SubtractHeadAtom(t3, t1 PASS_REGS);
1146 pop_text_stack(l);
1147 ot = ARG2;
1148 } else if (g2 && g3) {
1149 int l = push_text_stack();
1150 at = Yap_SubtractTailAtom(t3, t2 PASS_REGS);
1151 pop_text_stack(l);
1152 ot = ARG1;
1153 } else if (g3) {
1154 Int len = Yap_AtomicToUnicodeLength(t3 PASS_REGS);
1155 if (len <= 0) {
1156 cut_fail();
1157 }
1158 EXTRA_CBACK_ARG(3, 1) = MkIntTerm(0);
1159 EXTRA_CBACK_ARG(3, 2) = MkIntTerm(len);
1160 return cont_atomic_concat3(PASS_REGS1);
1161 } else {
1162 LOCAL_Error_TYPE = INSTANTIATION_ERROR;
1163 at = NULL;
1164 }
1165 if (at) {
1166 if (Yap_unify(ot, MkAtomTerm(at))) {
1167 cut_succeed();
1168 } else {
1169 cut_fail();
1170 }
1171 }
1172 /* Error handling */
1173 if (LOCAL_Error_TYPE) {
1174 if (Yap_HandleError("atomic_concat/3")) {
1175 goto restart_aux;
1176 } else {
1177 return false;
1178 }
1179 }
1180 cut_fail();
1181}
1182
1183static Int cont_string_concat3(USES_REGS1) {
1184 Term t3;
1185 Term ts[2];
1186 size_t i, max;
1187restart_aux:
1188 t3 = Deref(ARG3);
1189 i = IntOfTerm(EXTRA_CBACK_ARG(3, 1));
1190 max = IntOfTerm(EXTRA_CBACK_ARG(3, 2));
1191 EXTRA_CBACK_ARG(3, 1) = MkIntTerm(i + 1);
1192 int l;
1193 l = push_text_stack();
1194 bool rc = Yap_SpliceString(t3, ts, i, max PASS_REGS);
1195 pop_text_stack(l);
1196 if (!rc) {
1197 cut_fail();
1198 } else {
1199 if (i < max) {
1200 return Yap_unify(ARG1, ts[0]) && Yap_unify(ARG2, ts[1]);
1201 }
1202 return do_cut(Yap_unify(ARG1, ts[0]) && Yap_unify(ARG2, ts[1]));
1203 cut_succeed();
1204 }
1205 /* Error handling */
1206 if (LOCAL_Error_TYPE) {
1207 if (Yap_HandleError("string_concat/3")) {
1208 goto restart_aux;
1209 } else {
1210 return FALSE;
1211 }
1212 }
1213 cut_fail();
1214}
1215
1216static Int string_concat3(USES_REGS1) {
1217 Term t1;
1218 Term t2, t3, ot;
1219 Term s;
1220
1221 int g1, g2, g3;
1222 int v1, v2, v3;
1223 t1 = Deref(ARG1);
1224 t2 = Deref(ARG2);
1225 t3 = Deref(ARG3);
1226 g1 = IsStringTerm(t1) ? 1: 0;
1227 g2 = IsStringTerm(t2) ? 1: 0;
1228 g3 = IsStringTerm(t3) ? 1: 0;
1229 v1 = !Yap_IsGroundTerm(t1) ? 1: 0;
1230 v2 = !Yap_IsGroundTerm(t2) ? 1: 0;
1231 v3 = !Yap_IsGroundTerm(t3) ? 1: 0;
1232 if (g1 && g2) {
1233 int l = push_text_stack();
1234 s = Yap_ConcatStrings(t1, t2 PASS_REGS);
1235 pop_text_stack(l);
1236 ot = ARG3;
1237 } else if (g1 && g3) {
1238 int l = push_text_stack();
1239 s = Yap_SubtractHeadString(t3, t1 PASS_REGS);
1240 pop_text_stack(l);
1241 ot = ARG2;
1242 } else if (g2 && g3) {
1243 int l = push_text_stack();
1244 s = Yap_SubtractTailString(t3, t2 PASS_REGS);
1245 pop_text_stack(l);
1246 ot = ARG1;
1247 } else if (g3) {
1248 Int len = Yap_StringToUnicodeLength(t3 PASS_REGS);
1249 if (len <= 0) {
1250 cut_fail();
1251 }
1252 EXTRA_CBACK_ARG(3, 1) = MkIntTerm(0);
1253 EXTRA_CBACK_ARG(3, 2) = MkIntTerm(len);
1254 { return cont_string_concat3(PASS_REGS1); }
1255 } else {
1256 do_cut(true);
1257 if (g1+g2+g3+v1+v2+v3 == 3)
1258 Yap_ThrowError(INSTANTIATION_ERROR, v1 ? t1 : t2, "string_concat");
1259 if (g1+v1 == 0)
1260 Yap_ThrowError(TYPE_ERROR_STRING, t1, "string_concat");
1261 if (g2+v2 == 0)
1262 Yap_ThrowError(TYPE_ERROR_STRING, t2, "string_concat");
1263 Yap_ThrowError(TYPE_ERROR_STRING, t3, "string_concat");
1264 return false;
1265 }
1266 if (s) {
1267 return do_cut(Yap_unify(ot, s) );
1268 }
1269 cut_fail();
1270}
1271
1272static Int cont_string_code3(USES_REGS1) {
1273 Term t2;
1274 Int i, j;
1275 utf8proc_int32_t chr;
1276 const unsigned char *s;
1277 const unsigned char *s0;
1278 int l;
1279 l = push_text_stack();
1280restart_aux:
1281 t2 = Deref(ARG2);
1282 s0 = UStringOfTerm(t2);
1283 i = IntOfTerm(
1284 EXTRA_CBACK_ARG(3, 1)); // offset in coded string, increases by 1..6
1285 j = IntOfTerm(EXTRA_CBACK_ARG(3, 2)); // offset in UNICODE
1286 // string, always
1287 // increases by 1
1288 s = (s0 + i) + get_utf8((unsigned char *)s0 + i, -1, &chr);
1289 if (s[0]) {
1290 EXTRA_CBACK_ARG(3, 1) = MkIntTerm(s - s0);
1291 EXTRA_CBACK_ARG(3, 2) = MkIntTerm(j + 1);
1292 return (Yap_unify(MkIntegerTerm(chr), ARG3) &&
1293 Yap_unify(MkIntegerTerm(j + 1), ARG1));
1294 }
1295 return do_cut(Yap_unify(MkIntegerTerm(chr), ARG3) &&
1296 Yap_unify(MkIntegerTerm(j), ARG1));
1297 /* Error handling */
1298 if (LOCAL_Error_TYPE) {
1299 if (Yap_HandleError("string_code/3")) {
1300 goto restart_aux;
1301 } else {
1302 {
1303 pop_text_stack(l);
1304 return false;
1305 }
1306 }
1307 }
1308 cut_fail();
1309}
1310
1311static Int string_code3(USES_REGS1) {
1312 Term t1;
1313 Term t2;
1314 const unsigned char *s;
1315 int l = push_text_stack();
1316restart_aux:
1317 t1 = Deref(ARG1);
1318 t2 = Deref(ARG2);
1319 if (!Yap_IsGroundTerm(t2)) {
1320 LOCAL_Error_TYPE = INSTANTIATION_ERROR;
1321 } else if (!IsStringTerm(t2)) {
1322 LOCAL_Error_TYPE = TYPE_ERROR_STRING;
1323 } else {
1324 s = UStringOfTerm(t2);
1325 t1 = Deref(ARG1);
1326 if (!Yap_IsGroundTerm(t1)) {
1327 EXTRA_CBACK_ARG(3, 1) = MkIntTerm(0);
1328 EXTRA_CBACK_ARG(3, 2) = MkIntTerm(0);
1329 {
1330 pop_text_stack(l);
1331 return cont_string_code3(PASS_REGS1);
1332 }
1333 } else if (!IsIntegerTerm(t1)) {
1334 LOCAL_Error_TYPE = TYPE_ERROR_INTEGER;
1335 } else {
1336 const unsigned char *ns = s;
1337 utf8proc_int32_t chr;
1338 Int indx = IntegerOfTerm(t1);
1339 if (indx <= 0) {
1340 if (indx < 0) {
1341 LOCAL_Error_TYPE = DOMAIN_ERROR_NOT_LESS_THAN_ZERO;
1342 }
1343 cut_fail();
1344 }
1345 ns = skip_utf8(s, indx);
1346 if (ns == NULL) {
1347 cut_fail(); // silently fail?
1348 }
1349 get_utf8(ns, -1, &chr);
1350 if (chr == '\0')
1351 cut_fail();
1352 if (Yap_unify(ARG3, MkIntegerTerm(chr)))
1353 cut_succeed();
1354 cut_fail();
1355 }
1356 }
1357 /* Error handling */
1358 if (LOCAL_Error_TYPE) {
1359 if (Yap_HandleError("string_code/3")) {
1360 goto restart_aux;
1361 } else {
1362 {
1363 pop_text_stack(l);
1364 return false;
1365 }
1366 }
1367 }
1368 cut_fail();
1369}
1370
1371static Int get_string_code3(USES_REGS1) {
1372 Term t1;
1373 Term t2;
1374 const unsigned char *s;
1375restart_aux:
1376 t1 = Deref(ARG1);
1377 t2 = Deref(ARG2);
1378 if (!Yap_IsGroundTerm(t2)) {
1379 LOCAL_Error_TYPE = INSTANTIATION_ERROR;
1380 } else if (!IsStringTerm(t2)) {
1381 LOCAL_Error_TYPE = TYPE_ERROR_STRING;
1382 } else {
1383 s = UStringOfTerm(t2);
1384 t1 = Deref(ARG1);
1385 if (!Yap_IsGroundTerm(t1)) {
1386 LOCAL_Error_TYPE = INSTANTIATION_ERROR;
1387
1388 } else if (!IsIntegerTerm(t1)) {
1389 LOCAL_Error_TYPE = TYPE_ERROR_INTEGER;
1390 } else {
1391 const unsigned char *ns = s;
1392 Int indx = IntegerOfTerm(t1);
1393
1394 if (indx <= 0) {
1395 if (indx < 0) {
1396 LOCAL_Error_TYPE = DOMAIN_ERROR_NOT_LESS_THAN_ZERO;
1397 } else {
1398 return false;
1399 }
1400 } else {
1401 indx -= 1;
1402 ns = skip_utf8(ns, indx);
1403 if (ns == NULL) {
1404 return false;
1405 }
1406 }
1407 utf8proc_int32_t chr;
1408 get_utf8(ns, -1, &chr);
1409 if (chr != '\0') {
1410 return Yap_unify(ARG3, MkIntegerTerm(chr));
1411 }
1412 return false;
1413 }
1414 } // replace by error cod )e
1415 /* Error handling */
1416 if (LOCAL_Error_TYPE) {
1417 if (Yap_HandleError("string_code/3")) {
1418 goto restart_aux;
1419 } else {
1420 return false;
1421 }
1422 }
1423 cut_fail();
1424}
1425
1426static Int atom_concat2(USES_REGS1) {
1427 Term t1;
1428 Term *tailp;
1429 Int n;
1430 int l = push_text_stack();
1431restart_aux:
1432 t1 = Deref(ARG1);
1433 n = Yap_SkipList(&t1, &tailp);
1434 if (*tailp != TermNil) {
1435 LOCAL_Error_TYPE = TYPE_ERROR_LIST;
1436 } else {
1437 seq_tv_t *inpv = (seq_tv_t *)Malloc(n * sizeof(seq_tv_t)), out;
1438 int i = 0;
1439 Atom at;
1440
1441 if (!inpv) {
1442 LOCAL_Error_TYPE = RESOURCE_ERROR_HEAP;
1443 goto error;
1444 }
1445
1446 while (t1 != TermNil) {
1447 inpv[i].type = YAP_STRING_ATOM|YAP_STRING_INT|YAP_STRING_FLOAT|YAP_STRING_BIG;
1448 inpv[i].val.t = HeadOfTerm(t1);
1449 i++;
1450 t1 = TailOfTerm(t1);
1451 }
1452 out.type = YAP_STRING_ATOM;
1453 if (!Yap_Concat_Text(n, inpv, &out PASS_REGS)) {
1454 goto error;
1455 }
1456 at = out.val.a;
1457 if (at) {
1458 pop_text_stack(l);
1459 return Yap_unify(ARG2, MkAtomTerm(at));
1460 }
1461 }
1462error:
1463 /* Error handling */
1464 if (LOCAL_Error_TYPE) {
1465 if (Yap_HandleError("atom_concat/2")) {
1466 goto restart_aux;
1467 } else {
1468 pop_text_stack(l);
1469 return false;
1470 }
1471 }
1472 pop_text_stack(l);
1473 cut_fail();
1474}
1475
1476static Int string_concat2(USES_REGS1) {
1477 Term t1;
1478 Term *tailp;
1479 char *buf;
1480 int l = push_text_stack();
1481
1482 t1 = Deref(ARG1);
1483 Yap_SkipList(&t1, &tailp);
1484 if (*tailp != TermNil) {
1485 do_cut(true);
1486 Yap_ThrowError(TYPE_ERROR_LIST,*tailp,"string_code/3");
1487 return false;
1488 } else {
1489 size_t nsz = 1;
1490 while (t1 != TermNil) {
1491 Term head = HeadOfTerm(t1);
1492 if (IsAtomTerm(head)) {
1493 nsz += strlen(RepAtom(AtomOfTerm(head))->StrOfAE);
1494 } else if (!IsStringTerm(head)) {
1495 do_cut(true);
1496 Yap_ThrowError(TYPE_ERROR_STRING,head,"string_concat/2");
1497 return false;
1498 } else {
1499 nsz += strlen(StringOfTerm(head) );
1500 }
1501 t1 = TailOfTerm(t1);
1502 }
1503 buf = Malloc(nsz);
1504 buf[0] = '\0';
1505 t1 = Deref(ARG1);
1506 while (t1 != TermNil) {
1507 Term head = HeadOfTerm(t1);
1508 if (IsAtomTerm(head)) {
1509 strcat(buf,RepAtom(AtomOfTerm(head))->StrOfAE);
1510 } else { strcat(buf,StringOfTerm(head));
1511 }
1512 t1 = TailOfTerm(t1);
1513 }
1514 Term t = MkStringTerm(buf);
1515 pop_text_stack(l);
1516 return Yap_unify(ARG2, t);
1517 }
1518}
1519
1520static Int atomic_concat2(USES_REGS1) {
1521 Term t1;
1522 Term *tailp;
1523 Int n;
1524 int l = push_text_stack();
1525restart_aux:
1526 t1 = Deref(ARG1);
1527 n = Yap_SkipList(&t1, &tailp);
1528 if (*tailp != TermNil) {
1529 LOCAL_Error_TYPE = TYPE_ERROR_LIST;
1530 } else {
1531 seq_tv_t *inpv = (seq_tv_t *)calloc(n , sizeof(seq_tv_t)), out;
1532 int i = 0;
1533 Atom at;
1534
1535 if (n == 1) {
1536 pop_text_stack(l);
1537 return Yap_unify(ARG2, HeadOfTerm(t1));
1538 }
1539 if (!inpv) {
1540 LOCAL_Error_TYPE = RESOURCE_ERROR_HEAP;
1541 free(inpv);
1542 goto error;
1543 }
1544 while (t1 != TermNil) {
1545 Term th = HeadOfTerm(t1);
1546 if (IsAtomTerm(th)) {
1547 inpv[i].type = YAP_STRING_ATOM|YAP_STRING_TERM;
1548 } else if (IsStringTerm(th)) {
1549 inpv[i].type = YAP_STRING_STRING|YAP_STRING_TERM;
1550 } else if (IsIntegerTerm(th)) {
1551 inpv[i].type = YAP_STRING_INT|YAP_STRING_TERM;
1552 } else if (IsFloatTerm(th)) {
1553 inpv[i].type = YAP_STRING_FLOAT|YAP_STRING_TERM;
1554 } else if (IsBigIntTerm(th)) {
1555 inpv[i].type = YAP_STRING_BIG|YAP_STRING_TERM;
1556 } else {
1557 inpv[i].type = YAP_STRING_CHARS |
1558 YAP_STRING_CODES|YAP_STRING_TERM;
1559 }
1560 inpv[i].val.t = th;
1561 i++;
1562 t1 = TailOfTerm(t1);
1563 }
1564 out.type = YAP_STRING_ATOM;
1565 if (!Yap_Concat_Text(n, inpv, &out PASS_REGS)) {
1566 free(inpv);
1567 goto error;
1568 }
1569 free(inpv);
1570 at = out.val.a;
1571 if (at) {
1572 pop_text_stack(l);
1573 return Yap_unify(ARG2, MkAtomTerm(at));
1574 }
1575 }
1576error:
1577 /* Error handling */
1578 if (LOCAL_Error_TYPE && Yap_HandleError("atom_concat/3")) {
1579 goto restart_aux;
1580 }
1581 {
1582 pop_text_stack(l);
1583 return FALSE;
1584 }
1585}
1586
1587static Int atomics_to_string2(USES_REGS1) {
1588 Term t1;
1589 Term *tailp;
1590 Int n;
1591 int l = push_text_stack();
1592restart_aux:
1593 t1 = Deref(ARG1);
1594 n = Yap_SkipList(&t1, &tailp);
1595 if (*tailp != TermNil) {
1596 LOCAL_Error_TYPE = TYPE_ERROR_LIST;
1597 } else {
1598 seq_tv_t *inpv = (seq_tv_t *)calloc(n, sizeof(seq_tv_t)), out;
1599 int i = 0;
1600 Atom at;
1601
1602 if (!inpv) {
1603 LOCAL_Error_TYPE = RESOURCE_ERROR_HEAP;
1604 free(inpv);
1605 goto error;
1606 }
1607
1608 while (t1 != TermNil) {
1609 inpv[i].type = YAP_STRING_STRING | YAP_STRING_ATOM | YAP_STRING_INT |
1610 YAP_STRING_FLOAT | YAP_STRING_BIG | YAP_STRING_TERM;
1611 inpv[i].val.t = HeadOfTerm(t1);
1612 i++;
1613 t1 = TailOfTerm(t1);
1614 }
1615 out.type = YAP_STRING_STRING;
1616 if (!Yap_Concat_Text(n, inpv, &out PASS_REGS)) {
1617 free(inpv);
1618 goto error;
1619 }
1620 free(inpv);
1621 at = out.val.a;
1622 if (at) {
1623 pop_text_stack(l);
1624 return Yap_unify(ARG2, MkAtomTerm(at));
1625 }
1626 }
1627error:
1628 /* Error handling */
1629 if (LOCAL_Error_TYPE && Yap_HandleError("atomics_to_string/2")) {
1630 goto restart_aux;
1631 }
1632 {
1633 pop_text_stack(l);
1634 return false;
1635 }
1636}
1637
1638static Int atomics_to_string3(USES_REGS1) {
1639 Term t1, t2;
1640 Term *tailp;
1641 Int n;
1642 int l = push_text_stack();
1643restart_aux:
1644 t1 = Deref(ARG1);
1645 t2 = Deref(ARG2);
1646 n = Yap_SkipList(&t1, &tailp);
1647 if (*tailp != TermNil) {
1648 LOCAL_Error_TYPE = TYPE_ERROR_LIST;
1649 } else {
1650 seq_tv_t *inpv = (seq_tv_t *)malloc((n * 2 - 1) * sizeof(seq_tv_t)), out;
1651 int i = 0;
1652 Atom at;
1653
1654 if (!inpv) {
1655 LOCAL_Error_TYPE = RESOURCE_ERROR_HEAP;
1656 free(inpv);
1657 goto error;
1658 }
1659
1660 while (t1 != TermNil) {
1661 inpv[i].type = YAP_STRING_STRING | YAP_STRING_ATOM | YAP_STRING_INT |
1662 YAP_STRING_FLOAT | YAP_STRING_BIG | YAP_STRING_TERM;
1663 inpv[i].val.t = HeadOfTerm(t1);
1664 i++;
1665 inpv[i].type = YAP_STRING_STRING | YAP_STRING_ATOM | YAP_STRING_INT |
1666 YAP_STRING_FLOAT | YAP_STRING_BIG | YAP_STRING_TERM;
1667 inpv[i].val.t = t2;
1668 i++;
1669 t1 = TailOfTerm(t1);
1670 }
1671 out.type = YAP_STRING_STRING;
1672 if (!Yap_Concat_Text(2 * n - 1, inpv, &out PASS_REGS)) {
1673 free(inpv);
1674 goto error;
1675 }
1676 free(inpv);
1677 at = out.val.a;
1678 if (at) {
1679 pop_text_stack(l);
1680 return Yap_unify(ARG3, MkAtomTerm(at));
1681 }
1682 }
1683error:
1684 /* Error handling */
1685 if (LOCAL_Error_TYPE && Yap_HandleError("atomics_to_string/3")) {
1686 goto restart_aux;
1687 }
1688 pop_text_stack(l);
1689 return false;
1690}
1691
1701static Int atom_length(USES_REGS1) {
1702 Term t1 = Deref(ARG1);
1703 Term t2 = Deref(ARG2);
1704 size_t len;
1705
1706 int l = push_text_stack();
1707 if (!Yap_IsGroundTerm(t1)) {
1708 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
1709 return false;
1710 } else if (!IsAtomTerm(t1)) {
1711 Yap_ThrowError(TYPE_ERROR_ATOM, t1, "at first argument");
1712 return false;
1713 }
1714
1715 if (Yap_IsGroundTerm(t2)) {
1716
1717 if (!IsIntegerTerm(t2)) {
1718 Yap_ThrowError(TYPE_ERROR_INTEGER, t2, "atom_length/2");
1719 {
1720 pop_text_stack(l);
1721 return false;
1722 };
1723 } else if ((Int)(len = IntegerOfTerm(t2)) < 0) {
1724 Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t2, "atom_length/2");
1725 {
1726 pop_text_stack(l);
1727 return false;
1728 };
1729 }
1730 }
1731restart_aux:
1732 len = Yap_AtomToUnicodeLength(t1 PASS_REGS);
1733 if (len != (size_t)-1) {
1734 pop_text_stack(l);
1735 return Yap_unify(ARG2, MkIntegerTerm(len));
1736 };
1737 /* error handling */
1738 if (LOCAL_Error_TYPE && Yap_HandleError("atom_length/2")) {
1739 goto restart_aux;
1740 }
1741 {
1742 pop_text_stack(l);
1743 return false;
1744 };
1745}
1746
1756static Int atomic_length(USES_REGS1) {
1757 Term t1 = Deref(ARG1);
1758 Term t2 = Deref(ARG2);
1759 size_t len;
1760
1761 int l = push_text_stack();
1762 if (!Yap_IsGroundTerm(t1)) {
1763 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
1764 {
1765 pop_text_stack(l);
1766 return false;
1767 };
1768 }
1769
1770 if (IsNonVarTerm(t2)) {
1771
1772 if (!IsIntegerTerm(t2)) {
1773 Yap_ThrowError(TYPE_ERROR_INTEGER, t2, "atom_length/2");
1774 {
1775 pop_text_stack(l);
1776 return false;
1777 };
1778 } else if ((Int)(len = IntegerOfTerm(t2)) < 0) {
1779 Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t2, "atom_length/2");
1780 {
1781 pop_text_stack(l);
1782 return false;
1783 };
1784 }
1785 }
1786restart_aux:
1787 len = Yap_AtomicToUnicodeLength(t1 PASS_REGS);
1788 if (len != (size_t)-1) {
1789 pop_text_stack(l);
1790 return Yap_unify(ARG2, MkIntegerTerm(len));
1791 };
1792 /* error handling */
1793 if (LOCAL_Error_TYPE && Yap_HandleError("atomic_length/2")) {
1794 goto restart_aux;
1795 }
1796 {
1797 pop_text_stack(l);
1798 return false;
1799 };
1800}
1801
1802static Int string_length(USES_REGS1) {
1803 Term t1;
1804 Term t2 = Deref(ARG2);
1805 size_t len;
1806
1807 int l = push_text_stack();
1808 if (Yap_IsGroundTerm(t2)) {
1809
1810 if (!IsIntegerTerm(t2)) {
1811 Yap_ThrowError(TYPE_ERROR_INTEGER, t2, "string_length/2");
1812 {
1813 pop_text_stack(l);
1814 return false;
1815 };
1816 }
1817 if (FALSE && (Int)(len = IntegerOfTerm(t2)) < 0) {
1818 Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t2, "string_length/2");
1819 {
1820 pop_text_stack(l);
1821 return false;
1822 };
1823 }
1824 }
1825restart_aux:
1826 t1 = Deref(ARG1);
1827 len = Yap_StringToUnicodeLength(t1 PASS_REGS);
1828 if (len != (size_t)-1) {
1829 pop_text_stack(l);
1830 return Yap_unify(ARG2, MkIntegerTerm(len));
1831 };
1832 /* error handling */
1833 if (LOCAL_Error_TYPE && Yap_HandleError("string_length/2")) {
1834 goto restart_aux;
1835 }
1836 {
1837 pop_text_stack(l);
1838 return false;
1839 };
1840}
1841
1849static Int downcase_text_to_atom(USES_REGS1) {
1850 Term t1 = Deref(ARG1);
1851 Term t2 = Deref(ARG2);
1852
1853 int l = push_text_stack();
1854 if (!Yap_IsGroundTerm(t1)) {
1855 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
1856 {
1857 pop_text_stack(l);
1858 return false;
1859 };
1860 }
1861
1862 if (IsNonVarTerm(t2)) {
1863 if (!IsAtomTerm(t2)) {
1864 Yap_ThrowError(TYPE_ERROR_ATOM, t2, "at second argument");
1865 {
1866 pop_text_stack(l);
1867 return (FALSE);
1868 };
1869 }
1870 }
1871 while (true) {
1872 Atom at = Yap_AtomicToLowAtom(t1);
1873 if (at == NULL) {
1874 if (LOCAL_Error_TYPE && Yap_HandleError("downcase_text_to_atom/2"))
1875 continue;
1876
1877 pop_text_stack(l);
1878 return false;
1879 }
1880
1881 pop_text_stack(l);
1882 return Yap_unify(MkAtomTerm(at), t2);
1883 }
1884 pop_text_stack(l);
1885 return false;
1886}
1887
1895static Int upcase_text_to_atom(USES_REGS1) {
1896 Term t1 = Deref(ARG1);
1897 Term t2 = Deref(ARG2);
1898
1899 int l = push_text_stack();
1900 if (!Yap_IsGroundTerm(t1)) {
1901 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
1902 {
1903 pop_text_stack(l);
1904 return false;
1905 };
1906 }
1907
1908 if (IsNonVarTerm(t2)) {
1909 if (!IsAtomTerm(t2)) {
1910 Yap_ThrowError(TYPE_ERROR_ATOM, t2, "at second argument");
1911 {
1912 pop_text_stack(l);
1913 return (FALSE);
1914 };
1915 }
1916 }
1917 while (true) {
1918 Atom at = Yap_AtomicToUpAtom(t1);
1919 if (at == NULL) {
1920 if (LOCAL_Error_TYPE && Yap_HandleError("upcase_text_to_atom/2"))
1921 continue;
1922 {
1923 pop_text_stack(l);
1924 return false;
1925 };
1926 }
1927 pop_text_stack(l);
1928 return Yap_unify(MkAtomTerm(at), t2);
1929 }
1930 {
1931 pop_text_stack(l);
1932 return false;
1933 };
1934}
1935
1943static Int downcase_text_to_string(USES_REGS1) {
1944 Term t1 = Deref(ARG1);
1945 Term t2 = Deref(ARG2);
1946
1947 if (!Yap_IsGroundTerm(t1)) {
1948 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
1949 return false;
1950 }
1951
1952 if (IsNonVarTerm(t2)) {
1953 if (!IsStringTerm(t2)) {
1954 Yap_ThrowError(TYPE_ERROR_STRING, t2, "at second argument");
1955 return (FALSE);
1956 }
1957 while (true) {
1958 Term t = Yap_AtomicToLowString(t1);
1959 if (t == TermZERO) {
1960 if (LOCAL_Error_TYPE && Yap_HandleError("downcase_text_to_string/2"))
1961 continue;
1962 { return false; };
1963 }
1964
1965 return Yap_unify(t, t2);
1966 }
1967 }
1968 return false;
1969}
1970
1978static Int upcase_text_to_string(USES_REGS1) {
1979 Term t1 = Deref(ARG1);
1980 Term t2 = Deref(ARG2);
1981
1982 if (!Yap_IsGroundTerm(t1)) {
1983 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
1984 return false;
1985 }
1986
1987 if (IsNonVarTerm(t2)) {
1988 if (!IsStringTerm(t2)) {
1989 Yap_ThrowError(TYPE_ERROR_STRING, t2, "at second argument");
1990 return (FALSE);
1991 }
1992 }
1993 int l = push_text_stack();
1994 while (true) {
1995 Term t = Yap_AtomicToUpString(t1);
1996
1997 if (t == TermZERO) {
1998 if (LOCAL_Error_TYPE && Yap_HandleError("upcase_text_to_string/2"))
1999 continue;
2000
2001 pop_text_stack(l);
2002
2003 return false;
2004 }
2005 pop_text_stack(l);
2006 return Yap_unify(t, t2);
2007 }
2008 pop_text_stack(l);
2009 return false;
2010}
2011
2019static Int downcase_text_to_codes(USES_REGS1) {
2020 Term t1 = Deref(ARG1);
2021 Term t2 = Deref(ARG2);
2022
2023 if (!Yap_IsGroundTerm(t1)) {
2024 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
2025 return false;
2026 }
2027
2028 if (IsNonVarTerm(t2)) {
2029 if (!Yap_IsListTerm(t2)) {
2030 Yap_ThrowError(TYPE_ERROR_LIST, t2, "at second argument");
2031 return false;
2032 }
2033 }
2034 int l = push_text_stack();
2035 while (true) {
2036 Term t = Yap_AtomicToLowListOfCodes(t1);
2037 if (t == TermZERO) {
2038 if (LOCAL_Error_TYPE && Yap_HandleError("downcase_text_to_codes/2"))
2039 continue;
2040 pop_text_stack(l);
2041 return false;
2042 }
2043 pop_text_stack(l);
2044 return Yap_unify(t, t2);
2045 }
2046 pop_text_stack(l);
2047 return false;
2048}
2049
2057static Int upcase_text_to_codes(USES_REGS1) {
2058 Term t1 = Deref(ARG1);
2059 Term t2 = Deref(ARG2);
2060
2061 if (!Yap_IsGroundTerm(t1)) {
2062 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
2063 return false;
2064 }
2065
2066 if (IsNonVarTerm(t2)) {
2067 if (!Yap_IsListTerm(t2)) {
2068 Yap_ThrowError(TYPE_ERROR_LIST, t2, "at second argument");
2069 return (FALSE);
2070 }
2071 }
2072 int l = push_text_stack();
2073 while (true) {
2074 Term t = Yap_AtomicToUpListOfCodes(t1);
2075 if (t == TermZERO) {
2076 if (LOCAL_Error_TYPE && Yap_HandleError("upcase_text_to_codes/2"))
2077 continue;
2078 pop_text_stack(l);
2079 return false;
2080 }
2081 pop_text_stack(l);
2082 return Yap_unify(t, t2);
2083 }
2084 pop_text_stack(l);
2085 return false;
2086}
2087
2095static Int downcase_text_to_chars(USES_REGS1) {
2096 Term t1 = Deref(ARG1);
2097 Term t2 = Deref(ARG2);
2098
2099 if (!Yap_IsGroundTerm(t1)) {
2100 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
2101 return false;
2102 }
2103
2104 if (IsNonVarTerm(t2)) {
2105 if (!Yap_IsListTerm(t2)) {
2106 Yap_ThrowError(TYPE_ERROR_LIST, t2, "at second argument");
2107 return false;
2108 }
2109 }
2110 int l = push_text_stack();
2111 while (true) {
2112 Term t = Yap_AtomicToLowListOfAtoms(t1);
2113
2114 if (t == TermZERO) {
2115 if (LOCAL_Error_TYPE && Yap_HandleError("downcase_text_to_to_chars/2"))
2116 continue;
2117 pop_text_stack(l);
2118 return false;
2119 }
2120 pop_text_stack(l);
2121 return Yap_unify(t, t2);
2122 }
2123 pop_text_stack(l);
2124 return false;
2125}
2126
2134static Int upcase_text_to_chars(USES_REGS1) {
2135 Term t1 = Deref(ARG1);
2136 Term t2 = Deref(ARG2);
2137
2138 if (!Yap_IsGroundTerm(t1)) {
2139 Yap_ThrowError(INSTANTIATION_ERROR, t1, "at first argument");
2140 return false;
2141 }
2142
2143 if (IsNonVarTerm(t2)) {
2144 if (!Yap_IsListTerm(t2)) {
2145 Yap_ThrowError(TYPE_ERROR_LIST, t2, "at second argument");
2146 return (FALSE);
2147 }
2148 }
2149 int l = push_text_stack();
2150 while (true) {
2151 Term t = Yap_AtomicToUpListOfAtoms(t1);
2152 if (t == TermZERO) {
2153 if (LOCAL_Error_TYPE && Yap_HandleError("upcase_text_to_chars/2"))
2154 continue;
2155 pop_text_stack(l);
2156 return false;
2157 }
2158 pop_text_stack(l);
2159 return Yap_unify(t, t2);
2160 }
2161 pop_text_stack(l);
2162 return false;
2163}
2164
2165/* split an atom into two sub-atoms */
2166static Int atom_split(USES_REGS1) {
2167 Term t1 = Deref(ARG1);
2168 Term t2 = Deref(ARG2);
2169 size_t u_mid;
2170 Term to1, to2;
2171 Atom at;
2172
2173 if (!Yap_IsGroundTerm(t1)) {
2174 Yap_ThrowError(INSTANTIATION_ERROR, t1, "$atom_split/4");
2175 return (FALSE);
2176 }
2177 if (!IsAtomTerm(t1)) {
2178 Yap_ThrowError(TYPE_ERROR_ATOM, t1, "$atom_split/4");
2179 return (FALSE);
2180 }
2181 if (!Yap_IsGroundTerm(t2)) {
2182 Yap_ThrowError(INSTANTIATION_ERROR, t2, "$atom_split/4");
2183 return (FALSE);
2184 }
2185 if (!IsIntTerm(t2)) {
2186 Yap_ThrowError(TYPE_ERROR_INTEGER, t2, "$atom_split/4");
2187 return (FALSE);
2188 }
2189 if ((Int)(u_mid = IntOfTerm(t2)) < 0) {
2190 Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t2, "atom_split/4");
2191 return (FALSE);
2192 }
2193 at = AtomOfTerm(t1);
2194 const char *s = RepAtom(at)->StrOfAE;
2195 const unsigned char *s0 = RepAtom(at)->UStrOfAE;
2196 unsigned char *s1, *s10;
2197 size_t u_len = strlen_utf8(s0);
2198 if (u_mid > u_len) {
2199 return false;
2200 }
2201 size_t b_mid = skip_utf8(s0, u_mid) - s0;
2202 s1 = s10 = Malloc(b_mid + 1);
2203 memcpy(s1, s, b_mid);
2204 s1[b_mid] = '\0';
2205 to1 = MkAtomTerm(Yap_ULookupAtom(s10));
2206 to2 = MkAtomTerm(Yap_ULookupAtom(s0 + b_mid));
2207 return Yap_unify_constant(ARG3, to1) && Yap_unify_constant(ARG4, to2);
2208}
2209
2221static Int atom_number(USES_REGS1) {
2222 Term t1;
2223 int l = push_text_stack();
2224restart_aux:
2225 t1 = Deref(ARG1);
2226 if (Yap_IsGroundTerm(t1)) {
2227 Term tf = Yap_AtomToNumber(t1 PASS_REGS);
2228 if (tf) {
2229 pop_text_stack(l);
2230 return Yap_unify(ARG2, tf);
2231 }
2232 } else {
2233 /* ARG1 unbound */
2234 Term t = Deref(ARG2);
2235 Atom af = Yap_NumberToAtom(t PASS_REGS);
2236 if (af) {
2237 pop_text_stack(l);
2238 return Yap_unify(ARG1, MkAtomTerm(af));
2239 }
2240 }
2241 /* error handling */
2242 if (LOCAL_Error_TYPE && Yap_HandleError("atom_number/2")) {
2243 t1 = Deref(ARG1);
2244 goto restart_aux;
2245 }
2246 pop_text_stack(l);
2247 return false;
2248}
2249
2261static Int string_number(USES_REGS1) {
2262 Term t1;
2263 int l = push_text_stack();
2264restart_aux:
2265 t1 = Deref(ARG1);
2266 if (Yap_IsGroundTerm(t1)) {
2267 Term tf = Yap_StringToNumber(t1 PASS_REGS);
2268 if (tf) {
2269
2270 pop_text_stack(l);
2271 return Yap_unify(ARG2, tf);
2272 }
2273 } else {
2274 /* ARG1 unbound */
2275 Term t = Deref(ARG2);
2276 Term tf = Yap_NumberToString(t PASS_REGS);
2277 if (tf) {
2278 pop_text_stack(l);
2279 return Yap_unify(ARG1, tf);
2280 }
2281 }
2282
2283 /* error handling */
2284 if (LOCAL_Error_TYPE && Yap_HandleError("string_number/2")) {
2285 t1 = Deref(ARG1);
2286 goto restart_aux;
2287 }
2288 pop_text_stack(l);
2289 return false;
2290}
2291
2292#define SUB_ATOM_HAS_MIN 1
2293#define SUB_ATOM_HAS_SIZE 2
2294#define SUB_ATOM_HAS_AFTER 4
2295#define SUB_ATOM_HAS_VAL 8
2296#define SUB_ATOM_HAS_ATOM 16
2297#define SUB_ATOM_HAS_UTF8 32
2298
2299static Term build_new_atomic(int mask, const unsigned char *p, size_t minv,
2300 size_t len USES_REGS) {
2301 int n;
2302 seq_tv_t outv[5], inp;
2303 size_t cuts[3];
2304 if (minv) {
2305 cuts[0] = minv;
2306 cuts[1] = minv + len;
2307 cuts[2] = 0;
2308 outv[0].type = 0;
2309 n = 1;
2310 } else {
2311 cuts[0] = minv + len;
2312 cuts[1] = 0;
2313 n = 0;
2314 }
2315 inp.type = YAP_STRING_CHARS;
2316 inp.enc = ENC_ISO_UTF8;
2317 inp.val.uc0 = p;
2318 outv[n + 1].type = 0;
2319 if (mask & SUB_ATOM_HAS_ATOM) {
2320 outv[n].type = YAP_STRING_ATOM;
2321 } else {
2322 outv[n].type = YAP_STRING_STRING;
2323 }
2324 bool rc = Yap_Splice_Text(2 + n, cuts, &inp, outv PASS_REGS);
2325 if (!rc) {
2326 return (false);
2327 }
2328 if (mask & SUB_ATOM_HAS_ATOM) {
2329 return (MkAtomTerm(outv[n].val.a));
2330 }
2331 return (outv[n].val.t);
2332}
2333
2334static bool check_sub_string_at(int minv, const unsigned char *p1,
2335 const unsigned char *p2, size_t len) {
2336 p1 = skip_utf8((unsigned char *)p1, minv);
2337 if (p1 == NULL || p2 == NULL)
2338 return p1 == p2;
2339 return cmpn_utf8(p1, p2, len) == 0;
2340}
2341
2342static bool check_sub_string_bef(int max, const unsigned char *p1,
2343 const unsigned char *p2) {
2344 size_t len = strlen_utf8(p2);
2345 int minv = max - len;
2346 int c2;
2347
2348 if ((Int)(minv) < 0)
2349 return FALSE;
2350
2351 p1 = skip_utf8(p1, minv);
2352 if (p1 == NULL || p2 == NULL)
2353 return p1 == p2;
2354 while ((c2 = *p2++) == *p1++ && c2)
2355 ;
2356 return c2 == 0;
2357}
2358
2359static Int cont_sub_atomic(USES_REGS1) {
2360 Term tat1 = Deref(ARG1);
2361 Term tat5 = Deref(ARG5);
2362 int mask;
2363 size_t minv, len, after, sz;
2364 const unsigned char *p = NULL, *p5 = NULL;
2365
2366 mask = IntegerOfTerm(EXTRA_CBACK_ARG(5, 1));
2367 minv = IntegerOfTerm(EXTRA_CBACK_ARG(5, 2));
2368 len = IntegerOfTerm(EXTRA_CBACK_ARG(5, 3));
2369 after = IntegerOfTerm(EXTRA_CBACK_ARG(5, 4));
2370 sz = IntegerOfTerm(EXTRA_CBACK_ARG(5, 5));
2371
2372 if (Yap_IsGroundTerm(tat1)) {
2373 if (IsAtomTerm(tat1)) {
2374 p = AtomOfTerm(tat1)->UStrOfAE;
2375 } else if (IsNumTerm(tat1)) {
2376 p = RepAtom(Yap_NumberToAtom(tat1 PASS_REGS))->UStrOfAE;
2377 } else {
2378 p = UStringOfTerm(tat1);
2379 }
2380 }
2381 if (Yap_IsGroundTerm(tat5)) {
2382 if (IsAtomTerm(tat5)) {
2383 p5 = AtomOfTerm(tat5)->UStrOfAE;
2384 } else if (IsNumTerm(tat5)) {
2385 p5 = RepAtom(Yap_NumberToAtom(tat5 PASS_REGS))->UStrOfAE;
2386 } else {
2387 p5 = UStringOfTerm(tat5);
2388 }
2389 }
2390 /* we can have one of two cases: A5 bound or unbound */
2391 if (mask & SUB_ATOM_HAS_VAL) {
2392 bool found = false;
2393 {
2394 const unsigned char *p1 = p;
2395
2396 while (!found && minv < sz-len) {
2397 if (minv)
2398 p = skip_utf8(p1, minv);
2399 else
2400 p = p1;
2401 if (cmpn_utf8(p, p5, len) == 0) {
2402 Yap_unify(ARG2, MkIntegerTerm(minv));
2403 Yap_unify(ARG3, MkIntegerTerm(len));
2404 Yap_unify(ARG4, MkIntegerTerm(after));
2405 found = true;
2406 /* found one, check if there is any left */
2407 while (minv <= sz - len) {
2408 int chr;
2409 p += get_utf8((unsigned char *)p, -1, &chr);
2410 after--;
2411 minv++;
2412 if (cmpn_utf8(p, p5, len) == 0)
2413 break;
2414 }
2415 } else {
2416 if (minv == sz - len)
2417 break;
2418 after--;
2419 minv++;
2420 }
2421 }
2422 }
2423 if (found) {
2424 if (minv > sz - len)
2425 cut_succeed();
2426
2427 } else {
2428 cut_fail();
2429 }
2430 } else if (mask & SUB_ATOM_HAS_SIZE) {
2431 Term nat = build_new_atomic(mask, p, minv, len PASS_REGS);
2432 Yap_unify(ARG2, MkIntegerTerm(minv));
2433 Yap_unify(ARG4, MkIntegerTerm(after));
2434 Yap_unify(ARG5, nat);
2435 minv++;
2436 if (after-- == 0) {
2437 cut_succeed();
2438 }
2439 } else if (mask & SUB_ATOM_HAS_MIN) {
2440 after = sz - (minv + len);
2441 Term nat = build_new_atomic(mask, p, minv, len PASS_REGS);
2442 Yap_unify(ARG3, MkIntegerTerm(len));
2443 Yap_unify(ARG4, MkIntegerTerm(after));
2444 Yap_unify(ARG5, nat);
2445 len++;
2446 if (after-- == 0) {
2447 cut_succeed();
2448 }
2449 } else if (mask & SUB_ATOM_HAS_AFTER) {
2450 len = sz - (minv + after);
2451 Term nat = build_new_atomic(mask, p, minv, len PASS_REGS);
2452 Yap_unify(ARG2, MkIntegerTerm(minv));
2453 Yap_unify(ARG3, MkIntegerTerm(len));
2454 Yap_unify(ARG5, nat);
2455 minv++;
2456 if (len-- == 0) {
2457 cut_succeed();
2458 }
2459 } else {
2460 Term nat = build_new_atomic(mask, p, minv, len PASS_REGS);
2461 Yap_unify(ARG2, MkIntegerTerm(minv));
2462 Yap_unify(ARG3, MkIntegerTerm(len));
2463 Yap_unify(ARG4, MkIntegerTerm(after));
2464 Yap_unify(ARG5, nat);
2465 len++;
2466 if (after-- == 0) {
2467 if (minv == sz) {
2468 cut_succeed();
2469 }
2470 minv++;
2471 len = 0;
2472 after = sz - minv;
2473 }
2474 }
2475 EXTRA_CBACK_ARG(5, 1) = MkIntegerTerm(mask);
2476 EXTRA_CBACK_ARG(5, 2) = MkIntegerTerm(minv);
2477 EXTRA_CBACK_ARG(5, 3) = MkIntegerTerm(len);
2478 EXTRA_CBACK_ARG(5, 4) = MkIntegerTerm(after);
2479 EXTRA_CBACK_ARG(5, 5) = MkIntegerTerm(sz);
2480
2481 return TRUE;
2482}
2483
2484static Int sub_atomic(bool sub_atom, bool sub_string USES_REGS) {
2485 Term tat1, tbef, tsize, tafter, tout;
2486 int mask = SUB_ATOM_HAS_UTF8;
2487 size_t minv, len, after, sz;
2488 const unsigned char *p = NULL;
2489 int bnds = 0;
2490 Term nat = 0L;
2491
2492 if (sub_atom)
2493 mask |= SUB_ATOM_HAS_ATOM;
2494
2495 tat1 = Deref(ARG1);
2496
2497 if (!!Yap_IsGroundTerm(tat1)) {
2498 if (sub_atom) {
2499 if (IsAtomTerm(tat1)) {
2500 p = AtomOfTerm(tat1)->UStrOfAE;
2501 sz = strlen_utf8(p);
2502 } else if (IsNumTerm(tat1)) {
2503 p = RepAtom(Yap_NumberToAtom(tat1 PASS_REGS))->UStrOfAE;
2504 sz = strlen_utf8(p);
2505 } else {
2506 Yap_ThrowError(TYPE_ERROR_ATOM, tat1, "sub_atom/5");
2507 { return false; }
2508 }
2509 } else if (sub_string) {
2510 if (IsStringTerm(tat1)) {
2511 p = UStringOfTerm(tat1);
2512 sz = strlen_utf8(p);
2513 } else if (IsNumTerm(tat1)) {
2514 p = RepAtom(Yap_NumberToAtom(tat1 PASS_REGS))->UStrOfAE;
2515 sz = strlen_utf8(p);
2516 } else {
2517 Yap_ThrowError(TYPE_ERROR_STRING, tat1, "sub_string/5");
2518 { return false; }
2519 }
2520 } else {
2521 int l = push_text_stack();
2522 if ((p = Yap_TextToUTF8Buffer(tat1 PASS_REGS))) {
2523 pop_text_stack(l);
2524 sz = strlen_utf8(p);
2525 } else {
2526 pop_text_stack(l);
2527 return false;
2528 }
2529 }
2530 } else {
2531
2532 Yap_ThrowError(INSTANTIATION_ERROR, tat1, "sub_atom/5: first variable\n");
2533 return false;
2534 }
2535 EXTRA_CBACK_ARG(5, 3) = MkIntegerTerm(0);
2536 tbef = Deref(ARG2);
2537 if (!Yap_IsGroundTerm(tbef)) {
2538 minv = 0;
2539 } else if (!IsIntegerTerm(tbef)) {
2540 Yap_ThrowError(TYPE_ERROR_INTEGER, tbef, "sub_string/5");
2541 { return false; }
2542 } else {
2543 minv = IntegerOfTerm(tbef);
2544 if ((Int)minv < 0) {
2545 Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, tbef, "sub_string/5");
2546 { return false; }
2547 };
2548 mask |= SUB_ATOM_HAS_MIN;
2549 bnds++;
2550 }
2551 if (!Yap_IsGroundTerm(tsize = Deref(ARG3))) {
2552 len = 0;
2553 } else if (!IsIntegerTerm(tsize)) {
2554 Yap_ThrowError(TYPE_ERROR_INTEGER, tsize, "sub_string/5");
2555 { return false; }
2556 } else {
2557 len = IntegerOfTerm(tsize);
2558 if ((Int)len < 0) {
2559 Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, tsize, "sub_string/5");
2560 { return false; }
2561 };
2562 mask |= SUB_ATOM_HAS_SIZE;
2563 bnds++;
2564 }
2565 if (!Yap_IsGroundTerm(tafter = Deref(ARG4))) {
2566 after = 0;
2567 } else if (!IsIntegerTerm(tafter)) {
2568 Yap_ThrowError(TYPE_ERROR_INTEGER, tafter, "sub_string/5");
2569 { return false; }
2570 } else {
2571 after = IntegerOfTerm(tafter);
2572 if ((Int)after < 0) {
2573 Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, tafter, "sub_string/5");
2574 { return false; }
2575 };
2576 mask |= SUB_ATOM_HAS_AFTER;
2577 bnds++;
2578 }
2579 if (!!Yap_IsGroundTerm(tout = Deref(ARG5))) {
2580 if (sub_atom) {
2581 if (!IsAtomTerm(tout)) {
2582 Yap_ThrowError(TYPE_ERROR_ATOM, tout, "sub_atom/5");
2583 { return false; }
2584 } else {
2585 Atom oat;
2586 mask |= SUB_ATOM_HAS_VAL | SUB_ATOM_HAS_SIZE;
2587 oat = AtomOfTerm(tout);
2588 len = strlen_utf8(RepAtom(oat)->UStrOfAE);
2589 }
2590 } else {
2591 if (!IsStringTerm(tout)) {
2592 Yap_ThrowError(TYPE_ERROR_STRING, tout, "sub_string/5");
2593 { return false; }
2594 } else {
2595 mask |= SUB_ATOM_HAS_VAL | SUB_ATOM_HAS_SIZE;
2596 len = strlen_utf8(UStringOfTerm(tout));
2597 }
2598 }
2599 if (!Yap_unify(ARG3, MkIntegerTerm(len))) {
2600 cut_fail();
2601 }
2602 bnds += 2;
2603 }
2604 /* the problem is deterministic if we have two cases */
2605 if (bnds > 1) {
2606 int out = FALSE;
2607
2608 if ((mask & (SUB_ATOM_HAS_MIN | SUB_ATOM_HAS_VAL | SUB_ATOM_HAS_AFTER)) ==
2609 (SUB_ATOM_HAS_MIN | SUB_ATOM_HAS_VAL | SUB_ATOM_HAS_AFTER)) {
2610 const unsigned char *sm;
2611 if (sub_atom)
2612 sm = RepAtom(AtomOfTerm(tout))->UStrOfAE;
2613 else
2614 sm = UStringOfTerm(tout);
2615 if (mask & SUB_ATOM_HAS_SIZE) {
2616 if (len != strlen_utf8(sm) ) {
2617 cut_fail();
2618 } else {
2619 len = strlen_utf8(sm);
2620 }
2621 }
2622 if (sz != minv+len+after) {
2623 cut_fail();
2624 }
2625 return do_cut(check_sub_string_at(
2626 minv, p, sm, len));
2627 } else if ((mask & (SUB_ATOM_HAS_MIN | SUB_ATOM_HAS_VAL)) ==
2628 (SUB_ATOM_HAS_MIN | SUB_ATOM_HAS_VAL)) {
2629 if (! Yap_unify(ARG4,MkIntegerTerm(sz-minv-len)) )
2630 cut_fail();
2631 if (sub_atom)
2632 return do_cut(check_sub_string_at(
2633 minv, p, RepAtom(AtomOfTerm(tout))->UStrOfAE, len));
2634 else
2635 return do_cut(check_sub_string_at(minv, p, UStringOfTerm(tout), len));
2636 } else if ((mask & (SUB_ATOM_HAS_AFTER | SUB_ATOM_HAS_VAL)) ==
2637 (SUB_ATOM_HAS_AFTER | SUB_ATOM_HAS_VAL)) {
2638 if (! Yap_unify(ARG2,MkIntegerTerm(sz-after-len)) )
2639 cut_fail();
2640 if (sub_atom) {
2641 return do_cut(check_sub_string_bef(
2642 sz - after, p, RepAtom(AtomOfTerm(tout))->UStrOfAE));
2643 } else {
2644 return do_cut(check_sub_string_bef(sz - after, p, UStringOfTerm(tout)));}
2645 } else if ((mask & (SUB_ATOM_HAS_MIN | SUB_ATOM_HAS_SIZE)) ==
2646 (SUB_ATOM_HAS_MIN | SUB_ATOM_HAS_SIZE)) {
2647 if (minv + len + after > sz) {
2648 cut_fail();
2649 }
2650 if ((Int)(after = (sz - (minv + len))) < 0) {
2651 cut_fail();
2652 }
2653 nat = build_new_atomic(mask, p, minv, len PASS_REGS);
2654 if (!nat) {
2655 cut_fail();
2656 }
2657 return do_cut(Yap_unify(ARG4, MkIntegerTerm(after)) &&
2658 Yap_unify(ARG5, nat));
2659 } else if ((mask & (SUB_ATOM_HAS_MIN | SUB_ATOM_HAS_AFTER)) ==
2660 (SUB_ATOM_HAS_MIN | SUB_ATOM_HAS_AFTER)) {
2661 if (sz < minv + after) {
2662 cut_fail();
2663 }
2664 len = sz - (minv + after);
2665 int l = push_text_stack();
2666 nat = build_new_atomic(mask, p, minv, len PASS_REGS);
2667 pop_text_stack(l);
2668 if (!nat) {
2669 cut_fail();
2670 }
2671 return do_cut(Yap_unify(ARG3, MkIntegerTerm(len)) &&
2672 Yap_unify(ARG5, nat));
2673 } else if ((mask & (SUB_ATOM_HAS_SIZE | SUB_ATOM_HAS_AFTER)) ==
2674 (SUB_ATOM_HAS_SIZE | SUB_ATOM_HAS_AFTER)) {
2675 if (len + after > sz) {
2676 cut_fail();
2677 }
2678 minv = sz - (len + after);
2679 int l = push_text_stack();
2680 nat = build_new_atomic(mask, p, minv, len PASS_REGS);
2681 pop_text_stack(l);
2682 if (!nat) {
2683 cut_fail();
2684 }
2685 return do_cut(Yap_unify(ARG2, MkIntegerTerm(minv)) &&
2686 Yap_unify(ARG5, nat));
2687 } else if ((mask & (SUB_ATOM_HAS_SIZE | SUB_ATOM_HAS_VAL)) ==
2688 (SUB_ATOM_HAS_SIZE | SUB_ATOM_HAS_VAL)) {
2689 if (!sub_atom) {
2690 out = (strlen_utf8(UStringOfTerm(tout)) == len);
2691 if (!out) {
2692 cut_fail();
2693 }
2694 } else {
2695 out = (strlen(RepAtom(AtomOfTerm(tout))->StrOfAE) == len);
2696 if (!out) {
2697 cut_fail();
2698 }
2699 if (len == sz) {
2700 out = out && Yap_unify(ARG1, ARG5) &&
2701 Yap_unify(ARG2, MkIntegerTerm(0)) &&
2702 Yap_unify(ARG4, MkIntegerTerm(0));
2703 } else if (len > sz) {
2704 cut_fail();
2705 } else {
2706 mask |= SUB_ATOM_HAS_SIZE;
2707 minv = 0;
2708 after = sz - len;
2709 goto backtrackable;
2710 }
2711 }
2712 }
2713 if (out) {
2714 cut_succeed();
2715 }
2716 cut_fail();
2717 } else {
2718 if (!(mask & SUB_ATOM_HAS_MIN))
2719 minv = 0;
2720 if (!(mask & SUB_ATOM_HAS_SIZE))
2721 len = 0;
2722 if (!(mask & SUB_ATOM_HAS_AFTER))
2723 after = sz - (len + minv);
2724 }
2725backtrackable:
2726 EXTRA_CBACK_ARG(5, 1) = MkIntegerTerm(mask);
2727 EXTRA_CBACK_ARG(5, 2) = MkIntegerTerm(minv);
2728 EXTRA_CBACK_ARG(5, 3) = MkIntegerTerm(len);
2729 EXTRA_CBACK_ARG(5, 4) = MkIntegerTerm(after);
2730 EXTRA_CBACK_ARG(5, 5) = MkIntegerTerm(sz);
2731 return cont_sub_atomic(PASS_REGS1);
2732}
2733
2749static Int sub_atom(USES_REGS1) { return (sub_atomic(true, false PASS_REGS)); }
2750
2766static Int sub_string(USES_REGS1) { return sub_atomic(false, true PASS_REGS); }
2767
2772static Int sub_text(USES_REGS1) { return sub_atomic(false, false PASS_REGS); }
2773
2774
2775static Int cont_current_atom(USES_REGS1) {
2776 Atom catom;
2777 Int i = IntOfTerm(EXTRA_CBACK_ARG(1, 2));
2778 AtomEntry *ap; /* nasty hack for gcc on hpux */
2779
2780 /* protect current hash table line */
2781 if (IsAtomTerm(EXTRA_CBACK_ARG(1, 1)))
2782 catom = AtomOfTerm(EXTRA_CBACK_ARG(1, 1));
2783 else
2784 catom = NIL;
2785 if (catom == NIL) {
2786 i++;
2787 /* move away from current hash table line */
2788 while (i < AtomHashTableSize) {
2789 READ_LOCK(HashChain[i].AERWLock);
2790 catom = HashChain[i].Entry;
2791 READ_UNLOCK(HashChain[i].AERWLock);
2792 if (catom != NIL) {
2793 break;
2794 }
2795 i++;
2796 }
2797 if (i == AtomHashTableSize) {
2798 cut_fail();
2799 }
2800 }
2801 ap = RepAtom(catom);
2802 if (Yap_unify_constant(ARG1, MkAtomTerm(catom))) {
2803 READ_LOCK(ap->ARWLock);
2804 if (ap->NextOfAE == NIL) {
2805 READ_UNLOCK(ap->ARWLock);
2806 i++;
2807 while (i < AtomHashTableSize) {
2808 READ_LOCK(HashChain[i].AERWLock);
2809 catom = HashChain[i].Entry;
2810 READ_UNLOCK(HashChain[i].AERWLock);
2811 if (catom != NIL) {
2812 break;
2813 }
2814 i++;
2815 }
2816 if (i == AtomHashTableSize) {
2817 cut_fail();
2818 } else {
2819 EXTRA_CBACK_ARG(1, 1) = MkAtomTerm(catom);
2820 }
2821 } else {
2822 EXTRA_CBACK_ARG(1, 1) = MkAtomTerm(ap->NextOfAE);
2823 READ_UNLOCK(ap->ARWLock);
2824 }
2825 EXTRA_CBACK_ARG(1, 2) = MkIntTerm(i);
2826 return true;
2827 } else {
2828 return false;
2829 }
2830}
2831
2832static Int current_atom(USES_REGS1) { /* current_atom(?Atom)
2833 */
2834 Term t1 = Deref(ARG1);
2835 if (!!Yap_IsGroundTerm(t1)) {
2836 if (IsAtomTerm(t1)) {
2837 cut_succeed();
2838 } else
2839 cut_fail();
2840 }
2841 READ_LOCK(HashChain[0].AERWLock);
2842 if (HashChain[0].Entry != NIL) {
2843 EXTRA_CBACK_ARG(1, 1) = MkAtomTerm(HashChain[0].Entry);
2844 } else {
2845 EXTRA_CBACK_ARG(1, 1) = MkIntTerm(0);
2846 }
2847 READ_UNLOCK(HashChain[0].AERWLock);
2848 EXTRA_CBACK_ARG(1, 2) = MkIntTerm(0);
2849 return (cont_current_atom(PASS_REGS1));
2850}
2851
2852void Yap_InitBackAtoms(void) {
2853 Yap_InitCPredBack("$current_atom", 1, 2, current_atom, cont_current_atom,
2854 SafePredFlag | SyncPredFlag);
2855 Yap_InitCPredBack("non_det_atom_concat", 3, 2, non_det_atom_concat3, cont_atom_concat3, 0);
2856 Yap_InitCPredBack("atomic_concat", 3, 2, atomic_concat3, cont_atomic_concat3,
2857 0);
2858 Yap_InitCPredBack("string_concat", 3, 2, string_concat3, cont_string_concat3,
2859 0);
2860 Yap_InitCPredBack("sub_atom", 5, 5, sub_atom, cont_sub_atomic, 0);
2861 Yap_InitCPredBack("sub_string", 5, 5, sub_string, cont_sub_atomic, 0);
2862 Yap_InitCPredBack("sub_text", 5, 5, sub_text, cont_sub_atomic, 0);
2863 Yap_InitCPredBack("string_code", 3, 1, string_code3, cont_string_code3, 0);
2864}
2865
2866void Yap_InitAtomPreds(void) {
2867 Yap_InitCPred("name", 2, name, 0);
2868 Yap_InitCPred("det_atom_concat", 4, det_atom_concat3, SafePredFlag);
2869 Yap_InitCPred("string_to_atom", 2, string_to_atom, 0);
2870 Yap_InitCPred("atom_to_string", 2, atom_to_string, 0);
2871 Yap_InitCPred("string_to_atomic", 2, string_to_atomic, 0);
2872 Yap_InitCPred("atomic_to_string", 2, atomic_to_string, 0);
2873 Yap_InitCPred("string_to_list", 2, string_to_list, 0);
2874 Yap_InitCPred("char_code", 2, char_code, SafePredFlag);
2875 Yap_InitCPred("atom_chars", 2, atom_chars, 0);
2876 Yap_InitCPred("atom_codes", 2, atom_codes, 0);
2877 Yap_InitCPred("atom_string", 2, atom_string, 0);
2878 Yap_InitCPred("string_atom", 2, string_atom, 0);
2879 Yap_InitCPred("string_codes", 2, string_codes, 0);
2880 Yap_InitCPred("string_chars", 2, string_chars, 0);
2881 Yap_InitCPred("atom_length", 2, atom_length, SafePredFlag);
2882 Yap_InitCPred("atomic_length", 2, atomic_length, SafePredFlag);
2883 Yap_InitCPred("string_length", 2, string_length, SafePredFlag);
2884 Yap_InitCPred("$atom_split", 4, atom_split, SafePredFlag);
2885 Yap_InitCPred("number_chars", 2, number_chars, 0);
2886 Yap_InitCPred("number_atom", 2, number_atom, 0);
2887 Yap_InitCPred("number_string", 2, number_string, 0);
2888 Yap_InitCPred("number_codes", 2, number_codes, 0);
2889 Yap_InitCPred("atom_number", 2, atom_number, 0);
2890 Yap_InitCPred("string_number", 2, string_number, 0);
2891 Yap_InitCPred("$atom_concat", 2, atom_concat2, 0);
2892 Yap_InitCPred("$string_concat", 2, string_concat2, 0);
2893 Yap_InitCPred("atomic_concat", 2, atomic_concat2, 0);
2894 Yap_InitCPred("atomics_to_string", 2, atomics_to_string2, 0);
2895 Yap_InitCPred("atomics_to_string", 3, atomics_to_string3, 0);
2896 Yap_InitCPred("get_string_code", 3, get_string_code3, 0);
2897
2898 Yap_InitCPred("downcase_text_to_atom", 2, downcase_text_to_atom, 0);
2899 Yap_InitCPred("downcase_atom", 2, downcase_text_to_atom, 0);
2900 Yap_InitCPred("upcase_text_to_atom", 2, upcase_text_to_atom, 0);
2901 Yap_InitCPred("upcase_atom", 2, upcase_text_to_atom, 0);
2902 Yap_InitCPred("downcase_text_to_string", 2, downcase_text_to_string, 0);
2903 Yap_InitCPred("upcase_text_to_string", 2, upcase_text_to_string, 0);
2904 Yap_InitCPred("downcase_text_to_codes", 2, downcase_text_to_codes, 0);
2905 Yap_InitCPred("upcase_text_to_codes", 2, upcase_text_to_codes, 0);
2906 Yap_InitCPred("downcase_text_to_chars", 2, downcase_text_to_chars, 0);
2907 Yap_InitCPred("upcase_text_to_chars", 2, upcase_text_to_chars, 0);
2908
2909 /* hiding and unhiding some predicates */
2910 Yap_InitCPred("hide_atom", 1, hide_atom, SafePredFlag | SyncPredFlag);
2911 Yap_InitCPred("hide", 1, hide_atom, SafePredFlag | SyncPredFlag);
2912 Yap_InitCPred("unhide_atom", 1, unhide_atom, SafePredFlag | SyncPredFlag);
2913 Yap_InitCPred("$hidden_atom", 1, hidden_atom,
2914 HiddenPredFlag | SafePredFlag | SyncPredFlag);
2915}
2916
Main definitions.
void * Malloc(size_t sz USES_REGS)
allocate a temporary text block
Definition: alloc.c:1759