1641 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			1641 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | 
 | ||
|  | #include "pl-incl.h"
 | ||
|  | #include "pl-ctype.h"
 | ||
|  | #include "pl-utf8.h"
 | ||
|  | #include "pl-dtoa.h"
 | ||
|  | #include "pl-umap.c"			/* Unicode map */
 | ||
|  | 
 | ||
|  | #include "pl-read.h"			/* read structure */
 | ||
|  | 
 | ||
|  | /**
 | ||
|  |  *  @defgroup ReadTerm Read Term from Streams | ||
|  |  *  @ingroup  InputOutput | ||
|  |  * @{ | ||
|  |  */ | ||
|  | 
 | ||
|  | static bool | ||
|  | isStringStream(IOSTREAM *s) | ||
|  | { return s->functions == &Sstringfunctions; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | void | ||
|  | init_read_data(ReadData _PL_rd, IOSTREAM *in ARG_LD) | ||
|  | {  CACHE_REGS | ||
|  |     memset(_PL_rd, 0, sizeof(*_PL_rd));	/* optimise! */ | ||
|  | 
 | ||
|  |   _PL_rd->magic = RD_MAGIC; | ||
|  |   _PL_rd->varnames = 0; | ||
|  |   _PL_rd->module = Yap_GetModuleEntry(CurrentModule); | ||
|  |   _PL_rd->exception = 0; | ||
|  |   _PL_rd->stream = in; | ||
|  |   _PL_rd->has_exception = 0; | ||
|  |   _PL_rd->module = MODULE_parse; | ||
|  |   _PL_rd->flags  = _PL_rd->module->flags; /* change for options! */ | ||
|  |   _PL_rd->styleCheck = LOCAL_debugstatus.styleCheck; | ||
|  |   _PL_rd->on_error = AtomError; | ||
|  |   _PL_rd->backquoted_string = truePrologFlag(PLFLAG_BACKQUOTED_STRING); | ||
|  | } | ||
|  | 
 | ||
|  | void | ||
|  | free_read_data(ReadData _PL_rd) | ||
|  | { | ||
|  | } | ||
|  | 
 | ||
|  | static int | ||
|  | read_term(term_t t, ReadData _PL_rd ARG_LD) | ||
|  | { | ||
|  |   return Yap_read_term(t, rb.stream, _PL_rd); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static void	  addUTF8Buffer(Buffer b, int c); | ||
|  | 
 | ||
|  | static void | ||
|  | addUTF8Buffer(Buffer b, int c) | ||
|  | { if ( c >= 0x80 ) | ||
|  |     { char buf[6]; | ||
|  |       char *p, *end; | ||
|  | 
 | ||
|  |       end = utf8_put_char(buf, c); | ||
|  |       for(p=buf; p<end; p++) | ||
|  | 	{ addBuffer(b, *p&0xff, char); | ||
|  | 	} | ||
|  |     } else | ||
|  |     { addBuffer(b, c, char); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | /*******************************
 | ||
|  |  *     UNICODE CLASSIFIERS      * | ||
|  |  *******************************/ | ||
|  | 
 | ||
|  | #define CharTypeW(c, t, w)					\
 | ||
|  |   ((unsigned)(c) <= 0xff ? (_PL_char_types[(unsigned)(c)] t)	\ | ||
|  |    : (uflagsW(c) & (w))) | ||
|  | 
 | ||
|  | #define PlBlankW(c)     CharTypeW(c, == SP, U_SEPARATOR)
 | ||
|  | #define PlUpperW(c)     CharTypeW(c, == UC, U_UPPERCASE)
 | ||
|  | #define PlIdStartW(c)   (c <= 0xff ? (isLower(c)||isUpper(c)||c=='_')	\
 | ||
|  | 			 : uflagsW(c) & U_ID_START) | ||
|  | #define PlIdContW(c)    CharTypeW(c, >= UC, U_ID_CONTINUE)
 | ||
|  | #define PlSymbolW(c)    CharTypeW(c, == SY, U_SYMBOL)
 | ||
|  | #define PlPunctW(c)     CharTypeW(c, == PU, 0)
 | ||
|  | #define PlSoloW(c)      CharTypeW(c, == SO, U_OTHER)
 | ||
|  | #define PlInvalidW(c)   (uflagsW(c) == 0)
 | ||
|  | 
 | ||
|  | int | ||
|  | f_is_prolog_var_start(wint_t c) | ||
|  | { return PlIdStartW(c) && (PlUpperW(c) || c == '_'); | ||
|  | } | ||
|  | 
 | ||
|  | int | ||
|  | f_is_prolog_atom_start(wint_t c) | ||
|  | { return PlIdStartW(c) != 0; | ||
|  | } | ||
|  | 
 | ||
|  | int | ||
|  | f_is_prolog_identifier_continue(wint_t c) | ||
|  | { return PlIdContW(c) || c == '_'; | ||
|  | } | ||
|  | 
 | ||
|  | int | ||
|  | f_is_prolog_symbol(wint_t c) | ||
|  | { return PlSymbolW(c) != 0; | ||
|  | } | ||
|  | 
 | ||
|  | int | ||
|  | unicode_separator(pl_wchar_t c) | ||
|  | { return PlBlankW(c); | ||
|  | } | ||
|  | 
 | ||
|  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | ||
|  |    FALSE	return false | ||
|  |    TRUE	redo | ||
|  |    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
|  | 
 | ||
|  | static int | ||
|  | reportReadError(ReadData rd) | ||
|  | { if ( rd->on_error == ATOM_error ) | ||
|  |     return PL_raise_exception(rd->exception); | ||
|  |   if ( rd->on_error != ATOM_quiet ) | ||
|  |     printMessage(ATOM_error, PL_TERM, rd->exception); | ||
|  |   PL_clear_exception(); | ||
|  | 
 | ||
|  |   if ( rd->on_error == ATOM_dec10 ) | ||
|  |     return TRUE; | ||
|  | 
 | ||
|  |   return FALSE; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /* static int */ | ||
|  | /* reportSingletons(ReadData rd, singletons, Atom amod, Atom aname, UInt arity) */ | ||
|  | /* {  */ | ||
|  | /*   printMessage(ATOM_warning, PL_FUNCTOR_CHARS,  */ | ||
|  | /* 	       "singletons", 2, */ | ||
|  | /* 	       PL_TERM, singletons,  */ | ||
|  | /* 	       PL_TERM, mod, */ | ||
|  | /* 	       PL_FUNCTOR_divide2, */ | ||
|  | /* 	       PL_ATOM, name, */ | ||
|  | /* 	       PL_INT, arity); */ | ||
|  | 
 | ||
|  | /*   return FALSE; */ | ||
|  | /* } */ | ||
|  | 
 | ||
|  | 
 | ||
|  | /********************************
 | ||
|  |  *           RAW READING         * | ||
|  |  *********************************/ | ||
|  | 
 | ||
|  | 
 | ||
|  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | ||
|  |    Scan the input, give prompts when necessary and return a char *  holding | ||
|  |    a  stripped  version of the next term.  Contiguous white space is mapped | ||
|  |    on a single space, block and % ... \n comment  is  deleted.   Memory  is | ||
|  |    claimed automatically en enlarged if necessary. | ||
|  | 
 | ||
|  |    (char *) NULL is returned on a syntax error. | ||
|  |    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
|  | 
 | ||
|  | #define syntaxError(what, rd) { errorWarning(what, 0, rd); fail; }
 | ||
|  | 
 | ||
|  | static term_t | ||
|  | makeErrorTerm(const char *id_str, term_t id_term, ReadData _PL_rd) | ||
|  | { GET_LD | ||
|  |     term_t ex, loc=0;			/* keep compiler happy */ | ||
|  |   unsigned char const *s, *ll = NULL; | ||
|  |   int rc = TRUE; | ||
|  | 
 | ||
|  |   if ( !(ex = PL_new_term_ref()) || | ||
|  |        !(loc = PL_new_term_ref()) ) | ||
|  |     rc = FALSE; | ||
|  | 
 | ||
|  |   if ( rc && !id_term ) | ||
|  |     { if ( !(id_term=PL_new_term_ref()) || | ||
|  | 	   !PL_put_atom_chars(id_term, id_str) ) | ||
|  | 	rc = FALSE; | ||
|  |     } | ||
|  | 
 | ||
|  |   if ( rc ) | ||
|  |     rc = PL_unify_term(ex, | ||
|  | 		       PL_FUNCTOR, FUNCTOR_error2, | ||
|  | 		       PL_FUNCTOR, FUNCTOR_syntax_error1, | ||
|  | 		       PL_TERM, id_term, | ||
|  | 		       PL_TERM, loc); | ||
|  | 
 | ||
|  |   source_char_no += last_token_start - rdbase; | ||
|  |   for(s=rdbase; s<last_token_start; s++) | ||
|  |     { if ( *s == '\n' ) | ||
|  | 	{ source_line_no++; | ||
|  | 	  ll = s+1; | ||
|  | 	} | ||
|  |     } | ||
|  | 
 | ||
|  |   if ( ll ) | ||
|  |     { int lp = 0; | ||
|  | 
 | ||
|  |       for(s = ll; s<last_token_start; s++) | ||
|  | 	{ switch(*s) | ||
|  | 	    { case '\b': | ||
|  | 		if ( lp > 0 ) lp--; | ||
|  | 		break; | ||
|  | 	    case '\t': | ||
|  | 	      lp |= 7; | ||
|  | 	    default: | ||
|  | 	      lp++; | ||
|  | 	    } | ||
|  | 	} | ||
|  | 
 | ||
|  |       source_line_pos = lp; | ||
|  |     } | ||
|  | 
 | ||
|  |   if ( rc ) | ||
|  |     { if ( ReadingSource )			/* reading a file */ | ||
|  | 	{ rc = PL_unify_term(loc, | ||
|  | 			     PL_FUNCTOR, FUNCTOR_file4, | ||
|  | 			     PL_ATOM, source_file_name, | ||
|  | 			     PL_INT, source_line_no, | ||
|  | 			     PL_INT, source_line_pos, | ||
|  | 			     PL_INT64, source_char_no); | ||
|  | 	} else if ( isStringStream(rb.stream) ) | ||
|  | 	{ size_t pos; | ||
|  | 
 | ||
|  | 	  pos = utf8_strlen((char *)rdbase, last_token_start-rdbase); | ||
|  | 
 | ||
|  | 	  rc = PL_unify_term(loc, | ||
|  | 			     PL_FUNCTOR, FUNCTOR_string2, | ||
|  | 			     PL_UTF8_STRING, rdbase, | ||
|  | 			     PL_INT, (int)pos); | ||
|  | 	} else				/* any stream */ | ||
|  | 	{ term_t stream; | ||
|  | 
 | ||
|  | 	  if ( !(stream=PL_new_term_ref()) || | ||
|  | 	       !PL_unify_stream_or_alias(stream, rb.stream) || | ||
|  | 	       !PL_unify_term(loc, | ||
|  | 			      PL_FUNCTOR, FUNCTOR_stream4, | ||
|  | 			      PL_TERM, stream, | ||
|  | 			      PL_INT, source_line_no, | ||
|  | 			      PL_INT, source_line_pos, | ||
|  | 			      PL_INT64, source_char_no) ) | ||
|  | 	    rc = FALSE; | ||
|  | 	} | ||
|  |     } | ||
|  | 
 | ||
|  |   return (rc ? ex : (term_t)0); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | static bool | ||
|  | errorWarning(const char *id_str, term_t id_term, ReadData _PL_rd) | ||
|  | { GET_LD | ||
|  |     term_t ex; | ||
|  | 
 | ||
|  |   LD->exception.processing = TRUE;	/* allow using spare stack */ | ||
|  | 
 | ||
|  |   ex = makeErrorTerm(id_str, id_term, _PL_rd); | ||
|  | 
 | ||
|  |   if ( _PL_rd ) | ||
|  |     { _PL_rd->has_exception = TRUE; | ||
|  |       if ( ex ) | ||
|  | 	PL_put_term(_PL_rd->exception, ex); | ||
|  |       else | ||
|  | 	PL_put_term(_PL_rd->exception, exception_term); | ||
|  |     } else | ||
|  |     { if ( ex ) | ||
|  | 	PL_raise_exception(ex); | ||
|  |     } | ||
|  | 
 | ||
|  |   fail; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | static void | ||
|  | clearBuffer(ReadData _PL_rd) | ||
|  | { if (rb.size == 0) | ||
|  |     { rb.base = rb.fast; | ||
|  |       rb.size = sizeof(rb.fast); | ||
|  |     } | ||
|  |   rb.end = rb.base + rb.size; | ||
|  |   rdbase = rb.here = rb.base; | ||
|  | 
 | ||
|  |   _PL_rd->posp = rdbase; | ||
|  |   _PL_rd->posi = 0; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static void | ||
|  | growToBuffer(int c, ReadData _PL_rd) | ||
|  | { if ( rb.base == rb.fast )		/* intptr_t clause: jump to use malloc() */ | ||
|  |     { rb.base = PL_malloc(FASTBUFFERSIZE * 2); | ||
|  |       memcpy(rb.base, rb.fast, FASTBUFFERSIZE); | ||
|  |     } else | ||
|  |     rb.base = PL_realloc(rb.base, rb.size*2); | ||
|  | 
 | ||
|  |   DEBUG(8, Sdprintf("Reallocated read buffer at %ld\n", (intptr_t) rb.base)); | ||
|  |   _PL_rd->posp = rdbase = rb.base; | ||
|  |   rb.here = rb.base + rb.size; | ||
|  |   rb.size *= 2; | ||
|  |   rb.end  = rb.base + rb.size; | ||
|  |   _PL_rd->posi = 0; | ||
|  | 
 | ||
|  |   *rb.here++ = c; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static inline void | ||
|  | addByteToBuffer(int c, ReadData _PL_rd) | ||
|  | { c &= 0xff; | ||
|  | 
 | ||
|  |   if ( rb.here >= rb.end ) | ||
|  |     growToBuffer(c, _PL_rd); | ||
|  |   else | ||
|  |     *rb.here++ = c; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static void | ||
|  | addToBuffer(int c, ReadData _PL_rd) | ||
|  | { if ( c <= 0x7f ) | ||
|  |     { addByteToBuffer(c, _PL_rd); | ||
|  |     } else | ||
|  |     { char buf[10]; | ||
|  |       char *s, *e; | ||
|  | 
 | ||
|  |       e = utf8_put_char(buf, c); | ||
|  |       for(s=buf; s<e; s++) | ||
|  | 	addByteToBuffer(*s, _PL_rd); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #if __YAP_PROLOG__
 | ||
|  | void | ||
|  | Yap_setCurrentSourceLocation( void *rd ) | ||
|  | { | ||
|  |   GET_LD | ||
|  |     setCurrentSourceLocation(rd PASS_LD); | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 
 | ||
|  | static inline int | ||
|  | getchr__(ReadData _PL_rd) | ||
|  | { int c = Sgetcode(rb.stream); | ||
|  | 
 | ||
|  |   if ( !_PL_rd->char_conversion_table || c < 0 || c >= 256 ) | ||
|  |     return c; | ||
|  | 
 | ||
|  |   return _PL_rd->char_conversion_table[c]; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | #define getchr()  getchr__(_PL_rd)
 | ||
|  | #define getchrq() Sgetcode(rb.stream)
 | ||
|  | 
 | ||
|  | #define ensure_space(c) { if ( something_read &&			\
 | ||
|  | 			       (c == '\n' || !isBlank(rb.here[-1])) )	\ | ||
|  |       addToBuffer(c, _PL_rd);						\ | ||
|  |   } | ||
|  | #define set_start_line { if ( !something_read )		\
 | ||
|  |       { setCurrentSourceLocation(_PL_rd PASS_LD);	\ | ||
|  | 	something_read++;				\ | ||
|  |       }							\ | ||
|  |   } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifdef O_QUASIQUOTATIONS
 | ||
|  | /** '$qq_open'(+QQRange, -Stream) is det.
 | ||
|  | 
 | ||
|  |     Opens a quasi-quoted memory range. | ||
|  | 
 | ||
|  |     @arg QQRange is a term '$quasi_quotation'(ReadData, Start, Length) | ||
|  |     @arg Stream  is a UTF-8 encoded string, whose position indication | ||
|  |     reflects the location in the real file. | ||
|  | */ | ||
|  | 
 | ||
|  | static | ||
|  | PRED_IMPL("$qq_open", 2, qq_open, 0) | ||
|  | { PRED_LD | ||
|  | 
 | ||
|  |     if ( PL_is_functor(A1, FUNCTOR_dquasi_quotation3) ) | ||
|  |       { void *ptr; | ||
|  | 	char * start; | ||
|  | 	size_t len; | ||
|  | 	term_t arg = PL_new_term_ref(); | ||
|  | 	IOSTREAM *s; | ||
|  | 
 | ||
|  | 	if ( PL_get_arg(1, A1, arg) && PL_get_pointer_ex(arg, &ptr) && | ||
|  | 	     PL_get_arg(2, A1, arg) && PL_get_intptr(arg, (intptr_t *)&start) && | ||
|  | 	     PL_get_arg(3, A1, arg) && PL_get_intptr(arg, (intptr_t *)&len) ) | ||
|  | 	  {  //source_location pos;
 | ||
|  | 	    if ( (s=Sopenmem(&start, &len, "r")) ) | ||
|  | 	      s->encoding = ENC_UTF8; | ||
|  | 
 | ||
|  | 	    return PL_unify_stream(A2, s); | ||
|  | 	  } | ||
|  |       } else | ||
|  |       PL_type_error("read_context", A1); | ||
|  | 
 | ||
|  |   return FALSE; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static int | ||
|  | parse_quasi_quotations(ReadData _PL_rd ARG_LD) | ||
|  | { if ( _PL_rd->qq_tail ) | ||
|  |     { term_t av; | ||
|  |       int rc; | ||
|  | 
 | ||
|  |       if ( !PL_unify_nil(_PL_rd->qq_tail) ) | ||
|  | 	return FALSE; | ||
|  | 
 | ||
|  |       if ( !_PL_rd->quasi_quotations ) | ||
|  | 	{ if ( (av = PL_new_term_refs(2)) && | ||
|  | 	       PL_put_term(av+0, _PL_rd->qq) && | ||
|  | #if __YAP_PROLOG__
 | ||
|  | 	       PL_put_atom(av+1, YAP_SWIAtomFromAtom(_PL_rd->module->AtomOfME)) && | ||
|  | #else
 | ||
|  | 	       PL_put_atom(av+1, _PL_rd->module->name) && | ||
|  | #endif
 | ||
|  | 	       PL_cons_functor_v(av, FUNCTOR_dparse_quasi_quotations2, av) ) | ||
|  | 	    { term_t ex; | ||
|  | 	      rc = callProlog(MODULE_system, av+0, PL_Q_CATCH_EXCEPTION, &ex); | ||
|  | 	      if ( rc ) | ||
|  | 		return TRUE; | ||
|  | 	      _PL_rd->exception = ex; | ||
|  | 	      _PL_rd->has_exception = TRUE; | ||
|  | 	    } | ||
|  | 	  return FALSE; | ||
|  | 	} else | ||
|  | 	return TRUE; | ||
|  |     } else if ( _PL_rd->quasi_quotations )	/* user option, but no quotes */ | ||
|  |     { return PL_unify_nil(_PL_rd->quasi_quotations); | ||
|  |     } else | ||
|  |     return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | #endif /*O_QUASIQUOTATIONS*/
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #define rawSyntaxError(what) { addToBuffer(EOS, _PL_rd);	\
 | ||
|  |     rdbase = rb.base, last_token_start = rb.here-1;		\ | ||
|  |     syntaxError(what, _PL_rd);					\ | ||
|  |   } | ||
|  | 
 | ||
|  | static int | ||
|  | raw_read_quoted(int q, ReadData _PL_rd) | ||
|  | { int newlines = 0; | ||
|  |   int c; | ||
|  | 
 | ||
|  |   addToBuffer(q, _PL_rd); | ||
|  |   while((c=getchrq()) != EOF && c != q) | ||
|  |     { if ( c == '\\' && DO_CHARESCAPE ) | ||
|  | 	{ int base; | ||
|  | 	  addToBuffer(c, _PL_rd); | ||
|  | 
 | ||
|  | 	  switch( (c=getchrq()) ) | ||
|  | 	    { case EOF: | ||
|  | 		goto eofinstr; | ||
|  | 	    case 'u':			/* \uXXXX */ | ||
|  | 	    case 'U':			/* \UXXXXXXXX */ | ||
|  | 	      addToBuffer(c, _PL_rd); | ||
|  | 	      continue; | ||
|  | 	    case 'x':			/* \xNN\ */ | ||
|  | 	      addToBuffer(c, _PL_rd); | ||
|  | 	      c = getchrq(); | ||
|  | 	      if ( c == EOF ) | ||
|  | 		goto eofinstr; | ||
|  | 	      if ( digitValue(16, c) >= 0 ) | ||
|  | 		{ base = 16; | ||
|  | 		  addToBuffer(c, _PL_rd); | ||
|  | 
 | ||
|  | 		xdigits: | ||
|  | 		  c = getchrq(); | ||
|  | 		  while( digitValue(base, c) >= 0 ) | ||
|  | 		    { addToBuffer(c, _PL_rd); | ||
|  | 		      c = getchrq(); | ||
|  | 		    } | ||
|  | 		} | ||
|  | 	      if ( c == EOF ) | ||
|  | 		goto eofinstr; | ||
|  | 	      addToBuffer(c, _PL_rd); | ||
|  | 	      if ( c == q ) | ||
|  | 		return TRUE; | ||
|  | 	      continue; | ||
|  | 	    default: | ||
|  | 	      addToBuffer(c, _PL_rd); | ||
|  | 	      if ( digitValue(8, c) >= 0 )	/* \NNN\ */ | ||
|  | 		{ base = 8; | ||
|  | 		  goto xdigits; | ||
|  | 		} else if ( c == '\n' )	/* \<newline> */ | ||
|  | 		{ c = getchrq(); | ||
|  | 		  if ( c == EOF ) | ||
|  | 		    goto eofinstr; | ||
|  | 		  addToBuffer(c, _PL_rd); | ||
|  | 		  if ( c == q ) | ||
|  | 		    return TRUE; | ||
|  | 		} | ||
|  | 	      continue;			/* \symbolic-control-char */ | ||
|  | 	    } | ||
|  | 	} else if (c == '\n' && | ||
|  | 		   newlines++ > MAXNEWLINES && | ||
|  | 		   (_PL_rd->styleCheck & LONGATOM_CHECK)) | ||
|  | 	{ rawSyntaxError("long_string"); | ||
|  | 	} | ||
|  |       addToBuffer(c, _PL_rd); | ||
|  |     } | ||
|  |   if (c == EOF) | ||
|  |     { eofinstr: | ||
|  |       rawSyntaxError("end_of_file_in_string"); | ||
|  |     } | ||
|  |   addToBuffer(c, _PL_rd); | ||
|  | 
 | ||
|  |   return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static int | ||
|  | add_comment(Buffer b, IOPOS *pos, ReadData _PL_rd ARG_LD) | ||
|  | { term_t head = PL_new_term_ref(); | ||
|  | 
 | ||
|  |   assert(_PL_rd->comments); | ||
|  |   if ( !PL_unify_list(_PL_rd->comments, head, _PL_rd->comments) ) | ||
|  |     return FALSE; | ||
|  |   if ( pos ) | ||
|  |     { if ( !PL_unify_term(head, | ||
|  | 			  PL_FUNCTOR, FUNCTOR_minus2, | ||
|  | 			  PL_FUNCTOR, FUNCTOR_stream_position4, | ||
|  | 			  PL_INT64, pos->charno, | ||
|  | 			  PL_INT, pos->lineno, | ||
|  | 			  PL_INT, pos->linepos, | ||
|  | 			  PL_INT, 0, | ||
|  | 			  PL_UTF8_STRING, baseBuffer(b, char)) ) | ||
|  | 	return FALSE; | ||
|  |     } else | ||
|  |     { if ( !PL_unify_term(head, | ||
|  | 			  PL_FUNCTOR, FUNCTOR_minus2, | ||
|  | 			  ATOM_minus, | ||
|  | 			  PL_UTF8_STRING, baseBuffer(b, char)) ) | ||
|  | 	return FALSE; | ||
|  |     } | ||
|  | 
 | ||
|  |   PL_reset_term_refs(head); | ||
|  |   return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static void | ||
|  | setErrorLocation(IOPOS *pos, ReadData _PL_rd) | ||
|  | { if ( pos ) | ||
|  |     { GET_LD | ||
|  | 
 | ||
|  | 	source_char_no = pos->charno; | ||
|  |       source_line_pos = pos->linepos; | ||
|  |       source_line_no = pos->lineno; | ||
|  |     } | ||
|  |   rb.here = rb.base+1;			/* see rawSyntaxError() */ | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static unsigned char * | ||
|  | raw_read2(ReadData _PL_rd ARG_LD) | ||
|  | { int c; | ||
|  |   bool something_read = FALSE; | ||
|  |   bool dotseen = FALSE; | ||
|  |   IOPOS pbuf;					/* comment start */ | ||
|  |   IOPOS *pos; | ||
|  | 
 | ||
|  |   clearBuffer(_PL_rd);				/* clear input buffer */ | ||
|  |   _PL_rd->strictness = truePrologFlag(PLFLAG_ISO); | ||
|  |   source_line_no = -1; | ||
|  | 
 | ||
|  |   for(;;) | ||
|  |     { c = getchr(); | ||
|  | 
 | ||
|  |     handle_c: | ||
|  |       switch(c) | ||
|  | 	{ case EOF: | ||
|  | 	    if ( isStringStream(rb.stream) ) /* do not require '. ' when */ | ||
|  | 	      { addToBuffer(' ', _PL_rd);     /* reading from a string */ | ||
|  | 		addToBuffer('.', _PL_rd); | ||
|  | 		addToBuffer(' ', _PL_rd); | ||
|  | 		addToBuffer(EOS, _PL_rd); | ||
|  | 		return rb.base; | ||
|  | 	      } | ||
|  | 	    if (something_read) | ||
|  | 	      { if ( dotseen )		/* term.<EOF> */ | ||
|  | 		  { if ( rb.here - rb.base == 1 ) | ||
|  | 		      rawSyntaxError("end_of_clause"); | ||
|  | 		    ensure_space(' '); | ||
|  | 		    addToBuffer(EOS, _PL_rd); | ||
|  | 		    return rb.base; | ||
|  | 		  } | ||
|  | 		rawSyntaxError("end_of_file"); | ||
|  | 	      } | ||
|  | 	    if ( Sfpasteof(rb.stream) ) | ||
|  | 	      { term_t stream; | ||
|  | 
 | ||
|  | 		LD->exception.processing = TRUE; | ||
|  | 		stream = PL_new_term_ref(); | ||
|  | 		PL_unify_stream_or_alias(stream, rb.stream); | ||
|  | 		PL_error(NULL, 0, NULL, ERR_PERMISSION, | ||
|  | 			 ATOM_input, ATOM_past_end_of_stream, stream); | ||
|  | 		return NULL; | ||
|  | 	      } | ||
|  | 	    set_start_line; | ||
|  | 	    strcpy((char *)rb.base, "end_of_file. "); | ||
|  | 	    rb.here = rb.base + 14; | ||
|  | 	    return rb.base; | ||
|  | 	case '/': if ( rb.stream->position ) | ||
|  | 	      { pbuf = *rb.stream->position; | ||
|  | 		pbuf.charno--; | ||
|  | 		pbuf.linepos--; | ||
|  | 		pos = &pbuf; | ||
|  | 	      } else | ||
|  | 	      pos = NULL; | ||
|  | 
 | ||
|  | 	  c = getchr(); | ||
|  | 	  if ( c == '*' ) | ||
|  | 	    { int last; | ||
|  | 	      int level = 1; | ||
|  | 	      union { | ||
|  | 		tmp_buffer ctmpbuf; | ||
|  | 		buffer tmpbuf; | ||
|  | 	      } u; | ||
|  | 	      Buffer cbuf; | ||
|  | 
 | ||
|  | 	      if ( _PL_rd->comments ) | ||
|  | 		{ initBuffer(&u.ctmpbuf); | ||
|  | 		  cbuf = &u.tmpbuf; | ||
|  | 		  addUTF8Buffer(cbuf, '/'); | ||
|  | 		  addUTF8Buffer(cbuf, '*'); | ||
|  | 		} else | ||
|  | 		{ cbuf = NULL; | ||
|  | 		} | ||
|  | 
 | ||
|  | 	      if ((last = getchr()) == EOF) | ||
|  | 		{ if ( cbuf ) | ||
|  | 		    discardBuffer(cbuf); | ||
|  | 		  setErrorLocation(pos, _PL_rd); | ||
|  | 		  rawSyntaxError("end_of_file_in_block_comment"); | ||
|  | 		} | ||
|  | 	      if ( cbuf ) | ||
|  | 		addUTF8Buffer(cbuf, last); | ||
|  | 
 | ||
|  | 	      if ( something_read ) | ||
|  | 		{ addToBuffer(' ', _PL_rd);	/* positions */ | ||
|  | 		  addToBuffer(' ', _PL_rd); | ||
|  | 		  addToBuffer(last == '\n' ? last : ' ', _PL_rd); | ||
|  | 		} | ||
|  | 
 | ||
|  | 	      for(;;) | ||
|  | 		{ c = getchr(); | ||
|  | 
 | ||
|  | 		  if ( cbuf ) | ||
|  | 		    addUTF8Buffer(cbuf, c); | ||
|  | 
 | ||
|  | 		  switch( c ) | ||
|  | 		    { case EOF: | ||
|  | 			if ( cbuf ) | ||
|  | 			  discardBuffer(cbuf); | ||
|  | 			setErrorLocation(pos, _PL_rd); | ||
|  | 			rawSyntaxError("end_of_file_in_block_comment"); | ||
|  | #ifndef __YAP_PROLOG__
 | ||
|  | 			/* YAP does not support comment levels in original scanner */ | ||
|  | 		    case '*': | ||
|  | 		      if ( last == '/' ) | ||
|  | 			level++; | ||
|  | 		      break; | ||
|  | #endif
 | ||
|  | 		    case '/': | ||
|  | 		      if ( last == '*' && | ||
|  | 			   (--level == 0 || _PL_rd->strictness) ) | ||
|  | 			{ if ( cbuf ) | ||
|  | 			    { addUTF8Buffer(cbuf, EOS); | ||
|  | 			      if ( !add_comment(cbuf, pos, _PL_rd PASS_LD) ) | ||
|  | 				{ discardBuffer(cbuf); | ||
|  | 				  return FALSE; | ||
|  | 				} | ||
|  | 			      discardBuffer(cbuf); | ||
|  | 			    } | ||
|  | 			  c = ' '; | ||
|  | 			  goto handle_c; | ||
|  | 			} | ||
|  | 		      break; | ||
|  | 		    } | ||
|  | 		  if ( something_read ) | ||
|  | 		    addToBuffer(c == '\n' ? c : ' ', _PL_rd); | ||
|  | 		  last = c; | ||
|  | 		} | ||
|  | 	    } else | ||
|  | 	    { set_start_line; | ||
|  | 	      addToBuffer('/', _PL_rd); | ||
|  | 	      if ( isSymbolW(c) ) | ||
|  | 		{ while( c != EOF && isSymbolW(c) && | ||
|  | 			 !(c == '`' && _PL_rd->backquoted_string) ) | ||
|  | 		    { addToBuffer(c, _PL_rd); | ||
|  | 		      c = getchr(); | ||
|  | 		    } | ||
|  | 		} | ||
|  | 	      dotseen = FALSE; | ||
|  | 	      goto handle_c; | ||
|  | 	    } | ||
|  | 	case '%': if ( something_read ) | ||
|  | 	    addToBuffer(' ', _PL_rd); | ||
|  | 	  if ( _PL_rd->comments ) | ||
|  | 	    { union { | ||
|  | 	      tmp_buffer ctmpbuf; | ||
|  | 	      buffer uctmpbuf; | ||
|  | 	    } u; | ||
|  | 	      Buffer cbuf; | ||
|  | 
 | ||
|  | 	      if ( rb.stream->position ) | ||
|  | 		{ pbuf = *rb.stream->position; | ||
|  | 		  pbuf.charno--; | ||
|  | 		  pbuf.linepos--; | ||
|  | 		  pos = &pbuf; | ||
|  | 		} else | ||
|  | 		pos = NULL; | ||
|  | 
 | ||
|  | 	      initBuffer(&u.ctmpbuf); | ||
|  | 	      cbuf = (Buffer)&u.uctmpbuf; | ||
|  | 	      addUTF8Buffer(cbuf, '%'); | ||
|  | 
 | ||
|  | 	      for(;;) | ||
|  | 		{ while((c=getchr()) != EOF && c != '\n') | ||
|  | 		    { addUTF8Buffer(cbuf, c); | ||
|  | 		      if ( something_read )		/* record positions */ | ||
|  | 			addToBuffer(' ', _PL_rd); | ||
|  | 		    } | ||
|  | 		  if ( c == '\n' ) | ||
|  | 		    { int c2 = Speekcode(rb.stream); | ||
|  | 
 | ||
|  | 		      if ( c2 == '%' ) | ||
|  | 			{ if ( something_read ) | ||
|  | 			    { addToBuffer(c, _PL_rd); | ||
|  | 			      addToBuffer(' ', _PL_rd); | ||
|  | 			    } | ||
|  | 			  addUTF8Buffer(cbuf, c); | ||
|  | 			  c = Sgetcode(rb.stream); | ||
|  | 			  assert(c==c2); | ||
|  | 			  addUTF8Buffer(cbuf, c); | ||
|  | 			  continue; | ||
|  | 			} | ||
|  | 		    } | ||
|  | 		  break; | ||
|  | 		} | ||
|  | 	      addUTF8Buffer(cbuf, EOS); | ||
|  | 	      if ( !add_comment(cbuf, pos, _PL_rd PASS_LD) ) | ||
|  | 		{ discardBuffer(cbuf); | ||
|  | 		  return FALSE; | ||
|  | 		} | ||
|  | 	      discardBuffer(cbuf); | ||
|  | 	    } else | ||
|  | 	    { while((c=getchr()) != EOF && c != '\n') | ||
|  | 		{ if ( something_read )		/* record positions */ | ||
|  | 		    addToBuffer(' ', _PL_rd); | ||
|  | 		} | ||
|  | 	    } | ||
|  | 	  goto handle_c;		/* is the newline */ | ||
|  | 	case '\'': if ( rb.here > rb.base && isDigit(rb.here[-1]) ) | ||
|  | 	    { cucharp bs = &rb.here[-1]; | ||
|  | 
 | ||
|  | 	      if ( bs > rb.base && isDigit(bs[-1]) ) | ||
|  | 		bs--; | ||
|  | 	      if ( bs > rb.base && isSign(bs[-1]) ) | ||
|  | 		bs--; | ||
|  | 
 | ||
|  | 	      if ( bs == rb.base || !PlIdContW(bs[-1]) ) | ||
|  | 		{ int base; | ||
|  | 
 | ||
|  | 		  if ( isSign(bs[0]) ) | ||
|  | 		    bs++; | ||
|  | 		  base = atoi((char*)bs); | ||
|  | 
 | ||
|  | 		  if ( base <= 36 ) | ||
|  | 		    { if ( base == 0 )			/* 0'<c> */ | ||
|  | 			{ addToBuffer(c, _PL_rd); | ||
|  | 			  { if ( (c=getchr()) != EOF ) | ||
|  | 			      { addToBuffer(c, _PL_rd); | ||
|  | 				if ( c == '\\' ) 		/* 0'\<c> */ | ||
|  | 				  { if ( (c=getchr()) != EOF ) | ||
|  | 				      addToBuffer(c, _PL_rd); | ||
|  | 				  } else if ( c == '\'' ) 	/* 0'' */ | ||
|  | 				  { if ( (c=getchr()) != EOF ) | ||
|  | 				      { if ( c == '\'' ) | ||
|  | 					  addToBuffer(c, _PL_rd); | ||
|  | 					else | ||
|  | 					  goto handle_c; | ||
|  | 				      } | ||
|  | 				  } | ||
|  | 				break; | ||
|  | 			      } | ||
|  | 			    rawSyntaxError("end_of_file"); | ||
|  | 			  } | ||
|  | 			} else | ||
|  | 			{ int c2 = Speekcode(rb.stream); | ||
|  | 
 | ||
|  | 			  if ( c2 != EOF ) | ||
|  | 			    { if ( digitValue(base, c2) >= 0 ) | ||
|  | 				{ addToBuffer(c, _PL_rd); | ||
|  | 				  c = Sgetcode(rb.stream); | ||
|  | 				  addToBuffer(c, _PL_rd); | ||
|  | 				  dotseen = FALSE; | ||
|  | 				  break; | ||
|  | 				} | ||
|  | 			      goto sqatom; | ||
|  | 			    } | ||
|  | 			  rawSyntaxError("end_of_file"); | ||
|  | 			} | ||
|  | 		    } | ||
|  | 		} | ||
|  | 	    } | ||
|  | 
 | ||
|  | 	sqatom: | ||
|  | 	  set_start_line; | ||
|  | 	  if ( !raw_read_quoted(c, _PL_rd) ) | ||
|  | 	    fail; | ||
|  | 	  dotseen = FALSE; | ||
|  | 	  break; | ||
|  | 	case '"':	set_start_line; | ||
|  | 	  if ( !raw_read_quoted(c, _PL_rd) ) | ||
|  | 	    fail; | ||
|  | 	  dotseen = FALSE; | ||
|  | 	  break; | ||
|  | 	case '.': addToBuffer(c, _PL_rd); | ||
|  | 	  set_start_line; | ||
|  | 	  dotseen++; | ||
|  | 	  c = getchr(); | ||
|  | 	  if ( isSymbolW(c) ) | ||
|  | 	    { while( c != EOF && isSymbolW(c) && | ||
|  | 		     !(c == '`' && _PL_rd->backquoted_string) ) | ||
|  | 		{ addToBuffer(c, _PL_rd); | ||
|  | 		  c = getchr(); | ||
|  | 		} | ||
|  | 	      dotseen = FALSE; | ||
|  | 	    } | ||
|  | 	  goto handle_c; | ||
|  | 	case '`': if ( _PL_rd->backquoted_string ) | ||
|  | 	    { set_start_line; | ||
|  | 	      if ( !raw_read_quoted(c, _PL_rd) ) | ||
|  | 		fail; | ||
|  | 	      dotseen = FALSE; | ||
|  | 	      break; | ||
|  | 	    } | ||
|  | 	  /*FALLTHROUGH*/ | ||
|  | 	default:	if ( c < 0xff ) | ||
|  | 	    { switch(_PL_char_types[c]) | ||
|  | 		{ case SP: | ||
|  | 		case CT: | ||
|  | 		blank: | ||
|  | 		  if ( dotseen ) | ||
|  | 		    { if ( rb.here - rb.base == 1 ) | ||
|  | 			rawSyntaxError("end_of_clause"); | ||
|  | 		      ensure_space(c); | ||
|  | 		      addToBuffer(EOS, _PL_rd); | ||
|  | 		      return rb.base; | ||
|  | 		    } | ||
|  | 		  do | ||
|  | 		    { if ( something_read ) /* positions, \0 --> ' ' */ | ||
|  | 			addToBuffer(c ? c : ' ', _PL_rd); | ||
|  | 		      else | ||
|  | 			ensure_space(c); | ||
|  | 		      c = getchr(); | ||
|  | 		    } while( c != EOF && PlBlankW(c) ); | ||
|  | 		  goto handle_c; | ||
|  | 		case SY: | ||
|  | 		  set_start_line; | ||
|  | 		  do | ||
|  | 		    { addToBuffer(c, _PL_rd); | ||
|  | 		      c = getchr(); | ||
|  | 		      if ( c == '`' && _PL_rd->backquoted_string ) | ||
|  | 			break; | ||
|  | 		    } while( c != EOF && c <= 0xff && isSymbol(c) ); | ||
|  | 		  /* TBD: wide symbols? */ | ||
|  | 		  dotseen = FALSE; | ||
|  | 		  goto handle_c; | ||
|  | 		case LC: | ||
|  | 		case UC: | ||
|  | 		  set_start_line; | ||
|  | 		  do | ||
|  | 		    { addToBuffer(c, _PL_rd); | ||
|  | 		      c = getchr(); | ||
|  | 		    } while( c != EOF && PlIdContW(c) ); | ||
|  | 		  dotseen = FALSE; | ||
|  | 		  goto handle_c; | ||
|  | 		default: | ||
|  | 		  addToBuffer(c, _PL_rd); | ||
|  | 		  dotseen = FALSE; | ||
|  | 		  set_start_line; | ||
|  | 		} | ||
|  | 	    } else			/* > 255 */ | ||
|  | 	    { if ( PlIdStartW(c) ) | ||
|  | 		{ set_start_line; | ||
|  | 		  do | ||
|  | 		    { addToBuffer(c, _PL_rd); | ||
|  | 		      c = getchr(); | ||
|  | 		    } while( c != EOF && PlIdContW(c) ); | ||
|  | 		  dotseen = FALSE; | ||
|  | 		  goto handle_c; | ||
|  | 		} else if ( PlBlankW(c) ) | ||
|  | 		{ goto blank; | ||
|  | 		} else | ||
|  | 		{ addToBuffer(c, _PL_rd); | ||
|  | 		  dotseen = FALSE; | ||
|  | 		  set_start_line; | ||
|  | 		} | ||
|  | 	    } | ||
|  | 	} | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | ||
|  |    Raw reading returns a string in  UTF-8   notation  of the a Prolog term. | ||
|  |    Comment inside the term is  replaced  by   spaces  or  newline to ensure | ||
|  |    proper reconstruction of source locations. Comment   before  the term is | ||
|  |    skipped. | ||
|  |    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
|  | 
 | ||
|  | static unsigned char * | ||
|  | raw_read(ReadData _PL_rd, unsigned char **endp ARG_LD) | ||
|  | { unsigned char *s; | ||
|  | 
 | ||
|  |   if ( (rb.stream->flags & SIO_ISATTY) && Sfileno(rb.stream) >= 0 ) | ||
|  |     { ttybuf tab; | ||
|  | 
 | ||
|  |       PushTty(rb.stream, &tab, TTY_SAVE);		/* make sure tty is sane */ | ||
|  |       PopTty(rb.stream, &ttytab, FALSE); | ||
|  |       s = raw_read2(_PL_rd PASS_LD); | ||
|  |       PopTty(rb.stream, &tab, TRUE); | ||
|  |     } else | ||
|  |     { s = raw_read2(_PL_rd PASS_LD); | ||
|  |     } | ||
|  | 
 | ||
|  |   if ( endp ) | ||
|  |     *endp = _PL_rd->_rb.here; | ||
|  | 
 | ||
|  |   return s; | ||
|  | } | ||
|  | 
 | ||
|  | static void | ||
|  | callCommentHook(term_t comments, term_t tpos, term_t term) | ||
|  | { GET_LD | ||
|  |     fid_t fid; | ||
|  |   term_t av; | ||
|  | 
 | ||
|  |   if ( (fid = PL_open_foreign_frame()) && | ||
|  |        (av = PL_new_term_refs(3)) ) | ||
|  |     { qid_t qid; | ||
|  | 
 | ||
|  |       PL_put_term(av+0, comments); | ||
|  |       PL_put_term(av+1, tpos); | ||
|  |       PL_put_term(av+2, term); | ||
|  | 
 | ||
|  |       if ( (qid = PL_open_query(NULL, PL_Q_NODEBUG|PL_Q_CATCH_EXCEPTION, | ||
|  | 				(predicate_t)PredCommentHook, av)) ) | ||
|  | 	{ term_t ex; | ||
|  | 
 | ||
|  | 	  if ( !PL_next_solution(qid) && (ex=PL_exception(qid)) ) | ||
|  | 	    printMessage(ATOM_error, PL_TERM, ex); | ||
|  | 
 | ||
|  | 	  PL_close_query(qid); | ||
|  | 	} | ||
|  |       PL_discard_foreign_frame(fid); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /********************************
 | ||
|  |  *       PROLOG CONNECTION       * | ||
|  |  *********************************/ | ||
|  | 
 | ||
|  | static unsigned char * | ||
|  | backSkipUTF8(unsigned const char *start, unsigned const char *end, int *chr) | ||
|  | { const unsigned char *s; | ||
|  | 
 | ||
|  |   for(s=end-1 ; s>start && ( *s&0x80 ); s--) | ||
|  |     ; | ||
|  |   utf8_get_char((char*)s, chr); | ||
|  | 
 | ||
|  |   return (unsigned char *)s; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static unsigned char * | ||
|  | backSkipBlanks(const unsigned char *start, const unsigned char *end) | ||
|  | { const unsigned char *s; | ||
|  | 
 | ||
|  |   for( ; end > start; end = s) | ||
|  |     { unsigned char *e; | ||
|  |       int chr; | ||
|  | 
 | ||
|  |       for(s=end-1 ; s>start && ISUTF8_CB(*s); s--) | ||
|  | 	; | ||
|  |       e = (unsigned char*)utf8_get_char((char*)s, &chr); | ||
|  |       assert(e == end); | ||
|  |       if ( !PlBlankW(chr) ) | ||
|  | 	return (unsigned char*)end; | ||
|  |     } | ||
|  | 
 | ||
|  |   return (unsigned char *)start; | ||
|  | } | ||
|  | 
 | ||
|  | static inline ucharp | ||
|  | skipSpaces(cucharp in) | ||
|  | { int chr; | ||
|  |   ucharp s; | ||
|  | 
 | ||
|  |   for( ; *in; in=s) | ||
|  |     { s = utf8_get_uchar(in, &chr); | ||
|  | 
 | ||
|  |       if ( !PlBlankW(chr) ) | ||
|  | 	return (ucharp)in; | ||
|  |     } | ||
|  | 
 | ||
|  |   return (ucharp)in; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | word | ||
|  | pl_raw_read2(term_t from, term_t term) | ||
|  | { GET_LD | ||
|  |     unsigned char *s, *e, *t2, *top; | ||
|  |   read_data rd; | ||
|  |   word rval; | ||
|  |   IOSTREAM *in; | ||
|  |   int chr; | ||
|  |   PL_chars_t txt; | ||
|  | 
 | ||
|  |   if ( !getTextInputStream(from, &in) ) | ||
|  |     fail; | ||
|  | 
 | ||
|  |   init_read_data(&rd, in PASS_LD); | ||
|  |   if ( !(s = raw_read(&rd, &e PASS_LD)) ) | ||
|  |     { rval = PL_raise_exception(rd.exception); | ||
|  |       goto out; | ||
|  |     } | ||
|  | 
 | ||
|  |   /* strip the input from blanks */ | ||
|  |   top = backSkipBlanks(s, e-1); | ||
|  |   t2 = backSkipUTF8(s, top, &chr); | ||
|  |   if ( chr == '.' ) | ||
|  |     top = backSkipBlanks(s, t2); | ||
|  |   /* watch for "0' ." */ | ||
|  |   if ( top < e && top-2 >= s && top[-1] == '\'' && top[-2] == '0' ) | ||
|  |     top++; | ||
|  |   *top = EOS; | ||
|  |   s = skipSpaces(s); | ||
|  | 
 | ||
|  |   txt.text.t    = (char*)s; | ||
|  |   txt.length    = top-s; | ||
|  |   txt.storage   = PL_CHARS_HEAP; | ||
|  |   txt.encoding  = ENC_UTF8; | ||
|  |   txt.canonical = FALSE; | ||
|  | 
 | ||
|  |   rval = PL_unify_text(term, 0, &txt, PL_ATOM); | ||
|  |   LD->read_varnames = rd.varnames; | ||
|  | 
 | ||
|  |  out: | ||
|  |   free_read_data(&rd); | ||
|  |   if ( Sferror(in) ) | ||
|  |     return streamStatus(in); | ||
|  |   else | ||
|  |     PL_release_stream(in); | ||
|  | 
 | ||
|  |   return rval; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static int | ||
|  | unify_read_term_position(term_t tpos ARG_LD) | ||
|  | { if ( tpos && source_line_no > 0 ) | ||
|  |     { return PL_unify_term(tpos, | ||
|  | 			   PL_FUNCTOR, FUNCTOR_stream_position4, | ||
|  | 			   PL_INT64, source_char_no, | ||
|  | 			   PL_INT, source_line_no, | ||
|  | 			   PL_INT, source_line_pos, | ||
|  | 			   PL_INT64, source_byte_no); | ||
|  |     } else | ||
|  |     { return TRUE; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static const opt_spec read_clause_options[] = | ||
|  |   { { ATOM_variable_names,    OPT_TERM }, | ||
|  |     { ATOM_term_position,     OPT_TERM }, | ||
|  |     { ATOM_subterm_positions, OPT_TERM }, | ||
|  |     { ATOM_process_comment,   OPT_BOOL }, | ||
|  |     { ATOM_comments,          OPT_TERM }, | ||
|  |     { ATOM_syntax_errors,     OPT_ATOM }, | ||
|  |     { NULL_ATOM,              0 } | ||
|  |   }; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** read_clause(+Stream:stream, -Clause:clause, +Options:list)
 | ||
|  | 
 | ||
|  |     Like read_term/3, but uses current compiler options. | ||
|  | 
 | ||
|  |     Options: | ||
|  |     * variable_names(-Names) | ||
|  |     * process_comment(+Boolean) | ||
|  |     * comments(-List) | ||
|  |     * syntax_errors(+Atom) | ||
|  |     * term_position(-Position) | ||
|  |     * subterm_positions(-Layout) | ||
|  |     */ | ||
|  | static int | ||
|  | read_clause(IOSTREAM *s, term_t term, term_t options ARG_LD) | ||
|  | { | ||
|  |   read_data rd; | ||
|  |   int rval; | ||
|  |   fid_t fid; | ||
|  |   term_t tpos = 0; | ||
|  |   term_t comments = 0; | ||
|  |   term_t opt_comments = 0; | ||
|  |   int process_comment; | ||
|  |   atom_t syntax_errors = ATOM_dec10; | ||
|  | 
 | ||
|  |   { | ||
|  |     OPCODE ophook = PredCommentHook->OpcodeOfPred; | ||
|  |     if (ophook == UNDEF_OPCODE || ophook == FAIL_OPCODE) | ||
|  |       process_comment = FALSE; | ||
|  |     else | ||
|  |       process_comment = TRUE; | ||
|  |   } | ||
|  |   if ( !(fid=PL_open_foreign_frame()) ) | ||
|  |     return FALSE; | ||
|  | 
 | ||
|  |  retry: | ||
|  |   init_read_data(&rd, s PASS_LD); | ||
|  | 
 | ||
|  |   if ( options && | ||
|  |        !scan_options(options, 0, ATOM_read_option, read_clause_options, | ||
|  | 		     &rd.varnames, | ||
|  | 		     &tpos, | ||
|  | 		     &rd.subtpos, | ||
|  | 		     &process_comment, | ||
|  | 		     &opt_comments, | ||
|  | 		     &syntax_errors) ) | ||
|  |     { PL_close_foreign_frame(fid); | ||
|  |       return FALSE; | ||
|  |     } | ||
|  | 
 | ||
|  |   if ( opt_comments ) | ||
|  |     { comments = PL_new_term_ref(); | ||
|  |     } else if ( process_comment ) | ||
|  |     { if ( !tpos ) | ||
|  | 	tpos = PL_new_term_ref(); | ||
|  |       comments = PL_new_term_ref(); | ||
|  |     } | ||
|  | 
 | ||
|  |   REGS_FROM_LD | ||
|  |     rd.module = Yap_GetModuleEntry( LOCAL_SourceModule ); | ||
|  |   if ( comments ) | ||
|  |     rd.comments = PL_copy_term_ref(comments); | ||
|  |   rd.on_error = syntax_errors; | ||
|  |   rd.singles = rd.styleCheck & SINGLETON_CHECK ? 1 : 0; | ||
|  |   if ( (rval=read_term(term, &rd PASS_LD)) && | ||
|  |        (!tpos || (rval=unify_read_term_position(tpos PASS_LD))) ) | ||
|  |     { | ||
|  |       PredEntry *ap; | ||
|  |       LD->read_varnames = rd.varnames; | ||
|  | 
 | ||
|  |       if (rd.singles) { | ||
|  | 	// warning, singletons([X=_A],f(X,Y,Z), pos).
 | ||
|  | 	printMessage(ATOM_warning, | ||
|  | 		     PL_FUNCTOR_CHARS, "singletons", 3, | ||
|  | 		     PL_TERM, rd.singles, | ||
|  | 		     PL_TERM, term, | ||
|  | 		     PL_TERM, tpos ); | ||
|  |       } | ||
|  |       ap = Yap_PredFromClause( Yap_GetFromSlot(term)  PASS_REGS); | ||
|  |       if (rd.styleCheck & (DISCONTIGUOUS_STYLE|MULTIPLE_CHECK) && ap != NULL ) { | ||
|  | 	if ( rd.styleCheck & (DISCONTIGUOUS_STYLE) && Yap_discontiguous( ap  PASS_REGS) ) { | ||
|  | 	  printMessage(ATOM_warning, | ||
|  | 		       PL_FUNCTOR_CHARS, "discontiguous", 2, | ||
|  | 		       PL_TERM, term, | ||
|  | 		       PL_TERM, tpos ); | ||
|  | 	} | ||
|  | 	if (  rd.styleCheck & (MULTIPLE_CHECK) &&  Yap_multiple( ap  PASS_REGS) ) { | ||
|  | 	  printMessage(ATOM_warning, | ||
|  | 		       PL_FUNCTOR_CHARS, "multiple", 3, | ||
|  | 		       PL_TERM, term, | ||
|  | 		       PL_TERM, tpos, | ||
|  | 		       PL_ATOM, YAP_SWIAtomFromAtom(ap->src.OwnerFile) ); | ||
|  | 	} | ||
|  |       } | ||
|  |       if ( rd.comments && | ||
|  | 	   (rval = PL_unify_nil(rd.comments)) ) | ||
|  | 	{ if ( opt_comments ) | ||
|  | 	    rval = PL_unify(opt_comments, comments); | ||
|  | 	  else if ( !PL_get_nil(comments) ) | ||
|  | 	    callCommentHook(comments, tpos, term); | ||
|  | 	} | ||
|  |     } else | ||
|  |     { if ( rd.has_exception && reportReadError(&rd) ) | ||
|  | 	{ PL_rewind_foreign_frame(fid); | ||
|  | 	  free_read_data(&rd); | ||
|  | 	  goto retry; | ||
|  | 	} | ||
|  |     } | ||
|  |   free_read_data(&rd); | ||
|  | 
 | ||
|  |   return rval; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static | ||
|  | PRED_IMPL("read_clause", 3, read_clause, 0) | ||
|  | { PRED_LD | ||
|  |     int rc; | ||
|  |   IOSTREAM *s; | ||
|  | 
 | ||
|  |   if ( !getTextInputStream(A1, &s) ) | ||
|  |     return FALSE; | ||
|  |   rc = read_clause(s, A2, A3 PASS_LD); | ||
|  |   if ( Sferror(s) ) | ||
|  |     return streamStatus(s); | ||
|  |   else | ||
|  |     PL_release_stream(s); | ||
|  | 
 | ||
|  |   return rc; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | word | ||
|  | pl_raw_read(term_t term) | ||
|  | { return pl_raw_read2(0, term); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static const opt_spec read_term_options[] = | ||
|  |   { { ATOM_variable_names,    OPT_TERM }, | ||
|  |     { ATOM_variables,         OPT_TERM }, | ||
|  |     { ATOM_singletons,        OPT_TERM }, | ||
|  |     { ATOM_term_position,     OPT_TERM }, | ||
|  |     //  		{ ATOM_subterm_positions, OPT_TERM },
 | ||
|  |     { ATOM_character_escapes, OPT_BOOL }, | ||
|  |     { ATOM_double_quotes,	    OPT_ATOM }, | ||
|  |     { ATOM_module,	    OPT_ATOM }, | ||
|  |     { ATOM_syntax_errors,     OPT_ATOM }, | ||
|  |     { ATOM_backquoted_string, OPT_BOOL }, | ||
|  |     { ATOM_comments,	    OPT_TERM }, | ||
|  |     { ATOM_process_comment,   OPT_BOOL }, | ||
|  | #ifdef O_QUASIQUOTATIONS
 | ||
|  |     { ATOM_quasi_quotations,  OPT_TERM }, | ||
|  | #endif
 | ||
|  |     { ATOM_cycles,	    OPT_BOOL }, | ||
|  |     { NULL_ATOM,		    0 } | ||
|  |   }; | ||
|  | 
 | ||
|  | 
 | ||
|  | static foreign_t | ||
|  | read_term_from_stream(IOSTREAM *s, term_t term, term_t options ARG_LD) | ||
|  | { term_t tpos = 0; | ||
|  |   term_t comments = 0; | ||
|  |   term_t opt_comments = 0; | ||
|  |   int process_comment; | ||
|  |   int rval; | ||
|  |   atom_t w; | ||
|  |   read_data rd; | ||
|  |   int charescapes = -1; | ||
|  |   atom_t dq = NULL_ATOM; | ||
|  |   atom_t mname = NULL_ATOM; | ||
|  |   fid_t fid = PL_open_foreign_frame(); | ||
|  | 
 | ||
|  |   if (!fid) | ||
|  |     return FALSE; | ||
|  |  retry: | ||
|  |   init_read_data(&rd, s PASS_LD); | ||
|  | 
 | ||
|  |   if ( !scan_options(options, 0, ATOM_read_option, read_term_options, | ||
|  | 		     &rd.varnames, | ||
|  | 		     &rd.variables, | ||
|  | 		     &rd.singles, | ||
|  | 		     &tpos, | ||
|  | 		     //		&rd.subtpos,
 | ||
|  | 		     &charescapes, | ||
|  | 		     &dq, | ||
|  | 		     &mname, | ||
|  | 		     &rd.on_error, | ||
|  | 		     &rd.backquoted_string, | ||
|  | 		     &opt_comments, | ||
|  | 		     &process_comment, | ||
|  | #ifdef O_QUASIQUOTATIONS
 | ||
|  | 		     &rd.quasi_quotations, | ||
|  | #endif
 | ||
|  | 		     &rd.cycles) ) { | ||
|  |     PL_discard_foreign_frame(fid); | ||
|  |     free_read_data(&rd); | ||
|  |     return FALSE; | ||
|  |   } | ||
|  | 
 | ||
|  |   // yap specific, do not call process comment if undefined
 | ||
|  |   if (process_comment) { | ||
|  |     OPCODE ophook = PredCommentHook->OpcodeOfPred; | ||
|  |     if (ophook == UNDEF_OPCODE || ophook == FAIL_OPCODE) | ||
|  |       process_comment = FALSE; | ||
|  |   } | ||
|  | 
 | ||
|  |   if ( opt_comments ) | ||
|  |     { comments = PL_new_term_ref(); | ||
|  |     } else if ( process_comment ) | ||
|  |     { if ( !tpos ) | ||
|  | 	tpos = PL_new_term_ref(); | ||
|  |       comments = PL_new_term_ref(); | ||
|  |     } | ||
|  | 
 | ||
|  |   if ( mname ) | ||
|  |     { rd.module = lookupModule(mname); | ||
|  |       rd.flags  = rd.module->flags; | ||
|  |     } | ||
|  | 
 | ||
|  |   if ( charescapes != -1 ) | ||
|  |     { if ( charescapes ) | ||
|  | 	set(&rd, M_CHARESCAPE); | ||
|  |       else | ||
|  | 	clear(&rd, M_CHARESCAPE); | ||
|  |     } | ||
|  |   if ( dq ) | ||
|  |     { if ( !setDoubleQuotes(dq, &rd.flags) ) | ||
|  | 	return FALSE; | ||
|  |     } | ||
|  |   if ( rd.singles && PL_get_atom(rd.singles, &w) && w == ATOM_warning) | ||
|  |     rd.singles = 1; | ||
|  | 
 | ||
|  |   if ( comments ) | ||
|  |     rd.comments = PL_copy_term_ref(comments); | ||
|  | 
 | ||
|  |   rval = read_term(term, &rd PASS_LD); | ||
|  |   if ( Sferror(s) ) { | ||
|  |     free_read_data(&rd); | ||
|  |     return FALSE; | ||
|  |   } | ||
|  |   LD->read_varnames = rd.varnames; | ||
|  | #ifdef O_QUASIQUOTATIONS
 | ||
|  |   if ( rval ) | ||
|  |     rval = parse_quasi_quotations(&rd PASS_LD); | ||
|  | #endif
 | ||
|  |   if ( rval ) | ||
|  |     { if ( tpos ) | ||
|  | 	rval = unify_read_term_position(tpos PASS_LD); | ||
|  |       if (rval) { | ||
|  | 	if ( opt_comments ) | ||
|  | 	  rval = PL_unify(opt_comments, comments); | ||
|  | 	else if (comments && !PL_get_nil(comments) ) | ||
|  | 	  callCommentHook(comments, tpos, term); | ||
|  |       } | ||
|  |     } else { | ||
|  |     if ( rd.has_exception && reportReadError(&rd) ) | ||
|  |       { PL_rewind_foreign_frame(fid); | ||
|  | 	free_read_data(&rd); | ||
|  | 	goto retry; | ||
|  |       } | ||
|  |   } | ||
|  |   free_read_data(&rd); | ||
|  | 
 | ||
|  |   return rval; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /** @pred  read_term(+ _Stream_,- _T_,+ _Options_) is iso
 | ||
|  | 
 | ||
|  |     Reads term  _T_ from stream  _Stream_ with execution controlled by the | ||
|  |     same options as read_term/2. | ||
|  | 
 | ||
|  | 
 | ||
|  | */ | ||
|  | static | ||
|  | PRED_IMPL("read_term", 3, read_term, PL_FA_ISO) | ||
|  | { PRED_LD | ||
|  |     IOSTREAM *s; | ||
|  | 
 | ||
|  |   if ( getTextInputStream(A1, &s) ) | ||
|  |     { if ( read_term_from_stream(s, A2, A3 PASS_LD) ) | ||
|  | 	return PL_release_stream(s); | ||
|  |       if ( Sferror(s) ) | ||
|  | 	return streamStatus(s); | ||
|  |       PL_release_stream(s); | ||
|  |       return FALSE; | ||
|  |     } | ||
|  | 
 | ||
|  |   return FALSE; | ||
|  | } | ||
|  | 
 | ||
|  | /** read_term(-Term, +Options) is det.
 | ||
|  |  */ | ||
|  | 
 | ||
|  | 
 | ||
|  | /** @pred read_term(- _T_,+ _Options_) is iso
 | ||
|  | 
 | ||
|  | 
 | ||
|  |     Reads term  _T_ from the current input stream with execution | ||
|  |     controlled by the following options: | ||
|  | 
 | ||
|  |     + comments(- _Comments_) | ||
|  | 
 | ||
|  |     Unify _Comments_ with a list of string terms including comments before | ||
|  |     and within the term. | ||
|  | 
 | ||
|  |     + module( + _Module_) | ||
|  | 
 | ||
|  |     Read term using _Module_ as source module. | ||
|  | 
 | ||
|  |     + quasi_quotations(-List) | ||
|  | 
 | ||
|  |     Unify _List_ with the quasi-quotations present in the term. | ||
|  | 
 | ||
|  |     + term_position(- _Position_) | ||
|  | 
 | ||
|  |     Unify  _Position_ with a term describing the position of the stream | ||
|  |     at the start of parse. Use stream_position_data/3 to obtain extra | ||
|  |     information. | ||
|  | 
 | ||
|  |     + singletons(- _Names_) | ||
|  | 
 | ||
|  |     Unify  _Names_ with a list of the form  _Name=Var_, where | ||
|  |     _Name_ is the name of a non-anonymous singleton variable in the | ||
|  |     original term, and `Var` is the variable's representation in | ||
|  |     YAP. | ||
|  |     The variables occur in left-to-right traversal order. | ||
|  | 
 | ||
|  |     + syntax_errors(+ _Val_) | ||
|  | 
 | ||
|  |     Control action to be taken after syntax errors. See yap_flag/2 | ||
|  |     for detailed information. | ||
|  | 
 | ||
|  |     + variables(- _Names_) | ||
|  | 
 | ||
|  |     Unify  _Names_ with a list of the form  _Name=Var_, where  _Name_ is | ||
|  |     the name of a non-anonymous variable in the original term, and  _Var_ | ||
|  |     is the variable's representation in YAP. | ||
|  |     The variables occur in left-to-right traversal order. | ||
|  | 
 | ||
|  | 
 | ||
|  | */ | ||
|  | static | ||
|  | PRED_IMPL("read_term", 2, read_term, PL_FA_ISO) | ||
|  | { PRED_LD | ||
|  |     IOSTREAM *s; | ||
|  | 
 | ||
|  |   if ( getTextInputStream(0, &s) ) | ||
|  |     { if ( read_term_from_stream(s, A1, A2 PASS_LD) ) | ||
|  | 	return PL_release_stream(s); | ||
|  |       if ( Sferror(s) ) | ||
|  | 	return streamStatus(s); | ||
|  |       PL_release_stream(s); | ||
|  |       return FALSE; | ||
|  |     } | ||
|  | 
 | ||
|  |   return FALSE; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /*******************************
 | ||
|  |  *	   TERM <->ATOM		* | ||
|  |  *******************************/ | ||
|  | 
 | ||
|  | static int | ||
|  | atom_to_term(term_t atom, term_t term, term_t bindings) | ||
|  | { GET_LD | ||
|  |     PL_chars_t txt; | ||
|  | 
 | ||
|  |   if ( !bindings && PL_is_variable(atom) ) /* term_to_atom(+, -) */ | ||
|  |     { char buf[1024]; | ||
|  |       size_t bufsize = sizeof(buf); | ||
|  |       int rval; | ||
|  |       char *s = buf; | ||
|  |       IOSTREAM *stream; | ||
|  |       PL_chars_t txt; | ||
|  | 
 | ||
|  |       stream = Sopenmem(&s, &bufsize, "w"); | ||
|  |       stream->encoding = ENC_UTF8; | ||
|  |       PL_write_term(stream, term, 1200, PL_WRT_QUOTED); | ||
|  |       Sflush(stream); | ||
|  | 
 | ||
|  |       txt.text.t = s; | ||
|  |       txt.length = bufsize; | ||
|  |       txt.storage = PL_CHARS_HEAP; | ||
|  |       txt.encoding = ENC_UTF8; | ||
|  |       txt.canonical = FALSE; | ||
|  |       rval = PL_unify_text(atom, 0, &txt, PL_ATOM); | ||
|  | 
 | ||
|  |       Sclose(stream); | ||
|  |       if ( s != buf ) | ||
|  | 	Sfree(s); | ||
|  | 
 | ||
|  |       return rval; | ||
|  |     } | ||
|  | 
 | ||
|  |   if ( PL_get_text(atom, &txt, CVT_ALL|CVT_EXCEPTION) ) | ||
|  |     { GET_LD | ||
|  | 	read_data rd; | ||
|  |       int rval; | ||
|  |       IOSTREAM *stream; | ||
|  |       source_location oldsrc = LD->read_source; | ||
|  | 
 | ||
|  |       stream = Sopen_text(&txt, "r"); | ||
|  | 
 | ||
|  |       init_read_data(&rd, stream PASS_LD); | ||
|  |       if ( bindings && (PL_is_variable(bindings) || PL_is_list(bindings)) ) | ||
|  | 	rd.varnames = bindings; | ||
|  |       else if ( bindings ) | ||
|  | 	return PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_list, bindings); | ||
|  | 
 | ||
|  |       if ( !(rval = read_term(term, &rd PASS_LD)) && rd.has_exception ) | ||
|  | 	rval = PL_raise_exception(rd.exception); | ||
|  |       free_read_data(&rd); | ||
|  |       Sclose(stream); | ||
|  |       LD->read_source = oldsrc; | ||
|  | 
 | ||
|  |       //   getchar();
 | ||
|  |       return rval; | ||
|  |     } | ||
|  | 
 | ||
|  |   fail; | ||
|  | } | ||
|  | 
 | ||
|  | Term | ||
|  | Yap_StringToTerm(const char *s, size_t len, term_t bindings) | ||
|  | { GET_LD; | ||
|  |   read_data rd; | ||
|  |   int rval; | ||
|  |   IOSTREAM *stream; | ||
|  |   source_location oldsrc = LD->read_source; | ||
|  | 
 | ||
|  |   stream = Sopen_string(0, (char *)s, strlen( s ),  "r"); | ||
|  | 
 | ||
|  |   init_read_data(&rd, stream PASS_LD); | ||
|  |   rd.varnames = bindings; | ||
|  |   term_t tt = Yap_NewSlots(1); | ||
|  | 
 | ||
|  |   if ( !(rval = read_term(tt, &rd PASS_LD)) && rd.has_exception ) { | ||
|  |     rval = PL_raise_exception(rd.exception); | ||
|  |     return 0L; | ||
|  |   } | ||
|  |   free_read_data(&rd); | ||
|  |   Sclose(stream); | ||
|  |   LD->read_source = oldsrc; | ||
|  | 
 | ||
|  |   //   getchar();
 | ||
|  |   return Yap_GetFromSlot( tt); | ||
|  | } | ||
|  | 
 | ||
|  | /** @pred atom_to_term(+ _Atom_, - _Term_, - _Bindings_)
 | ||
|  | 
 | ||
|  | 
 | ||
|  |     Use  _Atom_ as input to read_term/2 using the option `variable_names` and return the read term in  _Term_ and the variable bindings in  _Bindings_.  _Bindings_ is a list of `Name = Var` couples, thus providing access to the actual variable names. See also read_term/2. If Atom has no valid syntax, a syntax_error exception is raised. | ||
|  | 
 | ||
|  | 
 | ||
|  | */ | ||
|  | static | ||
|  | PRED_IMPL("atom_to_term", 3, atom_to_term, 0) | ||
|  | { return atom_to_term(A1, A2, A3); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static | ||
|  | PRED_IMPL("term_to_atom", 2, term_to_atom, 0) | ||
|  | { return atom_to_term(A2, A1, 0); | ||
|  | } | ||
|  | 
 | ||
|  | static | ||
|  | PRED_IMPL("$context_variables", 1, context_variables, 0) | ||
|  | {   CACHE_REGS | ||
|  |     if ( LOCAL_VarNames == (CELL)0 ) | ||
|  |       return Yap_unify( TermNil, ARG1); | ||
|  |   return Yap_unify( LOCAL_VarNames, ARG1); | ||
|  | } | ||
|  | 
 | ||
|  | static | ||
|  | PRED_IMPL("$set_source", 2, set_source, 0) | ||
|  | { | ||
|  |   GET_LD | ||
|  |     atom_t at; | ||
|  |   term_t a = PL_new_term_ref(); | ||
|  | 
 | ||
|  |   if (!PL_get_atom(A1, &at)) | ||
|  |     return FALSE; | ||
|  |   source_file_name = at; | ||
|  |   if (!PL_get_arg(1, A2, a) || !PL_get_int64(a, &source_char_no) || | ||
|  |       !PL_get_arg(2, A2, a) || !PL_get_long(a, &source_line_no) || | ||
|  |       !PL_get_arg(3, A2, a) || !PL_get_long(a, &source_line_pos) || | ||
|  |       !PL_get_arg(4, A2, a) || !PL_get_int64(a, &source_byte_no) ) { | ||
|  |     return FALSE; | ||
|  |   } | ||
|  |   return TRUE; | ||
|  | } | ||
|  | 
 | ||
|  | int | ||
|  | PL_chars_to_term(const char *s, term_t t) | ||
|  | { GET_LD | ||
|  |     read_data rd; | ||
|  |   int rval; | ||
|  |   IOSTREAM *stream = Sopen_string(NULL, (char *)s, -1, "r"); | ||
|  |   source_location oldsrc = LD->read_source; | ||
|  | 
 | ||
|  |   init_read_data(&rd, stream PASS_LD); | ||
|  |   PL_put_variable(t); | ||
|  |   if ( !(rval = read_term(t, &rd PASS_LD)) && rd.has_exception ) | ||
|  |     PL_put_term(t, rd.exception); | ||
|  |   LOCAL_VarNames = rd.varnames; | ||
|  |   free_read_data(&rd); | ||
|  |   Sclose(stream); | ||
|  |   LD->read_source = oldsrc; | ||
|  | 
 | ||
|  |   return rval; | ||
|  | } | ||
|  | 
 | ||
|  | /*******************************
 | ||
|  |  *      PUBLISH PREDICATES	* | ||
|  |  *******************************/ | ||
|  | 
 | ||
|  | BeginPredDefs(read) | ||
|  | PRED_DEF("read_term",		  3, read_term,		  PL_FA_ISO) | ||
|  | PRED_DEF("read_term",		  2, read_term,		  PL_FA_ISO) | ||
|  | PRED_DEF("read_clause",         3, read_clause,         0) | ||
|  | PRED_DEF("atom_to_term", 3, atom_to_term, 0) | ||
|  | PRED_DEF("term_to_atom", 2, term_to_atom, 0) | ||
|  | PRED_DEF("$context_variables", 1, context_variables, 0) | ||
|  | PRED_DEF("$set_source",  2, set_source, 0) | ||
|  | #ifdef O_QUASIQUOTATIONS
 | ||
|  | PRED_DEF("$qq_open",            2, qq_open,             0) | ||
|  | #endif
 | ||
|  | EndPredDefs | ||
|  | 
 | ||
|  | //! @}
 |