00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 #include <plang/term.h>
00021 #include <plang/database.h>
00022 #include "term-priv.h"
00023 #include "context-priv.h"
00024 #include "rbtree-priv.h"
00025 #include "inst-priv.h"
00026 #include <string.h>
00027 #include <stdarg.h>
00028 #include <stdio.h>
00029 
00030 
00031 
00032 P_INLINE p_term *p_term_deref_non_null(const p_term *term)
00033 {
00034     for(;;) {
00035         if (term->header.type & P_TERM_VARIABLE) {
00036             if (!term->var.value)
00037                 break;
00038             term = term->var.value;
00039         } else {
00040             break;
00041         }
00042     }
00043     return (p_term *)term;
00044 }
00045 
00060 
00061 
00173 p_term *p_term_create_functor(p_context *context, p_term *name, int arg_count)
00174 {
00175     struct p_term_functor *term;
00176 
00177     
00178     if (!name || arg_count < 0)
00179         return 0;
00180     if (name->header.type != P_TERM_ATOM) {
00181         name = p_term_deref_non_null(name);
00182         if (name->header.type != P_TERM_ATOM)
00183             return 0;
00184     }
00185 
00186     
00187     if (!arg_count)
00188         return name;
00189 
00190     
00191     term = p_term_malloc
00192         (context, struct p_term_functor,
00193             sizeof(struct p_term_functor) +
00194             (sizeof(p_term *) * (unsigned int)(arg_count - 1)));
00195     if (!term)
00196         return 0;
00197     term->header.type = P_TERM_FUNCTOR;
00198     term->header.size = (unsigned int)arg_count;
00199     term->functor_name = name;
00200     return (p_term *)term;
00201 }
00202 
00214 int p_term_bind_functor_arg(p_term *term, int index, p_term *value)
00215 {
00216     if (!term || term->header.type != P_TERM_FUNCTOR || !value)
00217         return 0;
00218     if (((unsigned int)index) >= term->header.size)
00219         return 0;
00220     if (term->functor.arg[index])
00221         return 0;
00222     term->functor.arg[index] = value;
00223     return 1;
00224 }
00225 
00234 p_term *p_term_create_functor_with_args(p_context *context, p_term *name, p_term **args, int arg_count)
00235 {
00236     int index;
00237     p_term *term = p_term_create_functor(context, name, arg_count);
00238     if (!term)
00239         return 0;
00240     for (index = 0; index < arg_count; ++index)
00241         term->functor.arg[index] = args[index];
00242     return term;
00243 }
00244 
00252 p_term *p_term_create_list(p_context *context, p_term *head, p_term *tail)
00253 {
00254     struct p_term_list *term = p_term_new(context, struct p_term_list);
00255     if (!term)
00256         return 0;
00257     term->header.type = P_TERM_LIST;
00258     term->header.size = 2;  
00259     term->head = head;
00260     term->tail = tail;
00261     return (p_term *)term;
00262 }
00263 
00274 void p_term_set_tail(p_term *list, p_term *tail)
00275 {
00276     if (!list || list->header.type != P_TERM_LIST)
00277         return;
00278     list->list.tail = tail;
00279 }
00280 
00300 p_term *p_term_create_atom(p_context *context, const char *name)
00301 {
00302     return p_term_create_atom_n(context, name, name ? strlen(name) : 0);
00303 }
00304 
00324 p_term *p_term_create_atom_n(p_context *context, const char *name, size_t len)
00325 {
00326     unsigned int hash;
00327     const char *n;
00328     size_t nlen;
00329     p_term *atom;
00330 
00331     
00332     hash = 0;
00333     n = name;
00334     nlen = len;
00335     while (nlen > 0) {
00336         hash = hash * 5 + (((unsigned int)(*n++)) & 0xFF);
00337         --nlen;
00338     }
00339     hash %= P_CONTEXT_HASH_SIZE;
00340     atom = context->atom_hash[hash];
00341     while (atom != 0) {
00342         if (atom->header.size == len &&
00343                 !memcmp(atom->atom.name, name, len))
00344             return atom;
00345         atom = atom->atom.next;
00346     }
00347 
00348     
00349     atom = p_term_malloc
00350         (context, p_term, sizeof(struct p_term_atom) + len);
00351     if (!atom)
00352         return 0;
00353     atom->header.type = P_TERM_ATOM;
00354     atom->header.size = (unsigned int)len;
00355     atom->atom.next = context->atom_hash[hash];
00356     if (len > 0)
00357         memcpy(atom->atom.name, name, len);
00358     atom->atom.name[len] = '\0';
00359     context->atom_hash[hash] = atom;
00360     return atom;
00361 }
00362 
00382 p_term *p_term_create_string(p_context *context, const char *str)
00383 {
00384     size_t len = str ? strlen(str) : 0;
00385     struct p_term_string *term = p_term_malloc
00386         (context, struct p_term_string, sizeof(struct p_term_string) + len);
00387     if (!term)
00388         return 0;
00389     term->header.type = P_TERM_STRING;
00390     term->header.size = (unsigned int)len;
00391     if (len > 0)
00392         memcpy(term->name, str, len);
00393     term->name[len] = '\0';
00394     return (p_term *)term;
00395 }
00396 
00413 p_term *p_term_create_string_n(p_context *context, const char *str, size_t len)
00414 {
00415     struct p_term_string *term = p_term_malloc
00416         (context, struct p_term_string, sizeof(struct p_term_string) + len);
00417     if (!term)
00418         return 0;
00419     term->header.type = P_TERM_STRING;
00420     term->header.size = (unsigned int)len;
00421     if (len > 0)
00422         memcpy(term->name, str, len);
00423     term->name[len] = '\0';
00424     return (p_term *)term;
00425 }
00426 
00435 p_term *p_term_create_variable(p_context *context)
00436 {
00437     struct p_term_var *term = p_term_new(context, struct p_term_var);
00438     if (!term)
00439         return 0;
00440     term->header.type = P_TERM_VARIABLE;
00441     return (p_term *)term;
00442 }
00443 
00454 p_term *p_term_create_named_variable(p_context *context, const char *name)
00455 {
00456     size_t len = name ? strlen(name) : 0;
00457     struct p_term_var *term;
00458     if (!len)
00459         return p_term_create_variable(context);
00460     term = p_term_malloc(context, struct p_term_var,
00461                          sizeof(struct p_term_var) + len + 1);
00462     if (!term)
00463         return 0;
00464     term->header.type = P_TERM_VARIABLE;
00465     term->header.size = (unsigned int)len;
00466     strcpy((char *)(term + 1), name);
00467     return (p_term *)term;
00468 }
00469 
00484 p_term *p_term_create_member_variable(p_context *context, p_term *object, p_term *name, int auto_create)
00485 {
00486     struct p_term_member_var *term;
00487     if (!name || !object)
00488         return 0;
00489     name = p_term_deref_non_null(name);
00490     if (name->header.type != P_TERM_ATOM)
00491         return 0;
00492     term = p_term_new(context, struct p_term_member_var);
00493     if (!term)
00494         return 0;
00495     term->header.type = P_TERM_MEMBER_VARIABLE;
00496     term->header.size = (auto_create ? 1 : 0);
00497     term->object = object;
00498     term->name = name;
00499     return (p_term *)term;
00500 }
00501 
00511 p_term *p_term_create_integer(p_context *context, int value)
00512 {
00513     struct p_term_integer *term =
00514         p_term_new(context, struct p_term_integer);
00515     if (!term)
00516         return 0;
00517     term->header.type = P_TERM_INTEGER;
00518 #if defined(P_TERM_64BIT)
00519     
00520     term->header.size = (unsigned int)value;
00521 #else
00522     term->value = value;
00523 #endif
00524     return (p_term *)term;
00525 }
00526 
00536 p_term *p_term_create_real(p_context *context, double value)
00537 {
00538     struct p_term_real *term = p_term_new(context, struct p_term_real);
00539     if (!term)
00540         return 0;
00541     term->header.type = P_TERM_REAL;
00542     term->value = value;
00543     return (p_term *)term;
00544 }
00545 
00557 p_term *p_term_nil_atom(p_context *context)
00558 {
00559     return context->nil_atom;
00560 }
00561 
00573 p_term *p_term_prototype_atom(p_context *context)
00574 {
00575     return context->prototype_atom;
00576 }
00577 
00589 p_term *p_term_class_name_atom(p_context *context)
00590 {
00591     return context->class_name_atom;
00592 }
00593 
00609 p_term *p_term_deref(const p_term *term)
00610 {
00611     return term ? p_term_deref_non_null(term) : 0;
00612 }
00613 
00629 p_term *p_term_deref_member(p_context *context, p_term *term)
00630 {
00631     p_term *object;
00632     p_term *value;
00633     if (!term)
00634         return 0;
00635     term = p_term_deref_non_null(term);
00636     if (term->header.type != P_TERM_MEMBER_VARIABLE)
00637         return term;
00638     object = p_term_deref_member(context, term->member_var.object);
00639     if (!object || object->header.type != P_TERM_OBJECT)
00640         return term;
00641     value = p_term_property(context, object, term->member_var.name);
00642     if (value) {
00643         
00644         p_term_bind_variable(context, term, value, P_BIND_DEFAULT);
00645     } else if (term->header.size) {
00646         
00647 
00648         value = p_term_create_variable(context);
00649         p_term_add_property
00650             (context, object, term->member_var.name, value);
00651         p_term_bind_variable(context, term, value, P_BIND_DEFAULT);
00652     }
00653     return p_term_deref(value);
00654 }
00655 
00673 p_term *p_term_deref_own_member(p_context *context, p_term *term)
00674 {
00675     p_term *object;
00676     p_term *value;
00677     if (!term)
00678         return 0;
00679     term = p_term_deref_non_null(term);
00680     if (term->header.type != P_TERM_MEMBER_VARIABLE)
00681         return term;
00682     object = p_term_deref_member(context, term->member_var.object);
00683     if (!object || object->header.type != P_TERM_OBJECT)
00684         return term;
00685     value = p_term_own_property(context, object, term->member_var.name);
00686     if (value) {
00687         
00688         p_term_bind_variable(context, term, value, P_BIND_DEFAULT);
00689     } else if (term->header.size) {
00690         
00691 
00692         value = p_term_create_variable(context);
00693         p_term_add_property
00694             (context, object, term->member_var.name, value);
00695         p_term_bind_variable(context, term, value, P_BIND_DEFAULT);
00696     }
00697     return term;
00698 }
00699 
00709 int p_term_type(const p_term *term)
00710 {
00711     if (term)
00712         return (int)(p_term_deref_non_null(term)->header.type);
00713     else
00714         return P_TERM_INVALID;
00715 }
00716 
00727 int p_term_arg_count(const p_term *term)
00728 {
00729     if (!term)
00730         return 0;
00731     
00732     if (term->header.type == P_TERM_FUNCTOR ||
00733             term->header.type == P_TERM_PREDICATE)
00734         return (int)(term->header.size);
00735     term = p_term_deref_non_null(term);
00736     if (term->header.type == P_TERM_FUNCTOR ||
00737             term->header.type == P_TERM_PREDICATE)
00738         return (int)(term->header.size);
00739     else
00740         return 0;
00741 }
00742 
00753 const char *p_term_name(const p_term *term)
00754 {
00755     if (!term)
00756         return 0;
00757     term = p_term_deref_non_null(term);
00758     switch (term->header.type) {
00759     case P_TERM_FUNCTOR:
00760         return p_term_name(term->functor.functor_name);
00761     case P_TERM_ATOM:
00762         return term->atom.name;
00763     case P_TERM_STRING:
00764         return term->string.name;
00765     case P_TERM_PREDICATE:
00766         return p_term_name(term->predicate.name);
00767     case P_TERM_VARIABLE:
00768         if (term->header.size > 0)
00769             return (const char *)(&(term->var) + 1);
00770         break;
00771     case P_TERM_MEMBER_VARIABLE:
00772         return p_term_name(term->member_var.name);
00773     default: break;
00774     }
00775     return 0;
00776 }
00777 
00790 size_t p_term_name_length(const p_term *term)
00791 {
00792     if (!term)
00793         return 0;
00794     term = p_term_deref_non_null(term);
00795     switch (term->header.type) {
00796     case P_TERM_FUNCTOR:
00797         return p_term_name_length(term->functor.functor_name);
00798     case P_TERM_PREDICATE:
00799         return p_term_name_length(term->predicate.name);
00800     case P_TERM_ATOM:
00801     case P_TERM_STRING:
00802     case P_TERM_VARIABLE:
00803         return term->header.size;
00804     case P_TERM_MEMBER_VARIABLE:
00805         return p_term_name_length(term->member_var.name);
00806     default: break;
00807     }
00808     return 0;
00809 }
00810 
00811 
00812 int _p_term_next_utf8(const char *str, size_t len, size_t *size)
00813 {
00814     int ch, ch2;
00815     size_t req, sz;
00816     if (!len) {
00817         *size = 0;
00818         return -1;
00819     }
00820     ch = ((int)(*str)) & 0xFF;
00821     sz = 1;
00822     if (ch < 0x80) {
00823         req = 0;
00824     } else if ((ch & 0xE0) == 0xC0) {
00825         ch &= 0x1F;
00826         req = 1;
00827         ++str;
00828         --len;
00829     } else if ((ch & 0xF0) == 0xE0) {
00830         ch &= 0x0F;
00831         req = 2;
00832         ++str;
00833         --len;
00834     } else if ((ch & 0xF8) == 0xF0) {
00835         ch &= 0x07;
00836         req = 3;
00837         ++str;
00838         --len;
00839     } else {
00840         ++str;
00841         --len;
00842     invalid:
00843         
00844         while (len > 0) {
00845             ch = ((int)(*str)) & 0xFF;
00846             if (ch < 0x80 || (ch & 0xE0) == 0xC0 ||
00847                     (ch & 0xF0) == 0xE0 || (ch & 0xF8) == 0xF0)
00848                 break;
00849             ++sz;
00850             ++str;
00851             --len;
00852         }
00853         *size = sz;
00854         return -1;
00855     }
00856     while (req > 0) {
00857         if (!len)
00858             goto invalid;
00859         ch2 = ((int)(*str)) & 0xFF;
00860         if ((ch2 & 0xC0) == 0x80)
00861             ch = (ch << 6) | (ch2 & 0x3F);
00862         else
00863             goto invalid;
00864         ++str;
00865         --len;
00866         ++sz;
00867         --req;
00868     }
00869     *size = sz;
00870     return ch;
00871 }
00872 
00885 size_t p_term_name_length_utf8(const p_term *term)
00886 {
00887     const char *name;
00888     size_t byte_len;
00889     size_t utf8_len;
00890     size_t ch_size;
00891     if (!term)
00892         return 0;
00893     term = p_term_deref_non_null(term);
00894     switch (term->header.type) {
00895     case P_TERM_FUNCTOR:
00896         return p_term_name_length_utf8(term->functor.functor_name);
00897     case P_TERM_PREDICATE:
00898         return p_term_name_length_utf8(term->predicate.name);
00899     case P_TERM_ATOM:
00900         name = term->atom.name;
00901         byte_len = term->header.size;
00902         break;
00903     case P_TERM_STRING:
00904         name = term->string.name;
00905         byte_len = term->header.size;
00906         break;
00907     case P_TERM_VARIABLE:
00908         byte_len = term->header.size;
00909         if (!byte_len)
00910             return 0;
00911         name = (const char *)(&(term->var) + 1);
00912         break;
00913     case P_TERM_MEMBER_VARIABLE:
00914         return p_term_name_length_utf8(term->member_var.name);
00915     default: return 0;
00916     }
00917     utf8_len = 0;
00918     while (byte_len > 0) {
00919         _p_term_next_utf8(name, byte_len, &ch_size);
00920         name += ch_size;
00921         byte_len -= ch_size;
00922         ++utf8_len;
00923     }
00924     return utf8_len;
00925 }
00926 
00936 p_term *p_term_functor(const p_term *term)
00937 {
00938     if (!term)
00939         return 0;
00940     
00941     if (term->header.type == P_TERM_FUNCTOR)
00942         return term->functor.functor_name;
00943     else if (term->header.type == P_TERM_PREDICATE)
00944         return term->predicate.name;
00945     term = p_term_deref_non_null(term);
00946     if (term->header.type == P_TERM_FUNCTOR)
00947         return term->functor.functor_name;
00948     else if (term->header.type == P_TERM_PREDICATE)
00949         return term->predicate.name;
00950     return 0;
00951 }
00952 
00963 p_term *p_term_arg(const p_term *term, int index)
00964 {
00965     if (!term)
00966         return 0;
00967     
00968     if (term->header.type != P_TERM_FUNCTOR) {
00969         term = p_term_deref_non_null(term);
00970         if (term->header.type != P_TERM_FUNCTOR)
00971             return 0;
00972     }
00973     if (((unsigned int)index) < term->header.size)
00974         return term->functor.arg[index];
00975     else
00976         return 0;
00977 }
00978 
00988 int p_term_integer_value(const p_term *term)
00989 {
00990     if (!term)
00991         return 0;
00992 #if defined(P_TERM_64BIT)
00993     
00994     if (term->header.type == P_TERM_INTEGER)
00995         return (int)(term->header.size);
00996     term = p_term_deref_non_null(term);
00997     if (term->header.type == P_TERM_INTEGER)
00998         return (int)(term->header.size);
00999     else
01000         return 0;
01001 #else
01002     if (term->header.type == P_TERM_INTEGER)
01003         return term->integer.value;
01004     term = p_term_deref_non_null(term);
01005     if (term->header.type == P_TERM_INTEGER)
01006         return term->integer.value;
01007     else
01008         return 0;
01009 #endif
01010 }
01011 
01021 double p_term_real_value(const p_term *term)
01022 {
01023     if (!term)
01024         return 0.0;
01025     
01026     if (term->header.type == P_TERM_REAL)
01027         return term->real.value;
01028     term = p_term_deref_non_null(term);
01029     if (term->header.type == P_TERM_REAL)
01030         return term->real.value;
01031     else
01032         return 0.0;
01033 }
01034 
01044 p_term *p_term_head(const p_term *term)
01045 {
01046     if (!term)
01047         return 0;
01048     
01049     if (term->header.type == P_TERM_LIST)
01050         return term->list.head;
01051     term = p_term_deref_non_null(term);
01052     if (term->header.type == P_TERM_LIST)
01053         return term->list.head;
01054     else
01055         return 0;
01056 }
01057 
01067 p_term *p_term_tail(const p_term *term)
01068 {
01069     if (!term)
01070         return 0;
01071     
01072     if (term->header.type == P_TERM_LIST)
01073         return term->list.tail;
01074     term = p_term_deref_non_null(term);
01075     if (term->header.type == P_TERM_LIST)
01076         return term->list.tail;
01077     else
01078         return 0;
01079 }
01080 
01092 p_term *p_term_object(const p_term *term)
01093 {
01094     if (!term)
01095         return 0;
01096     
01097     if (term->header.type == P_TERM_MEMBER_VARIABLE)
01098         return term->member_var.object;
01099     term = p_term_deref_non_null(term);
01100     if (term->header.type == P_TERM_MEMBER_VARIABLE)
01101         return term->member_var.object;
01102     else
01103         return 0;
01104 }
01105 
01116 p_term *p_term_create_object(p_context *context, p_term *prototype)
01117 {
01118     struct p_term_object *term;
01119     if (!prototype)
01120         return 0;
01121     prototype = p_term_deref_non_null(prototype);
01122     if (prototype->header.type != P_TERM_OBJECT)
01123         return 0;
01124     term = p_term_new(context, struct p_term_object);
01125     if (!term)
01126         return 0;
01127     term->header.type = P_TERM_OBJECT;
01128     term->header.size = 1;
01129     term->properties[0].name = context->prototype_atom;
01130     term->properties[0].value = prototype;
01131     return (p_term *)term;
01132 }
01133 
01145 p_term *p_term_create_class_object(p_context *context, p_term *class_name, p_term *prototype)
01146 {
01147     struct p_term_object *term;
01148     if (!class_name)
01149         return 0;
01150     class_name = p_term_deref_non_null(class_name);
01151     if (class_name->header.type != P_TERM_ATOM)
01152         return 0;
01153     if (prototype) {
01154         prototype = p_term_deref_non_null(prototype);
01155         if (prototype->header.type != P_TERM_OBJECT)
01156             return 0;
01157     }
01158     term = p_term_new(context, struct p_term_object);
01159     if (!term)
01160         return 0;
01161     term->header.type = P_TERM_OBJECT;
01162     if (prototype) {
01163         
01164         term->properties[0].name = context->prototype_atom;
01165         term->properties[0].value = prototype;
01166         term->properties[1].name = context->class_name_atom;
01167         term->properties[1].value = class_name;
01168         term->header.size = 2;
01169     } else {
01170         term->properties[0].name = context->class_name_atom;
01171         term->properties[0].value = class_name;
01172         term->header.size = 1;
01173     }
01174     return (p_term *)term;
01175 }
01176 
01192 int p_term_add_property(p_context *context, p_term *term, p_term *name, p_term *value)
01193 {
01194     
01195     if (!term || !name)
01196         return 0;
01197     term = p_term_deref_non_null(term);
01198     if (term->header.type != P_TERM_OBJECT)
01199         return 0;
01200     name = p_term_deref_non_null(name);
01201     if (name->header.type != P_TERM_ATOM)
01202         return 0;
01203     if (name == context->prototype_atom ||
01204             name == context->class_name_atom)
01205         return 0;
01206 
01207     
01208     while (term->header.size >= P_TERM_MAX_PROPS && term->object.next)
01209         term = term->object.next;
01210     if (term->header.size >= P_TERM_MAX_PROPS) {
01211         
01212         p_term *block = p_term_malloc
01213             (context, p_term, sizeof(struct p_term_object));
01214         if (!block)
01215             return 0;
01216         block->header.type = P_TERM_OBJECT;
01217         term->object.next = block;
01218         term = block;
01219     }
01220 
01221     
01222     term->object.properties[term->header.size].name = name;
01223     term->object.properties[term->header.size].value = value;
01224     ++(term->header.size);
01225     return 1;
01226 }
01227 
01239 p_term *p_term_property(p_context *context, const p_term *term, const p_term *name)
01240 {
01241     const p_term *block;
01242     unsigned int index;
01243 
01244     
01245     if (!term || !name)
01246         return 0;
01247     term = p_term_deref_non_null(term);
01248     if (term->header.type != P_TERM_OBJECT)
01249         return 0;
01250     name = p_term_deref_non_null(name);
01251     if (name->header.type != P_TERM_ATOM)
01252         return 0;
01253 
01254     for (;;) {
01255         
01256         block = term;
01257         do {
01258             for (index = 0; index < block->header.size; ++index) {
01259                 if (block->object.properties[index].name == name)
01260                     return block->object.properties[index].value;
01261             }
01262             block = block->object.next;
01263         } while (block != 0);
01264 
01265         
01266         if (term->object.properties[0].name != context->prototype_atom)
01267             break;
01268         term = term->object.properties[0].value;
01269     }
01270     return 0;
01271 }
01272 
01283 p_term *p_term_own_property(p_context *context, const p_term *term, const p_term *name)
01284 {
01285     unsigned int index;
01286 
01287     
01288     if (!term || !name)
01289         return 0;
01290     term = p_term_deref_non_null(term);
01291     if (term->header.type != P_TERM_OBJECT)
01292         return 0;
01293     name = p_term_deref_non_null(name);
01294     if (name->header.type != P_TERM_ATOM)
01295         return 0;
01296 
01297     
01298     do {
01299         for (index = 0; index < term->header.size; ++index) {
01300             if (term->object.properties[index].name == name)
01301                 return term->object.properties[index].value;
01302         }
01303         term = term->object.next;
01304     } while (term != 0);
01305     return 0;
01306 }
01307 
01328 int p_term_set_own_property(p_context *context, p_term *term, p_term *name, p_term *value)
01329 {
01330     unsigned int index;
01331 
01332     
01333     if (!term || !name)
01334         return 0;
01335     term = p_term_deref_non_null(term);
01336     if (term->header.type != P_TERM_OBJECT)
01337         return 0;
01338     name = p_term_deref_non_null(name);
01339     if (name->header.type != P_TERM_ATOM)
01340         return 0;
01341 
01342     
01343     do {
01344         for (index = 0; index < term->header.size; ++index) {
01345             if (term->object.properties[index].name == name) {
01346                 term->object.properties[index].value = value;
01347                 return 1;
01348             }
01349         }
01350         term = term->object.next;
01351     } while (term != 0);
01352 
01353     
01354     return p_term_add_property(context, term, name, value);
01355 }
01356 
01367 int p_term_is_instance_object(p_context *context, const p_term *term)
01368 {
01369     p_term *name;
01370     if (!term)
01371         return 0;
01372     if (term->header.type != P_TERM_OBJECT) {
01373         term = p_term_deref_non_null(term);
01374         if (term->header.type != P_TERM_OBJECT)
01375             return 0;
01376     }
01377     name = context->class_name_atom;
01378     return term->object.properties[0].name != name &&
01379            term->object.properties[1].name != name;
01380 }
01381 
01392 int p_term_is_class_object(p_context *context, const p_term *term)
01393 {
01394     p_term *name;
01395     if (!term)
01396         return 0;
01397     if (term->header.type != P_TERM_OBJECT) {
01398         term = p_term_deref_non_null(term);
01399         if (term->header.type != P_TERM_OBJECT)
01400             return 0;
01401     }
01402     name = context->class_name_atom;
01403     return term->object.properties[0].name == name ||
01404            term->object.properties[1].name == name;
01405 }
01406 
01416 int p_term_inherits(p_context *context, const p_term *term1, const p_term *term2)
01417 {
01418     p_term *pname = context->prototype_atom;
01419     if (!term1 || !term2)
01420         return 0;
01421     term2 = p_term_deref_non_null(term2);
01422     if (term2->header.type != P_TERM_OBJECT)
01423         return 0;
01424     do {
01425         term1 = p_term_deref_non_null(term1);
01426         if (term1 == term2)
01427             return 1;
01428         if (term1->header.type != P_TERM_OBJECT)
01429             break;
01430         if (term1->object.properties[0].name != pname)
01431             break;
01432         term1 = term1->object.properties[0].value;
01433     } while (term1 != 0);
01434     return 0;
01435 }
01436 
01447 int p_term_is_instance_of(p_context *context, const p_term *term1, const p_term *term2)
01448 {
01449     if (!p_term_is_instance_object(context, term1))
01450         return 0;
01451     if (!p_term_is_class_object(context, term2))
01452         return 0;
01453     return p_term_inherits(context, term1, term2);
01454 }
01455 
01469 p_term *p_term_create_predicate(p_context *context, p_term *name, int arg_count)
01470 {
01471     struct p_term_predicate *term;
01472 
01473     
01474     if (!name || arg_count < 0)
01475         return 0;
01476     if (name->header.type != P_TERM_ATOM) {
01477         name = p_term_deref_non_null(name);
01478         if (name->header.type != P_TERM_ATOM)
01479             return 0;
01480     }
01481 
01482     
01483     term = p_term_new(context, struct p_term_predicate);
01484     if (!term)
01485         return 0;
01486     term->header.type = P_TERM_PREDICATE;
01487     term->header.size = (unsigned int)arg_count;
01488     term->name = name;
01489     return (p_term *)term;
01490 }
01491 
01499 p_term *p_term_create_dynamic_clause(p_context *context, p_term *head, p_term *body)
01500 {
01501     struct p_term_clause *term =
01502         p_term_new(context, struct p_term_clause);
01503     p_code *code = _p_code_new();
01504     if (!term || !code)
01505         return 0;
01506     term->header.type = P_TERM_CLAUSE;
01507     _p_code_generate_dynamic_clause(context, head, body, code);
01508     _p_code_finish(code, &(term->clause_code));
01509     return (p_term *)term;
01510 }
01511 
01512 
01513 P_INLINE void p_term_add_indexed_clause
01514     (p_context *context, struct p_term_clause_list *list,
01515      struct p_term_clause *clause, int first)
01516 {
01517     if (!list->head) {
01518         list->head = clause;
01519         list->tail = clause;
01520         clause->next_index = 0;
01521     } else if (!first) {
01522         list->tail->next_index = clause;
01523         clause->next_index = 0;
01524         list->tail = clause;
01525     } else {
01526         clause->next_index = list->head;
01527         list->head = clause;
01528     }
01529 }
01530 
01531 
01532 P_INLINE void p_term_add_regular_clause
01533     (p_context *context, struct p_term_clause_list *list,
01534      p_term *clause, int first)
01535 {
01536     if (!list->head) {
01537         list->head = &(clause->clause);
01538         list->tail = &(clause->clause);
01539         clause->clause.next_clause = 0;
01540     } else if (!first) {
01541         list->tail->next_clause = &(clause->clause);
01542         clause->clause.next_clause = 0;
01543         list->tail = &(clause->clause);
01544     } else {
01545         clause->clause.next_clause = list->head;
01546         list->head = &(clause->clause);
01547     }
01548 }
01549 
01550 
01551 static void p_term_index_clause
01552     (p_context *context, p_term *predicate,
01553      struct p_term_clause *clause, int first)
01554 {
01555     p_rbkey key;
01556     p_rbnode *node;
01557 
01558     
01559 
01560 
01561     if (!_p_code_argument_key(&key, &(clause->clause_code),
01562                               predicate->predicate.index_arg)) {
01563         p_term_add_indexed_clause
01564             (context, &(predicate->predicate.var_clauses),
01565              clause, first);
01566         return;
01567     }
01568 
01569     
01570     node = _p_rbtree_insert(&(predicate->predicate.index), &key);
01571     if (!node)
01572         return;
01573     p_term_add_indexed_clause(context, &(node->clauses), clause, first);
01574 }
01575 
01576 
01577 static void p_term_index_all_clauses
01578     (p_context *context, p_term *predicate)
01579 {
01580     struct p_term_clause *clause;
01581     p_rbkey key;
01582     p_rbkey keys[4];
01583     unsigned int counts[4];
01584     unsigned int arg;
01585     unsigned int max_count;
01586 
01587     
01588     if (predicate->header.size == 0) {
01589         predicate->predicate.dont_index = 1;
01590         return;
01591     }
01592 
01593     
01594 
01595 
01596     clause = predicate->predicate.clauses.head;
01597     for (arg = 0; arg < 4 && arg < predicate->header.size; ++arg) {
01598         if (!_p_code_argument_key
01599                 (&(keys[arg]), &(clause->clause_code), arg)) {
01600             keys[arg].type = P_TERM_VARIABLE;
01601             keys[arg].size = 0;
01602             keys[arg].name = 0;
01603         }
01604         counts[arg] = 0;
01605     }
01606     while ((clause = clause->next_clause) != 0) {
01607         for (arg = 0; arg < 4 && arg < predicate->header.size; ++arg) {
01608             if (!_p_code_argument_key
01609                     (&key, &(clause->clause_code), arg)) {
01610                 key.type = P_TERM_VARIABLE;
01611                 key.size = 0;
01612                 key.name = 0;
01613             }
01614             if (_p_rbkey_compare_keys(&(keys[arg]), &key) != 0) {
01615                 ++(counts[arg]);
01616                 keys[arg] = key;
01617             }
01618         }
01619     }
01620     max_count = counts[0];
01621     predicate->predicate.index_arg = 0;
01622     for (arg = 1; arg < 4 && arg < predicate->header.size; ++arg) {
01623         if (counts[arg] > max_count) {
01624             max_count = counts[arg];
01625             predicate->predicate.index_arg = arg;
01626         }
01627     }
01628     if (predicate->predicate.index_arg == 0 &&
01629             keys[0].type == P_TERM_VARIABLE && !(counts[arg]) &&
01630             predicate->header.size >= 2) {
01631         
01632 
01633 
01634         predicate->predicate.index_arg = 1;
01635     }
01636 
01637     
01638     clause = predicate->predicate.clauses.head;
01639     while (clause != 0) {
01640         p_term_index_clause(context, predicate, clause, 0);
01641         clause = clause->next_clause;
01642     }
01643 
01644     
01645     predicate->predicate.is_indexed = 1;
01646 }
01647 
01648 
01649 
01650 static void p_term_renumber_clauses(p_term *predicate)
01651 {
01652     unsigned int clause_num = P_TERM_DEFAULT_CLAUSE_NUM -
01653         predicate->predicate.clause_count / 2;
01654     struct p_term_clause *clause = predicate->predicate.clauses.head;
01655     while (clause != 0) {
01656         clause->header.size = clause_num++;
01657         clause = clause->next_clause;
01658     }
01659 }
01660 
01675 void p_term_add_clause_first(p_context *context, p_term *predicate, p_term *clause)
01676 {
01677     unsigned int clause_num;
01678     if (predicate->predicate.clauses.head) {
01679         struct p_term_clause *first = predicate->predicate.clauses.head;
01680         clause_num = first->header.size - 1;
01681     } else {
01682         clause_num = P_TERM_DEFAULT_CLAUSE_NUM;
01683     }
01684     clause->header.size = clause_num;
01685     p_term_add_regular_clause
01686         (context, &(predicate->predicate.clauses), clause, 1);
01687     ++(predicate->predicate.clause_count);
01688     if (!clause->header.size)
01689         p_term_renumber_clauses(predicate);
01690     if (predicate->predicate.is_indexed) {
01691         p_term_index_clause(context, predicate, &(clause->clause), 1);
01692     } else if (!(predicate->predicate.dont_index) &&
01693                predicate->predicate.clause_count > P_TERM_INDEX_TRIGGER) {
01694         p_term_index_all_clauses(context, predicate);
01695     }
01696 }
01697 
01712 void p_term_add_clause_last(p_context *context, p_term *predicate, p_term *clause)
01713 {
01714     unsigned int clause_num;
01715     if (predicate->predicate.clauses.tail) {
01716         struct p_term_clause *last = predicate->predicate.clauses.tail;
01717         clause_num = last->header.size + 1;
01718     } else {
01719         clause_num = P_TERM_DEFAULT_CLAUSE_NUM;
01720     }
01721     clause->header.size = clause_num;
01722     p_term_add_regular_clause
01723         (context, &(predicate->predicate.clauses), clause, 0);
01724     ++(predicate->predicate.clause_count);
01725     if (!clause->header.size)
01726         p_term_renumber_clauses(predicate);
01727     if (predicate->predicate.is_indexed) {
01728         p_term_index_clause(context, predicate, &(clause->clause), 0);
01729     } else if (!(predicate->predicate.dont_index) &&
01730                predicate->predicate.clause_count > P_TERM_INDEX_TRIGGER) {
01731         p_term_index_all_clauses(context, predicate);
01732     }
01733 }
01734 
01735 
01736 int _p_term_retract_clause
01737     (p_context *context, p_term *predicate,
01738      struct p_term_clause *clause, p_term *clause2)
01739 {
01740     p_rbkey key;
01741     p_rbnode *node;
01742     p_term *body;
01743     void *marker;
01744     struct p_term_clause_list *list;
01745     struct p_term_clause *current;
01746     struct p_term_clause *prev;
01747 
01748     
01749     if (!predicate->predicate.is_indexed ||
01750             !_p_code_argument_key
01751                 (&key, &(clause->clause_code),
01752                  predicate->predicate.index_arg)) {
01753         key.type = P_TERM_VARIABLE;
01754         key.size = 0;
01755         key.name = 0;
01756     }
01757 
01758     
01759     marker = p_context_mark_trail(context);
01760     body = p_term_unify_clause
01761         (context, p_term_arg(clause2, 0), (p_term *)clause);
01762     if (!body)
01763         return 0;
01764     if (!p_term_unify(context, body,
01765                       p_term_arg(clause2, 1), P_BIND_DEFAULT)) {
01766         p_context_backtrack_trail(context, marker);
01767         return 0;
01768     }
01769 
01770     
01771     if (!predicate->predicate.is_indexed)
01772         return 1;
01773 
01774     
01775     if (key.type != P_TERM_VARIABLE) {
01776         node = _p_rbtree_lookup(&(predicate->predicate.index), &key);
01777         if (node)
01778             list = &(node->clauses);
01779         else
01780             list = &(predicate->predicate.var_clauses); 
01781     } else {
01782         list = &(predicate->predicate.var_clauses);
01783     }
01784     current = list->head;
01785     prev = 0;
01786     while (current != 0 && current != clause) {
01787         prev = current;
01788         current = current->next_index;
01789     }
01790     if (!current)
01791         return 1;
01792     if (prev) {
01793         prev->next_index = current->next_index;
01794         if (!current->next_index)
01795             list->tail = prev;
01796     } else {
01797         list->head = current->next_index;
01798         if (!(list->head)) {
01799             list->tail = 0;
01800             if (key.type != P_TERM_VARIABLE)
01801                 _p_rbtree_remove(&(predicate->predicate.index), &key);
01802         }
01803     }
01804     return 1;
01805 }
01806 
01821 void p_term_clauses_begin(const p_term *predicate, const p_term *head, p_term_clause_iter *iter)
01822 {
01823     iter->next1 = 0;
01824     iter->next2 = 0;
01825     iter->next3 = 0;
01826     if (!predicate)
01827         return;
01828     if (predicate->header.type != P_TERM_PREDICATE) {
01829         predicate = p_term_deref_non_null(predicate);
01830         if (predicate->header.type != P_TERM_PREDICATE)
01831             return;
01832     }
01833     if (head && predicate->predicate.is_indexed) {
01834         p_rbkey key;
01835         p_rbnode *node;
01836         p_term *arg = p_term_arg(head, predicate->predicate.index_arg);
01837         if (_p_rbkey_init(&key, arg)) {
01838             node = _p_rbtree_lookup
01839                 (&(predicate->predicate.index), &key);
01840             if (node) {
01841                 iter->next1 = node->clauses.head;
01842                 iter->next2 = predicate->predicate.var_clauses.head;
01843                 return;
01844             }
01845         }
01846     }
01847     iter->next3 = predicate->predicate.clauses.head;
01848 }
01849 
01857 p_term *p_term_clauses_next(p_term_clause_iter *iter)
01858 {
01859     struct p_term_clause *clause;
01860     if (iter->next1) {
01861         clause = iter->next1;
01862         if (iter->next2 && iter->next2->header.size < clause->header.size) {
01863             clause = iter->next2;
01864             iter->next2 = clause->next_index;
01865         } else {
01866             iter->next1 = clause->next_index;
01867             if (!(iter->next1)) {
01868                 iter->next1 = iter->next2;
01869                 iter->next2 = 0;
01870             }
01871         }
01872         return (p_term *)clause;
01873     } else if (iter->next3) {
01874         clause = iter->next3;
01875         iter->next3 = clause->next_clause;
01876         return (p_term *)clause;
01877     }
01878     return 0;
01879 }
01880 
01888 int p_term_clauses_has_more(const p_term_clause_iter *iter)
01889 {
01890     return iter->next1 != 0 || iter->next3 != 0;
01891 }
01892 
01899 p_term *p_term_create_database(p_context *context)
01900 {
01901     struct p_term_database *term =
01902         p_term_new(context, struct p_term_database);
01903     if (!term)
01904         return 0;
01905     term->header.type = P_TERM_DATABASE;
01906     return (p_term *)term;
01907 }
01908 
01916 void p_term_database_add_predicate(p_term *database, p_term *predicate)
01917 {
01918     p_rbkey key;
01919     p_rbnode *node;
01920     database = p_term_deref(database);
01921     predicate = p_term_deref(predicate);
01922     if (!database || database->header.type != P_TERM_DATABASE)
01923         return;
01924     if (!predicate || predicate->header.type != P_TERM_PREDICATE)
01925         return;
01926     key.type = P_TERM_FUNCTOR;
01927     key.size = predicate->header.size;
01928     key.name = predicate->predicate.name;
01929     node = _p_rbtree_insert(&(database->database.predicates), &key);
01930     if (!node)
01931         return;
01932     node->value = predicate;
01933 }
01934 
01944 p_term *p_term_database_lookup_predicate
01945     (p_term *database, p_term *name, int arity)
01946 {
01947     p_rbkey key;
01948     p_rbnode *node;
01949     database = p_term_deref(database);
01950     name = p_term_deref(name);
01951     if (!database || database->header.type != P_TERM_DATABASE)
01952         return 0;
01953     if (!name || name->header.type != P_TERM_ATOM)
01954         return 0;
01955     key.type = P_TERM_FUNCTOR;
01956     key.size = arity;
01957     key.name = name;
01958     node = _p_rbtree_lookup(&(database->database.predicates), &key);
01959     if (node)
01960         return node->value;
01961     else
01962         return 0;
01963 }
01964 
01976 p_term *p_term_create_member_name
01977     (p_context *context, p_term *class_name, p_term *name)
01978 {
01979     size_t clen = p_term_name_length(class_name);
01980     size_t nlen = p_term_name_length(name);
01981     char *str = (char *)GC_MALLOC(clen + nlen + 2);
01982     p_term *result;
01983     if (!str)
01984         return name;
01985     memcpy(str, p_term_name(class_name), clen);
01986     str[clen] = ':';
01987     str[clen + 1] = ':';
01988     memcpy(str + clen + 2, p_term_name(name), nlen);
01989     result = p_term_create_atom_n(context, str, clen + nlen + 2);
01990     GC_FREE(str);
01991     return result;
01992 }
01993 
01994 
01995 int p_term_occurs_in(const p_term *var, const p_term *value)
01996 {
01997     unsigned int index;
01998     if (!value)
01999         return 0;
02000     value = p_term_deref_non_null(value);
02001     if (var == value)
02002         return 1;
02003     switch (value->header.type) {
02004     case P_TERM_FUNCTOR:
02005         
02006         for (index = 0; index < value->header.size; ++index) {
02007             if (p_term_occurs_in(var, value->functor.arg[index]))
02008                 return 1;
02009         }
02010         break;
02011     case P_TERM_LIST:
02012         
02013         do {
02014             if (p_term_occurs_in(var, value->list.head))
02015                 return 1;
02016             value = value->list.tail;
02017             if (!value)
02018                 return 0;
02019             value = p_term_deref_non_null(value);
02020         } while (value->header.type == P_TERM_LIST);
02021         if (value->header.type != P_TERM_ATOM)
02022             return p_term_occurs_in(var, value);
02023         break;
02024     case P_TERM_OBJECT:
02025         
02026         do {
02027             for (index = 0; index < value->header.size; ++index) {
02028                 if (p_term_occurs_in
02029                         (var, value->object.properties[index].value))
02030                     return 1;
02031             }
02032             value = value->object.next;
02033         }
02034         while (value);
02035         break;
02036     case P_TERM_MEMBER_VARIABLE:
02037         return p_term_occurs_in(var, value->member_var.object);
02038     default: break;
02039     }
02040     return 0;
02041 }
02042 
02111 int p_term_bind_variable(p_context *context, p_term *var, p_term *value, int flags)
02112 {
02113     if (!var)
02114         return 0;
02115     var = p_term_deref_non_null(var);
02116     if ((var->header.type & P_TERM_VARIABLE) == 0)
02117         return 0;
02118     if ((flags & P_BIND_NO_OCCURS_CHECK) == 0) {
02119         if (p_term_occurs_in(var, value))
02120             return 0;
02121     }
02122     if ((flags & P_BIND_NO_RECORD) == 0) {
02123         if (!_p_context_record_in_trail(context, var))
02124             return 0;
02125     }
02126     var->var.value = value;
02127     return 1;
02128 }
02129 
02130 
02131 P_INLINE int p_term_bind_var(p_context *context, p_term *var, p_term *value, int flags)
02132 {
02133     if ((flags & P_BIND_NO_OCCURS_CHECK) == 0) {
02134         if (p_term_occurs_in(var, value))
02135             return 0;
02136     }
02137     if ((flags & P_BIND_NO_RECORD) == 0) {
02138         if (!_p_context_record_in_trail(context, var))
02139             return 0;
02140     }
02141     var->var.value = value;
02142     return 1;
02143 }
02144 
02145 
02146 static int p_term_unify_inner(p_context *context, p_term *term1, p_term *term2, int flags);
02147 
02148 
02149 static p_term *p_term_resolve_member(p_context *context, p_term *term, int flags)
02150 {
02151     p_term *object = term->member_var.object;
02152     p_term *value;
02153     if (!object)
02154         return 0;
02155     object = p_term_deref_non_null(object);
02156     if (object->header.type == P_TERM_MEMBER_VARIABLE) {
02157         
02158         object = p_term_resolve_member(context, object, flags);
02159         if (!object)
02160             return 0;
02161         object = p_term_deref_non_null(object);
02162     }
02163     if (object->header.type != P_TERM_OBJECT)
02164         return 0;
02165     value = p_term_property(context, object, term->member_var.name);
02166     if (!value && term->header.size && (flags & P_BIND_EQUALITY) == 0) {
02167         
02168         value = p_term_create_variable(context);
02169         if (!p_term_add_property(context, object,
02170                                  term->member_var.name, value))
02171             return 0;
02172     }
02173     return value;
02174 }
02175 
02176 
02177 static int p_term_unify_variable(p_context *context, p_term *term1, p_term *term2, int flags)
02178 {
02179     
02180     if (term1->header.type == P_TERM_MEMBER_VARIABLE) {
02181         term1 = p_term_resolve_member(context, term1, flags);
02182         return p_term_unify_inner(context, term1, term2, flags);
02183     }
02184     if (term2->header.type == P_TERM_MEMBER_VARIABLE) {
02185         term2 = p_term_resolve_member(context, term2, flags);
02186         return p_term_unify_inner(context, term1, term2, flags);
02187     }
02188 
02189     
02190     if (flags & P_BIND_EQUALITY)
02191         return 0;
02192 
02193     
02194     if (flags & P_BIND_RECORD_ONE_WAY)
02195         flags |= P_BIND_NO_RECORD;
02196     return p_term_bind_var(context, term1, term2, flags);
02197 }
02198 
02199 
02200 static int p_term_unify_inner(p_context *context, p_term *term1, p_term *term2, int flags)
02201 {
02202     if (!term1 || !term2)
02203         return 0;
02204     term1 = p_term_deref_non_null(term1);
02205     term2 = p_term_deref_non_null(term2);
02206     if (term1 == term2)
02207         return 1;
02208     if (term1->header.type & P_TERM_VARIABLE)
02209         return p_term_unify_variable(context, term1, term2, flags);
02210     if (term2->header.type & P_TERM_VARIABLE) {
02211         if (flags & P_BIND_ONE_WAY)
02212             return 0;
02213         return p_term_unify_variable
02214             (context, term2, term1, flags & ~P_BIND_RECORD_ONE_WAY);
02215     }
02216     switch (term1->header.type) {
02217     case P_TERM_FUNCTOR:
02218         
02219         if (term2->header.type == P_TERM_FUNCTOR &&
02220                 term1->header.size == term2->header.size &&
02221                 term1->functor.functor_name ==
02222                         term2->functor.functor_name) {
02223             unsigned int index;
02224             for (index = 0; index < term1->header.size; ++index) {
02225                 if (!p_term_unify_inner
02226                         (context, term1->functor.arg[index],
02227                          term2->functor.arg[index], flags))
02228                     return 0;
02229             }
02230             return 1;
02231         }
02232         break;
02233     case P_TERM_LIST:
02234         
02235 
02236         if (term2->header.type != P_TERM_LIST)
02237             return 0;
02238         for (;;) {
02239             if (!p_term_unify_inner(context, term1->list.head,
02240                                     term2->list.head, flags))
02241                 break;
02242             term1 = term1->list.tail;
02243             term2 = term2->list.tail;
02244             if (!term1 || !term2)
02245                 break;
02246             term1 = p_term_deref_non_null(term1);
02247             term2 = p_term_deref_non_null(term2);
02248             if (term1->header.type != P_TERM_LIST ||
02249                     term2->header.type != P_TERM_LIST)
02250                 return p_term_unify_inner(context, term1, term2, flags);
02251         }
02252         break;
02253     case P_TERM_ATOM:
02254         
02255 
02256         break;
02257     case P_TERM_STRING:
02258         
02259         if (term2->header.type == P_TERM_STRING &&
02260                 term1->header.size == term2->header.size &&
02261                 !memcmp(term1->string.name, term2->string.name,
02262                         term1->header.size))
02263             return 1;
02264         break;
02265     case P_TERM_INTEGER:
02266         
02267         if (term2->header.type == P_TERM_INTEGER) {
02268 #if defined(P_TERM_64BIT)
02269             
02270             return term1->header.size == term2->header.size;
02271 #else
02272             return term1->integer.value == term2->integer.value;
02273 #endif
02274         }
02275         break;
02276     case P_TERM_REAL:
02277         
02278         if (term2->header.type == P_TERM_REAL)
02279             return term1->real.value == term2->real.value;
02280         break;
02281     case P_TERM_OBJECT:
02282     case P_TERM_PREDICATE:
02283     case P_TERM_CLAUSE:
02284     case P_TERM_DATABASE:
02285         
02286 
02287 
02288         break;
02289     default: break;
02290     }
02291     return 0;
02292 }
02293 
02303 int p_term_unify(p_context *context, p_term *term1, p_term *term2, int flags)
02304 {
02305     void *marker = p_context_mark_trail(context);
02306     int result = p_term_unify_inner(context, term1, term2, flags);
02307     if (!result && (flags & P_BIND_NO_RECORD) == 0)
02308         p_context_backtrack_trail(context, marker);
02309     return result;
02310 }
02311 
02330 void p_term_stdio_print_func(void *data, const char *format, ...)
02331 {
02332     va_list va;
02333     va_start(va, format);
02334     vfprintf((FILE *)data, format, va);
02335     va_end(va);
02336 }
02337 
02338 
02339 static const p_term *p_term_deref_limited(const p_term *term)
02340 {
02341     int count = 32;
02342     if (!term)
02343         return 0;
02344     while (count-- > 0) {
02345         if (term->header.type & P_TERM_VARIABLE) {
02346             if (!term->var.value)
02347                 break;
02348             term = term->var.value;
02349         } else {
02350             break;
02351         }
02352     }
02353     return term;
02354 }
02355 
02356 
02357 static void p_term_print_quoted(const p_term *term, p_term_print_func print_func, void *print_data, int quote)
02358 {
02359     const char *str = p_term_name(term);
02360     size_t len = p_term_name_length(term);
02361     int ch;
02362     (*print_func)(print_data, "%c", quote);
02363     while (len-- > 0) {
02364         ch = ((int)(*str++)) & 0xFF;
02365         if (ch == quote || ch == '\\')
02366             (*print_func)(print_data, "\\%c", ch);
02367         else if (ch >= 0x20)
02368             (*print_func)(print_data, "%c", ch);
02369         else if (ch == '\t')
02370             (*print_func)(print_data, "\\t");
02371         else if (ch == '\n')
02372             (*print_func)(print_data, "\\n");
02373         else if (ch == '\r')
02374             (*print_func)(print_data, "\\r");
02375         else if (ch == '\f')
02376             (*print_func)(print_data, "\\f");
02377         else if (ch == '\v')
02378             (*print_func)(print_data, "\\v");
02379         else if (ch == '\0')
02380             (*print_func)(print_data, "\\0");
02381         else
02382             (*print_func)(print_data, "\\x%02x", ch);
02383     }
02384     (*print_func)(print_data, "%c", quote);
02385 }
02386 
02387 
02388 static void p_term_print_atom(const p_term *atom, p_term_print_func print_func, void *print_data)
02389 {
02390     const char *name = p_term_name(atom);
02391     int ok;
02392     if (!name)
02393         return;
02394     if (*name >= 'a' && *name <= 'z') {
02395         ++name;
02396         while (*name != '\0') {
02397             if (*name >= 'a' && *name <= 'z')
02398                 ++name;
02399             else if (*name >= 'Z' && *name <= 'Z')
02400                 ++name;
02401             else if (*name >= '0' && *name <= '9')
02402                 ++name;
02403             else if (*name == '_')
02404                 ++name;
02405             else if (*name == ':' && name[1] == ':')
02406                 name += 2;
02407             else
02408                 break;
02409         }
02410         ok = (name == (atom->atom.name + atom->header.size));
02411     } else if (*name == '[' && name[1] == ']' && name[2] == '\0' &&
02412                atom->header.size == 2) {
02413         ok = 1;
02414     } else {
02415         ok = 0;
02416     }
02417     if (ok)
02418         (*print_func)(print_data, "%s", p_term_name(atom));
02419     else
02420         p_term_print_quoted(atom, print_func, print_data, '\'');
02421 }
02422 
02423 static p_term *p_term_var_name(const p_term *vars, const p_term *var)
02424 {
02425     p_term *v;
02426     vars = p_term_deref(vars);
02427     while (vars && vars->header.type == P_TERM_LIST) {
02428         v = p_term_arg(vars->list.head, 1);
02429         while (v && v != var) {
02430             if (v->header.type & P_TERM_VARIABLE)
02431                 v = v->var.value;
02432             else
02433                 break;
02434         }
02435         if (v == var) {
02436             p_term *name = p_term_deref(p_term_arg(vars->list.head, 0));
02437             if (name && (name->header.type == P_TERM_ATOM ||
02438                          name->header.type == P_TERM_STRING))
02439                 return name;
02440             else
02441                 break;
02442         }
02443         vars = p_term_deref(vars->list.tail);
02444     }
02445     return 0;
02446 }
02447 
02448 static void p_term_print_inner(p_context *context, const p_term *term, p_term_print_func print_func, void *print_data, int level, int prec, const p_term *vars)
02449 {
02450     
02451     if (level <= 0) {
02452         (*print_func)(print_data, "...");
02453         return;
02454     }
02455 
02456     
02457     if (!term) {
02458         (*print_func)(print_data, "NULL");
02459         return;
02460     }
02461 
02462     
02463     switch (term->header.type) {
02464     case P_TERM_FUNCTOR: {
02465         unsigned int index;
02466         p_op_specifier spec;
02467         int priority;
02468         spec = p_db_operator_info
02469             (term->functor.functor_name,
02470              (int)(term->header.size), &priority);
02471         if (spec == P_OP_NONE) {
02472             p_term_print_atom(term->functor.functor_name,
02473                               print_func, print_data);
02474             (*print_func)(print_data, "(");
02475             for (index = 0; index < term->header.size; ++index) {
02476                 if (index)
02477                     (*print_func)(print_data, ", ");
02478                 p_term_print_inner
02479                     (context, term->functor.arg[index],
02480                      print_func, print_data, level - 1, 950, vars);
02481             }
02482             (*print_func)(print_data, ")");
02483         } else {
02484             int bracketed = (priority > prec);
02485             if (bracketed) {
02486                 (*print_func)(print_data, "(");
02487                 priority = 1300;
02488             }
02489             switch (spec) {
02490             case P_OP_NONE: break;
02491             case P_OP_XF:
02492                 p_term_print_inner
02493                     (context, term->functor.arg[0],
02494                      print_func, print_data, level - 1,
02495                      priority - 1, vars);
02496                 (*print_func)(print_data, " %s",
02497                               p_term_name(term->functor.functor_name));
02498                 break;
02499             case P_OP_YF:
02500                 p_term_print_inner
02501                     (context, term->functor.arg[0],
02502                      print_func, print_data, level - 1, priority, vars);
02503                 (*print_func)(print_data, " %s",
02504                               p_term_name(term->functor.functor_name));
02505                 break;
02506             case P_OP_XFX:
02507                 p_term_print_inner
02508                     (context, term->functor.arg[0],
02509                      print_func, print_data, level - 1,
02510                      priority - 1, vars);
02511                 (*print_func)(print_data, " %s ",
02512                               p_term_name(term->functor.functor_name));
02513                 p_term_print_inner
02514                     (context, term->functor.arg[1],
02515                      print_func, print_data, level - 1,
02516                      priority - 1, vars);
02517                 break;
02518             case P_OP_XFY:
02519                 p_term_print_inner
02520                     (context, term->functor.arg[0],
02521                      print_func, print_data, level - 1,
02522                      priority - 1, vars);
02523                 (*print_func)(print_data, " %s ",
02524                               p_term_name(term->functor.functor_name));
02525                 p_term_print_inner
02526                     (context, term->functor.arg[1],
02527                      print_func, print_data, level - 1,
02528                      priority, vars);
02529                 break;
02530             case P_OP_YFX:
02531                 p_term_print_inner
02532                     (context, term->functor.arg[0],
02533                      print_func, print_data, level - 1, priority, vars);
02534                 (*print_func)(print_data, " %s ",
02535                               p_term_name(term->functor.functor_name));
02536                 p_term_print_inner
02537                     (context, term->functor.arg[1],
02538                      print_func, print_data, level - 1,
02539                      priority - 1, vars);
02540                 break;
02541             case P_OP_FX:
02542                 (*print_func)(print_data, "%s ",
02543                               p_term_name(term->functor.functor_name));
02544                 p_term_print_inner
02545                     (context, term->functor.arg[0],
02546                      print_func, print_data, level - 1,
02547                      priority - 1, vars);
02548                 break;
02549             case P_OP_FY:
02550                 (*print_func)(print_data, "%s ",
02551                               p_term_name(term->functor.functor_name));
02552                 p_term_print_inner
02553                     (context, term->functor.arg[0],
02554                      print_func, print_data, level - 1, priority, vars);
02555                 break;
02556             }
02557             if (bracketed)
02558                 (*print_func)(print_data, ")");
02559         }
02560         break; }
02561     case P_TERM_LIST:
02562         (*print_func)(print_data, "[");
02563         p_term_print_inner(context, term->list.head,
02564                            print_func, print_data,
02565                            level - 1, 950, vars);
02566         term = p_term_deref_limited(term->list.tail);
02567         while (term && term->header.type == P_TERM_LIST && level > 0) {
02568             (*print_func)(print_data, ", ");
02569             p_term_print_inner(context, term->list.head,
02570                                print_func, print_data,
02571                                level - 1, 950, vars);
02572             term = p_term_deref_limited(term->list.tail);
02573             --level;
02574         }
02575         if (level <= 0) {
02576             (*print_func)(print_data, "|...]");
02577             break;
02578         }
02579         if (term != context->nil_atom) {
02580             (*print_func)(print_data, "|");
02581             p_term_print_inner(context, term, print_func,
02582                                print_data, level - 1, 950, vars);
02583         }
02584         (*print_func)(print_data, "]");
02585         break;
02586     case P_TERM_ATOM:
02587         p_term_print_atom(term, print_func, print_data);
02588         break;
02589     case P_TERM_STRING:
02590         p_term_print_quoted(term, print_func, print_data, '"');
02591         break;
02592     case P_TERM_INTEGER:
02593         (*print_func)(print_data, "%d", p_term_integer_value(term));
02594         break;
02595     case P_TERM_REAL:
02596         (*print_func)(print_data, "%.10g", p_term_real_value(term));
02597         break;
02598     case P_TERM_OBJECT: {
02599         p_term *name = p_term_property
02600             (context, term, context->class_name_atom);
02601         unsigned int index;
02602         int first = 1;
02603         if (p_term_is_class_object(context, term))
02604             (*print_func)(print_data, "class ");
02605         if (name)
02606             (*print_func)(print_data, "%s {", p_term_name(name));
02607         else
02608             (*print_func)(print_data, "unknown_class {");
02609         do {
02610             for (index = 0; index < term->header.size; ++index) {
02611                 name = term->object.properties[index].name;
02612                 if (name == context->class_name_atom)
02613                     continue;
02614                 if (name == context->prototype_atom)
02615                     continue;
02616                 if (!first)
02617                     (*print_func)(print_data, ", ");
02618                 p_term_print_atom(name, print_func, print_data);
02619                 (*print_func)(print_data, ": ");
02620                 p_term_print_inner
02621                     (context, term->object.properties[index].value,
02622                      print_func, print_data, level - 1, 950, vars);
02623                 first = 0;
02624             }
02625             term = term->object.next;
02626         } while (term != 0);
02627         (*print_func)(print_data, "}");
02628         break; }
02629     case P_TERM_PREDICATE:
02630         (*print_func)(print_data, "predicate ");
02631         p_term_print_atom(term->predicate.name, print_func, print_data);
02632         (*print_func)(print_data, "/%d", (int)(term->header.size));
02633         break;
02634     case P_TERM_CLAUSE:
02635         (*print_func)(print_data, "clause %lx", (long)term);
02636         break;
02637     case P_TERM_DATABASE:
02638         (*print_func)(print_data, "database %lx", (long)term);
02639         break;
02640     case P_TERM_VARIABLE: {
02641         if (term->var.value) {
02642             p_term_print_inner(context, term->var.value, print_func,
02643                                print_data, level - 1, prec, vars);
02644         } else if (vars) {
02645             p_term *name = p_term_var_name(vars, term);
02646             if (name)
02647                 (*print_func)(print_data, "%s", p_term_name(name));
02648             else
02649                 (*print_func)(print_data, "_%lx", (long)term);
02650         } else if (term->header.size > 0) {
02651             (*print_func)(print_data, "%s", p_term_name(term));
02652         } else {
02653             (*print_func)(print_data, "_%lx", (long)term);
02654         }
02655         break; }
02656     case P_TERM_MEMBER_VARIABLE:
02657         if (term->var.value) {
02658             p_term_print_inner(context, term->var.value, print_func,
02659                                print_data, level - 1, prec, vars);
02660             break;
02661         }
02662         p_term_print_inner(context, term->member_var.object, print_func,
02663                            print_data, level - 1, 0, vars);
02664         (*print_func)(print_data, ".");
02665         p_term_print_atom(term->member_var.name, print_func, print_data);
02666         break;
02667     default: break;
02668     }
02669 }
02670 
02682 void p_term_print(p_context *context, const p_term *term, p_term_print_func print_func, void *print_data)
02683 {
02684     p_term_print_inner(context, term, print_func, print_data, 1000, 1300, 0);
02685 }
02686 
02701 void p_term_print_unquoted(p_context *context, const p_term *term, p_term_print_func print_func, void *print_data)
02702 {
02703     term = p_term_deref(term);
02704     if (term) {
02705         if (term->header.type == P_TERM_ATOM ||
02706                 term->header.type == P_TERM_STRING) {
02707             (*print_func)(print_data, "%s", p_term_name(term));
02708             return;
02709         }
02710     }
02711     p_term_print_inner(context, term, print_func, print_data, 1000, 1300, 0);
02712 }
02713 
02726 void p_term_print_with_vars(p_context *context, const p_term *term, p_term_print_func print_func, void *print_data, const p_term *vars)
02727 {
02728     if (!vars)
02729         vars = p_term_nil_atom(context);
02730     p_term_print_inner(context, term, print_func, print_data, 1000, 1300, vars);
02731 }
02732 
02751 int p_term_precedes(p_context *context, const p_term *term1, const p_term *term2)
02752 {
02753     int group1, group2, cmp;
02754     static unsigned char const precedes_ordering[] = {
02755         0,  
02756         6,  
02757         6,  
02758         5,  
02759         4,  
02760         3,  
02761         2,  
02762         7,  
02763         8,  
02764         9,  
02765         10, 
02766         0, 0, 0, 0, 0,
02767         1,  
02768         1   
02769     };
02770 
02771     
02772     if (!term1)
02773         return term2 ? -1 : 0;
02774     if (!term2)
02775         return 1;
02776     term1 = p_term_deref_non_null(term1);
02777     term2 = p_term_deref_non_null(term2);
02778     if (term1 == term2)
02779         return 0;
02780 
02781     
02782     group1 = precedes_ordering[term1->header.type];
02783     group2 = precedes_ordering[term2->header.type];
02784     if (group1 < group2)
02785         return -1;
02786     else if (group1 > group2)
02787         return 1;
02788 
02789     
02790     switch (term1->header.type) {
02791     case P_TERM_FUNCTOR:
02792     case P_TERM_LIST: {
02793         p_term *name1;
02794         p_term *name2;
02795         unsigned int index;
02796         if (term1->header.size < term2->header.size)
02797             return -1;
02798         else if (term1->header.size > term2->header.size)
02799             return 1;
02800         if (term1->header.type == P_TERM_FUNCTOR)
02801             name1 = term1->functor.functor_name;
02802         else
02803             name1 = context->dot_atom;
02804         if (term2->header.type == P_TERM_FUNCTOR)
02805             name2 = term2->functor.functor_name;
02806         else
02807             name2 = context->dot_atom;
02808         cmp = p_term_strcmp(name1, name2);
02809         if (cmp < 0)
02810             return -1;
02811         else if (cmp > 0)
02812             return 1;
02813         if (term1->header.type == P_TERM_FUNCTOR &&
02814                 term2->header.type == P_TERM_FUNCTOR) {
02815             for (index = 0; index < term1->header.size; ++index) {
02816                 cmp = p_term_precedes(context,
02817                                       term1->functor.arg[index],
02818                                       term2->functor.arg[index]);
02819                 if (cmp != 0)
02820                     return cmp;
02821             }
02822         } else if (term1->header.type == P_TERM_LIST &&
02823                    term2->header.type == P_TERM_LIST) {
02824             do {
02825                 cmp = p_term_precedes
02826                     (context, term1->list.head, term2->list.head);
02827                 if (cmp != 0)
02828                     return cmp;
02829                 term1 = term1->list.tail;
02830                 term2 = term2->list.tail;
02831                 if (!term1 || !term2)
02832                     break;
02833                 term1 = p_term_deref_non_null(term1);
02834                 term2 = p_term_deref_non_null(term2);
02835             } while (term1->header.type == P_TERM_LIST &&
02836                      term2->header.type == P_TERM_LIST);
02837             return p_term_precedes(context, term1, term2);
02838         } else {
02839             
02840 
02841 
02842             return (term1 < term2) ? -1 : 1;
02843         }
02844         break; }
02845     case P_TERM_ATOM:
02846     case P_TERM_STRING:
02847         cmp = p_term_strcmp(term1, term2);
02848         if (cmp < 0)
02849             return -1;
02850         else if (cmp > 0)
02851             return 1;
02852         break;
02853     case P_TERM_INTEGER:
02854 #if defined(P_TERM_64BIT)
02855         if (((int)(term1->header.size)) < ((int)(term2->header.size)))
02856             return -1;
02857         else if (((int)(term1->header.size)) > ((int)(term2->header.size)))
02858             return 1;
02859 #else
02860         if (term1->integer.value < term2->integer.value)
02861             return -1;
02862         else if (term1->integer.value > term2->integer.value)
02863             return 1;
02864 #endif
02865         break;
02866     case P_TERM_REAL:
02867         if (term1->real.value < term2->real.value)
02868             return -1;
02869         else if (term1->real.value > term2->real.value)
02870             return 1;
02871         break;
02872     case P_TERM_OBJECT:
02873     case P_TERM_PREDICATE:
02874     case P_TERM_CLAUSE:
02875     case P_TERM_DATABASE:
02876     case P_TERM_VARIABLE:
02877     case P_TERM_MEMBER_VARIABLE:
02878         return (term1 < term2) ? -1 : 1;
02879     default: break;
02880     }
02881     return 0;
02882 }
02883 
02893 int p_term_is_ground(const p_term *term)
02894 {
02895     if (!term)
02896         return 0;
02897     term = p_term_deref_non_null(term);
02898     switch (term->header.type) {
02899     case P_TERM_FUNCTOR: {
02900         unsigned int index;
02901         for (index = 0; index < term->header.size; ++index) {
02902             if (!p_term_is_ground(term->functor.arg[index]))
02903                 return 0;
02904         }
02905         return 1; }
02906     case P_TERM_LIST:
02907         do {
02908             if (!p_term_is_ground(term->list.head))
02909                 return 0;
02910             term = term->list.tail;
02911             if (!term)
02912                 return 0;
02913             term = p_term_deref_non_null(term);
02914         }
02915         while (term->header.type == P_TERM_LIST);
02916         return p_term_is_ground(term);
02917     case P_TERM_ATOM:
02918     case P_TERM_STRING:
02919     case P_TERM_INTEGER:
02920     case P_TERM_REAL:
02921     case P_TERM_OBJECT:
02922     case P_TERM_PREDICATE:
02923     case P_TERM_CLAUSE:
02924     case P_TERM_DATABASE:
02925         return 1;
02926     case P_TERM_VARIABLE:
02927     case P_TERM_MEMBER_VARIABLE:
02928     case P_TERM_RENAME:
02929         return 0;
02930     default: break;
02931     }
02932     return 0;
02933 }
02934 
02935 static p_term *p_term_clone_inner(p_context *context, p_term *term)
02936 {
02937     p_term *clone;
02938     p_term *rename;
02939     if (!term)
02940         return 0;
02941     term = p_term_deref_non_null(term);
02942     switch (term->header.type) {
02943     case P_TERM_FUNCTOR: {
02944         
02945         unsigned int index;
02946         clone = p_term_create_functor
02947             (context, term->functor.functor_name,
02948              (int)(term->header.size));
02949         if (!clone)
02950             return 0;
02951         for (index = 0; index < term->header.size; ++index) {
02952             p_term *arg = p_term_clone_inner
02953                 (context, term->functor.arg[index]);
02954             if (!arg)
02955                 return 0;
02956             p_term_bind_functor_arg(clone, (int)index, arg);
02957         }
02958         return clone; }
02959     case P_TERM_LIST: {
02960         
02961         p_term *head;
02962         p_term *tail = 0;
02963         clone = 0;
02964         do {
02965             head = p_term_clone_inner(context, term->list.head);
02966             if (!head)
02967                 return 0;
02968             head = p_term_create_list(context, head, 0);
02969             if (tail)
02970                 tail->list.tail = head;
02971             else
02972                 clone = head;
02973             tail = head;
02974             term = term->list.tail;
02975             if (!term)
02976                 return 0;
02977             term = p_term_deref_non_null(term);
02978         }
02979         while (term->header.type == P_TERM_LIST);
02980         head = p_term_clone_inner(context, term);
02981         if (!head)
02982             return 0;
02983         tail->list.tail = head;
02984         return clone; }
02985     case P_TERM_ATOM:
02986     case P_TERM_STRING:
02987     case P_TERM_INTEGER:
02988     case P_TERM_REAL:
02989     case P_TERM_OBJECT:
02990     case P_TERM_PREDICATE:
02991     case P_TERM_DATABASE:
02992         
02993         break;
02994     case P_TERM_VARIABLE:
02995         
02996 
02997 
02998         if (term->header.size > 0)
02999             clone = p_term_create_named_variable(context, p_term_name(term));
03000         else
03001             clone = p_term_create_variable(context);
03002         if (!clone)
03003             return 0;
03004         _p_context_record_in_trail(context, term);
03005         rename = p_term_malloc
03006             (context, p_term, sizeof(struct p_term_rename));
03007         if (!rename)
03008             return 0;
03009         rename->header.type = P_TERM_RENAME;
03010         rename->rename.var = clone;
03011         term->var.value = rename;
03012         return clone;
03013     case P_TERM_MEMBER_VARIABLE:
03014         
03015         clone = p_term_clone_inner(context, term->member_var.object);
03016         if (!clone)
03017             return 0;
03018         clone = p_term_create_member_variable
03019             (context, clone, term->member_var.name,
03020              (int)(term->header.size));
03021         if (!clone)
03022             return 0;
03023         _p_context_record_in_trail(context, term);
03024         rename = p_term_malloc
03025             (context, p_term, sizeof(struct p_term_rename));
03026         if (!rename)
03027             return 0;
03028         rename->header.type = P_TERM_RENAME;
03029         rename->rename.var = clone;
03030         term->var.value = rename;
03031         return clone;
03032     case P_TERM_RENAME:
03033         
03034         return term->rename.var;
03035     default: break;
03036     }
03037     return term;
03038 }
03039 
03048 p_term *p_term_clone(p_context *context, p_term *term)
03049 {
03050     
03051 
03052 
03053 
03054     void *marker = p_context_mark_trail(context);
03055     p_term *clone = p_term_clone_inner(context, term);
03056     p_context_backtrack_trail(context, marker);
03057     return clone;
03058 }
03059 
03076 p_term *p_term_unify_clause(p_context *context, p_term *term, p_term *clause)
03077 {
03078     unsigned int index;
03079     p_goal_result result;
03080     p_term *body = 0;
03081 
03082     
03083     term = p_term_deref(term);
03084     if (!term)
03085         return 0;
03086     if (term->header.type == P_TERM_FUNCTOR) {
03087         for (index = 0; index < term->header.size; ++index) {
03088             _p_code_set_xreg
03089                 (context, (int)index, term->functor.arg[index]);
03090         }
03091     }
03092 
03093     
03094 
03095     result = _p_code_run(context, &(clause->clause.clause_code), &body);
03096     if (result == P_RESULT_RETURN_BODY)
03097         return body;
03098     else if (result == P_RESULT_TRUE)
03099         return context->true_atom;
03100     else
03101         return 0;
03102 }
03103 
03117 int p_term_strcmp(const p_term *str1, const p_term *str2)
03118 {
03119     const char *s1;
03120     unsigned int s1len;
03121     const char *s2;
03122     unsigned int s2len;
03123     int cmp;
03124     if (!str1 || !str2)
03125         return 0;
03126     str1 = p_term_deref_non_null(str1);
03127     str2 = p_term_deref_non_null(str2);
03128     if (str1->header.type == P_TERM_ATOM) {
03129         s1 = str1->atom.name;
03130         s1len = str1->header.size;
03131     } else if (str1->header.type == P_TERM_STRING) {
03132         s1 = str1->string.name;
03133         s1len = str1->header.size;
03134     } else {
03135         return 0;
03136     }
03137     if (str2->header.type == P_TERM_ATOM) {
03138         s2 = str2->atom.name;
03139         s2len = str2->header.size;
03140     } else if (str2->header.type == P_TERM_STRING) {
03141         s2 = str2->string.name;
03142         s2len = str2->header.size;
03143     } else {
03144         return 0;
03145     }
03146     if (!s1len)
03147         return s2len ? -1 : 0;
03148     if (!s2len)
03149         return s1len ? 1 : 0;
03150     if (s1len == s2len) {
03151         return memcmp(s1, s2, s1len);
03152     } else if (s1len < s2len) {
03153         cmp = memcmp(s1, s2, s1len);
03154         if (cmp != 0)
03155             return cmp;
03156         else
03157             return -1;
03158     } else {
03159         cmp = memcmp(s1, s2, s2len);
03160         if (cmp != 0)
03161             return cmp;
03162         else
03163             return 1;
03164     }
03165 }
03166 
03176 p_term *p_term_concat_string(p_context *context, p_term *str1, p_term *str2)
03177 {
03178     size_t len;
03179     struct p_term_string *term;
03180     str1 = p_term_deref(str1);
03181     str2 = p_term_deref(str2);
03182     if (!str1 || str1->header.type != P_TERM_STRING)
03183         return 0;
03184     if (!str2 || str2->header.type != P_TERM_STRING)
03185         return 0;
03186     if (str1->header.size == 0)
03187         return str2;
03188     if (str2->header.size == 0)
03189         return str1;
03190     len = str1->header.size + str2->header.size;
03191     term = p_term_malloc
03192         (context, struct p_term_string, sizeof(struct p_term_string) + len);
03193     if (!term)
03194         return 0;
03195     term->header.type = P_TERM_STRING;
03196     term->header.size = (unsigned int)len;
03197     memcpy(term->name, str1->string.name, str1->header.size);
03198     memcpy(term->name + str1->header.size, str2->string.name, str2->header.size);
03199     return (p_term *)term;
03200 }
03201 
03202 
03203 static p_term *p_term_witness_inner
03204     (p_context *context, p_term *term, p_term *list)
03205 {
03206     unsigned int index;
03207     if (!term)
03208         return list;
03209     term = p_term_deref_non_null(term);
03210     switch (term->header.type) {
03211     case P_TERM_FUNCTOR:
03212         
03213         for (index = 0; index < term->header.size; ++index) {
03214             list = p_term_witness_inner
03215                 (context, term->functor.arg[index], list);
03216         }
03217         break;
03218     case P_TERM_LIST:
03219         
03220         do {
03221             list = p_term_witness_inner(context, term->list.head, list);
03222             term = term->list.tail;
03223             if (!term)
03224                 break;
03225             term = p_term_deref_non_null(term);
03226         } while (term->header.type == P_TERM_LIST);
03227         return p_term_witness_inner(context, term, list);
03228     case P_TERM_VARIABLE:
03229         
03230 
03231 
03232 
03233 
03234         if (list)
03235             list = p_term_create_list(context, term, list);
03236         if (_p_context_record_in_trail(context, term))
03237             term->var.value = context->true_atom;
03238         break;
03239     case P_TERM_MEMBER_VARIABLE:
03240         
03241         return p_term_witness_inner
03242             (context, term->member_var.object, list);
03243     default: break;
03244     }
03245     return list;
03246 }
03247 
03260 p_term *p_term_witness(p_context *context, p_term *term, p_term **subgoal)
03261 {
03262     p_term *caret = p_term_create_atom(context, "^");
03263     p_term *list;
03264     void *marker = p_context_mark_trail(context);
03265     while (term) {
03266         term = p_term_deref_non_null(term);
03267         if (term->header.type == P_TERM_FUNCTOR &&
03268                 term->header.size == 2 &&
03269                 term->functor.functor_name == caret) {
03270             p_term_witness_inner(context, term->functor.arg[0], 0);
03271             term = term->functor.arg[1];
03272         } else {
03273             break;
03274         }
03275     }
03276     *subgoal = term;
03277     list = p_term_witness_inner(context, term, context->nil_atom);
03278     p_context_backtrack_trail(context, marker);
03279     return list;
03280 }
03281 
03282