This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/os/pl-codelist.c

149 lines
3.6 KiB
C

/* $Id$
Part of SWI-Prolog
Author: Jan Wielemaker
E-mail: J.Wielemaker@uva.nl
WWW: http://www.swi-prolog.org
Copyright (C): 1985-2011, University of Amsterdam
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "pl-incl.h"
#if __YAP_PROLOG__
#include "pl-codelist.h"
#else
#include "../pl-codelist.h"
#endif
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
codes_or_chars_to_buffer(term_t l, unsigned int flags, int wide, CVT_code *status)
If l represents a list of codes or characters, return a buffer holding
the characters. If wide == TRUE the buffer contains objects of type
pl_wchar_t. Otherwise it contains traditional characters.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
Buffer
codes_or_chars_to_buffer(term_t l, unsigned int flags, int wide, CVT_result *result)
{ GET_LD
Buffer b;
word list = valHandle(l);
word slow;
Word arg, tail;
int step_slow = TRUE;
enum { CHARS, CODES } type;
if ( isList(list) )
{ intptr_t c = -1;
arg = argTermP(list, 0);
deRef(arg);
if ( isTaggedInt(*arg) )
{ c = valInt(*arg);
type = CODES;
} else
{ c = charCode(*arg);
type = CHARS;
}
result->culprit = *arg;
if ( c < 0 || (!wide && c > 0xff) )
{ if ( canBind(*arg) )
result->status = CVT_partial;
else if ( c < 0 )
result->status = CVT_nocode;
else if ( c > 0xff )
result->status = CVT_wide;
return NULL;
}
} else if ( isNil(list) )
{ return findBuffer(flags);
} else
{ if ( canBind(list) )
result->status = CVT_partial;
else
result->status = CVT_nolist;
return NULL;
}
b = findBuffer(flags);
slow = list;
while( isList(list) )
{ intptr_t c = -1;
arg = argTermP(list, 0);
deRef(arg);
switch(type)
{ case CODES:
if ( isTaggedInt(*arg) )
c = valInt(*arg);
break;
case CHARS:
c = charCode(*arg);
break;
}
if ( c < 0 || (!wide && c > 0xff) )
{ result->culprit = *arg;
unfindBuffer(flags); /* TBD: check unicode range */
if ( canBind(*arg) )
result->status = CVT_partial;
else if ( c < 0 )
result->status = (type == CODES ? CVT_nocode : CVT_nochar);
else if ( c > 0xff )
result->status = CVT_wide;
return NULL;
}
if ( wide )
addBuffer(b, (pl_wchar_t)c, pl_wchar_t);
else
addBuffer(b, (unsigned char)c, unsigned char);
tail = argTermP(list, 1);
deRef(tail);
list = *tail;
if ( list == slow ) /* cyclic */
{ unfindBuffer(flags);
result->status = CVT_nolist;
return NULL;
}
if ( (step_slow = !step_slow) )
{ tail = argTermP(slow, 1);
deRef(tail);
slow = *tail;
}
}
if ( !isNil(list) )
{ unfindBuffer(flags);
if ( canBind(list) )
result->status = CVT_partial;
else
result->status = CVT_nolist;
return NULL;
}
result->status = CVT_ok;
return b;
}