diff --git a/C/c_interface.c b/C/c_interface.c index 90ed1d0d0..92627bda2 100644 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -479,6 +479,7 @@ X_API Term STD_PROTO(YAP_Read, (IOSTREAM *)); X_API void STD_PROTO(YAP_Write, (Term, IOSTREAM *, int)); X_API Term STD_PROTO(YAP_CopyTerm, (Term)); X_API int STD_PROTO(YAP_WriteBuffer, (Term, char *, size_t, int)); +X_API char *STD_PROTO(YAP_WriteDynamicBuffer, (Term, char *, size_t, size_t *, int *, int)); X_API char *STD_PROTO(YAP_CompileClause, (Term)); X_API void STD_PROTO(YAP_PutValue, (Atom,Term)); X_API Term STD_PROTO(YAP_GetValue, (Atom)); @@ -2802,10 +2803,30 @@ YAP_CopyTerm(Term t) X_API int YAP_WriteBuffer(Term t, char *buf, size_t sze, int flags) { + int enc; + size_t length; + char *b; + BACKUP_MACHINE_REGS(); - t = Yap_TermToString(t, buf, sze, flags); + if ((b = Yap_TermToString(t, buf, sze, &length, &enc, flags)) != buf) { + if (b) free(b); + RECOVER_MACHINE_REGS(); + return FALSE; + } RECOVER_MACHINE_REGS(); - return t; + return TRUE; +} + +X_API char * +YAP_WriteDynamicBuffer(Term t, char *buf, size_t sze, size_t *lengthp, int *encp, int flags) +{ + int enc; + char *b; + + BACKUP_MACHINE_REGS(); + b = Yap_TermToString(t, buf, sze, lengthp, encp, flags); + RECOVER_MACHINE_REGS(); + return b; } X_API char * diff --git a/C/iopreds.c b/C/iopreds.c index 0f964d340..c7791ff02 100644 --- a/C/iopreds.c +++ b/C/iopreds.c @@ -1090,6 +1090,24 @@ Yap_InitBackIO (void) { } +/* used to test writebuffer +static Int +p_write_string( USES_REGS1 ) +{ + Term in = Deref(ARG1); + char *s; + size_t length; + int encoding; + char buf[256]; + + if ((s = Yap_TermToString( in, NULL, 0, &length, &encoding, 0))) + fprintf(stderr,"%ld %s\n",length, s); + if ((s = Yap_TermToString( in, buf, 256, &length, &encoding, 0))) + fprintf(stderr,"%ld %s\n",length, s); + return TRUE; +} +*/ + void Yap_InitIOPreds(void) @@ -1101,6 +1119,7 @@ Yap_InitIOPreds(void) Yap_InitCPred ("$get_read_error_handler", 1, p_get_read_error_handler, SafePredFlag|SyncPredFlag|HiddenPredFlag); Yap_InitCPred ("$read", 7, p_read, SyncPredFlag|HiddenPredFlag|UserCPredFlag); Yap_InitCPred ("$read", 8, p_read2, SyncPredFlag|HiddenPredFlag|UserCPredFlag); + /* test predicate Yap_InitCPred ("write_string", 2, p_write_string, SyncPredFlag|UserCPredFlag); */ Yap_InitCPred ("$start_line", 1, p_startline, SafePredFlag|SyncPredFlag|HiddenPredFlag); Yap_InitCPred ("$change_type_of_char", 2, p_change_type_of_char, SafePredFlag|SyncPredFlag|HiddenPredFlag); Yap_InitCPred ("$type_of_char", 2, p_type_of_char, SafePredFlag|SyncPredFlag|HiddenPredFlag); diff --git a/C/pl-yap.c b/C/pl-yap.c index 529d43906..6fa9dabcc 100755 --- a/C/pl-yap.c +++ b/C/pl-yap.c @@ -836,7 +836,72 @@ PL_get_chars(term_t t, char **s, unsigned flags) { return PL_get_nchars(t, NULL, s, flags); } +char *Yap_TermToString(Term t, char *s, size_t sz, size_t *length, int *encoding, int flags); +char * +Yap_TermToString(Term t, char *s, size_t sz, size_t *length, int *encoding, int flags) +{ + CACHE_REGS + Int l; + + Yap_StartSlots( PASS_REGS1 ); + l = Yap_InitSlot(t); + + { IOENC encodings[3]; + IOENC *enc; + char *r, buf[256]; + + encodings[0] = ENC_ISO_LATIN_1; + encodings[1] = ENC_WCHAR; + encodings[2] = ENC_UNKNOWN; + + for(enc = encodings; *enc != ENC_UNKNOWN; enc++) + { + int64_t size; + IOSTREAM *fd; + + if (s) { + r = s; + } else { + r = buf; + } + fd = Sopenmem(&r, &sz, "w"); + fd->encoding = *enc; + if ( PL_write_term(fd, l, 1200, flags) && + Sputcode(EOS, fd) >= 0 && + Sflush(fd) >= 0 ) + { *encoding = *enc; + size = Stell64(fd); + if ( *enc == ENC_ISO_LATIN_1 ) + { + *length = size-1; + } else + { + *length = (size/sizeof(pl_wchar_t))-1; + } + /* found, just check if using local space */ + if (r == buf) { + char *bf = malloc(*length+1); + if (!bf) + return NULL; + strncpy(bf,buf,*length+1); + r = bf; + } + /* go away */ + Yap_CloseSlots( PASS_REGS1 ); + return r; + } else + { Sclose(fd); + } + } + /* failed */ + if ( r != s && r != buf ) { + Sfree(r); + } + } + Yap_CloseSlots( PASS_REGS1 ); + return NULL; +} X_API int diff --git a/H/yapio.h b/H/yapio.h index 590f6933a..e36e7c642 100644 --- a/H/yapio.h +++ b/H/yapio.h @@ -278,7 +278,7 @@ int STD_PROTO(Yap_GetCharForSIGINT,(void)); Int STD_PROTO(Yap_StreamToFileNo,(Term)); Term STD_PROTO(Yap_OpenStream,(FILE *,char *,Term,int)); Term STD_PROTO(Yap_StringToTerm,(char *,Term *)); -int Yap_TermToString(Term t, char *s, size_t sz, int flags); +char *Yap_TermToString(Term t, char *s, size_t sz, size_t *length, int *encoding, int flags); int Yap_GetFreeStreamD(void); int Yap_GetFreeStreamDForReading(void); diff --git a/docs/yap.tex b/docs/yap.tex index 94ceb0828..7ca40895b 100644 --- a/docs/yap.tex +++ b/docs/yap.tex @@ -17738,11 +17738,24 @@ flags in the @code{flag} argument: @code{YAP_WRITE_QUOTED}, @var{buff}, @code{size_t} @var{size}, @code{int} @var{flags}) @findex YAP_WriteBuffer/4 -Write a YAP_Term @var{t} to buffer @var{buff} with size @var{size}. The -flag are currently ignored. This function can fail, say, if the term -cannot be encoded in ISO-LATIN8. The code always uses -@code{YAP_WRITE_HANDLE_VARS}. You may also use @code{YAP_WRITE_QUOTED}, -and @code{YAP_WRITE_IGNORE_OPS} together. +Write a YAP_Term @var{t} to buffer @var{buff} with size +@var{size}. The term is written +according to a mask of the following flags in the @code{flag} +argument: @code{YAP_WRITE_QUOTED}, @code{YAP_WRITE_HANDLE_VARS}, +@code{YAP_WRITE_USE_PORTRAY}, and @code{YAP_WRITE_IGNORE_OPS}. The +function will fail if it does not have enough space in the buffer. + +@item @code{char *} YAP_WriteDynamicBuffer(@code{YAP_Term} @var{t}, @code{char *} +@var{buff}, @code{size_t} +@var{size}, @code{size_t} +@var{*lengthp}, @code{size_t} +@var{*encodingp}, @code{int} @var{flags}) +@findex YAP_WriteDynamicBuffer/6 +Write a YAP_Term @var{t} to buffer @var{buff} with size +@var{size}. The code will allocate an extra buffer if @var{buff} is +@code{NULL} or if @code{buffer} does not have enough room. The +variable @code{lengthp} is assigned the size of the resulting buffer, +and @code{encodingp} will receive the type of encoding (currently only @code{PL_ENC_ISO_LATIN_1} and @code{PL_ENC_WCHAR} are supported) @item @code{void} YAP_InitConsult(@code{int} @var{mode}, @code{char *} @var{filename}) @findex YAP_InitConsult/2 diff --git a/include/yap_structs.h b/include/yap_structs.h index 4b56c661d..fc9ef8dd8 100755 --- a/include/yap_structs.h +++ b/include/yap_structs.h @@ -255,6 +255,21 @@ typedef enum YAPC_COMPILE_ALL /* compile all predicates */ } yapc_exec_mode; +/********* encoding ***********************/ + +typedef enum +{ PL_ENC_UNKNOWN = 0, /* invalid/unknown */ + PL_ENC_OCTET, /* raw 8 bit input */ + PL_ENC_ASCII, /* US-ASCII (0..127) */ + PL_ENC_ISO_LATIN_1, /* ISO Latin-1 (0..256) */ + PL_ENC_ANSI, /* default (multibyte) codepage */ + PL_ENC_UTF8, + PL_ENC_UNICODE_BE, /* big endian unicode file */ + PL_ENC_UNICODE_LE, /* little endian unicode file */ + PL_ENC_WCHAR /* pl_wchar_t */ +} PL_IOENC; + + /********* YAP C-Flags ***********************/ typedef enum