Changeset 2920:e22c68333e73 in livinglogic.python.xist

Show
Ignore:
Timestamp:
09/12/07 14:15:08 (12 years ago)
Author:
Walter Doerwald <walter@…>
Branch:
default
Message:

Change sgmlop back to support both unicode and 8bit parsing via a #define

Files:
2 modified

Legend:

Unmodified
Added
Removed
  • setup.py

    r2903 r2920  
    6868        tools.Extension("ll.xist.csstokenizer", ["src/ll/xist/csstokenizer.cxx"]), 
    6969        tools.Extension("ll.xist.helpers", ["src/ll/xist/helpers.c"]), 
    70         tools.Extension("ll.xist.sgmlop", ["src/ll/xist/sgmlop.c"]) 
     70        tools.Extension("ll.xist.sgmlop", ["src/ll/xist/sgmlop.c"], define_macros=[("SGMLOP_UNICODE_SUPPORT", None)]), 
    7171    ], 
    7272    entry_points=dict( 
  • src/ll/xist/sgmlop.c

    r2915 r2920  
    4040 * 2003-09-07 fl  Fixed garbage collection support for Python 2.2 and later 
    4141 * 2004-04-04 fl  Fixed parsing of non-ascii attribute values (@XMLTOOLKIT38) 
    42  * 2007-09-05 wd  Python 2.5 updates: use Py_ssize_t 
     42 * 2007-09-12 wd  Python 2.5 updates: use Py_ssize_t 
    4343 * 
    44  * Copyright (c) 1998-2003 by Secret Labs AB 
    45  * Copyright (c) 1998-2003 by Fredrik Lundh 
     44 * Copyright (c) 1998-2007 by Secret Labs AB 
     45 * Copyright (c) 1998-2007 by Fredrik Lundh 
    4646 *  
    4747 * fredrik@pythonware.com 
     
    7676 
    7777static char copyright[] = 
    78     " SGMLOP 1.1 Copyright (c) 1998-2003 by Secret Labs AB "; 
     78    " SGMLOP 1.1.2 Copyright (c) 1998-2003 by Secret Labs AB "; 
    7979 
    8080#define PY_SIZE_T_CLEAN 
     
    8383 
    8484#include <ctype.h> 
     85 
     86#ifdef SGMLOP_UNICODE_SUPPORT 
     87/* use wide character set (experimental) */ 
     88/* FIXME: under Python 1.6, the current version converts Unicode 
     89   strings to UTF-8, and parses the result as if it was an ASCII 
     90   string. */ 
     91 
     92#define CHAR_T            Py_UNICODE 
     93#define ISALNUM           Py_UNICODE_ISALNUM 
     94#define TOLOWER           Py_UNICODE_TOLOWER 
     95#define EMPTYSTRING()     PyUnicode_FromUnicode(NULL, 0) 
     96#define BUILDSTRING(s, l) PyUnicode_FromUnicode(s, l) 
     97#define PARSEFORMAT       "u#" 
     98#define BUILDFORMAT       "u#" 
     99 
     100#define ISSPACE(ch) Py_UNICODE_ISSPACE(ch) 
     101 
     102#define LETTER(ch) Py_UNICODE_ISALPHA(ch) 
     103 
     104#define NAMECHAR(ch)\ 
     105    (Py_UNICODE_ISALNUM(ch) || (ch) == '.' || (ch) == '-' ||\ 
     106     (ch) == '_' || (ch) == ':') 
     107 
     108#else 
     109 
     110/* 8-bit character set */ 
     111#define CHAR_T            unsigned char 
     112#define ISALNUM           isalnum 
     113#define TOLOWER           tolower 
     114#define EMPTYSTRING()     PyString_FromString("") 
     115#define BUILDSTRING(s, l) PyString_FromStringAndSize(s, l) 
     116#define PARSEFORMAT       "t#" 
     117#define BUILDFORMAT       "s#" 
     118 
     119#define ISSPACE(ch)\ 
     120    ((ch) == ' ' || (ch) == '\t' || (ch) == '\r' || (ch) == '\n') 
     121 
     122#define LETTER(ch)\ 
     123    (((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z') ||\ 
     124     (ch) >= 0x80) 
     125 
     126#define DIGIT(ch)\ 
     127    ((ch) >= '0' && (ch) <= '9') 
     128 
     129#define NAMECHAR(ch)\ 
     130    (LETTER(ch) || DIGIT(ch) || (ch) == '.' || (ch) == '-' ||\ 
     131     (ch) == '_' || (ch) == ':') 
     132 
     133#endif 
     134 
     135#if PY_VERSION_HEX >= 0x02050000 
     136/* use Py_ssize_t (requires Python 2.5 or later) */ 
     137#define INTFORMAT "n" 
     138#else 
     139typedef int Py_ssize_t; 
     140#define INTFORMAT "i" 
     141#endif 
    85142 
    86143#if PY_VERSION_HEX >= 0x02000000 
     
    121178typedef struct { 
    122179    /* well-formedness checker */ 
    123     int (*starttag)(void* self, Py_UNICODE* b, Py_UNICODE* e); 
    124     int (*endtag)(void* self, Py_UNICODE* b, Py_UNICODE* e); 
    125     int (*attribute)(void* self, Py_UNICODE* b, Py_UNICODE* e); 
    126     int (*entityref)(void* self, Py_UNICODE* b, Py_UNICODE* e); 
    127     int (*charref)(void* self, Py_UNICODE* b, Py_UNICODE* e); 
    128     int (*comment)(void* self, Py_UNICODE* b, Py_UNICODE* e); 
     180    int (*starttag)(void* self, CHAR_T* b, CHAR_T* e); 
     181    int (*endtag)(void* self, CHAR_T* b, CHAR_T* e); 
     182    int (*attribute)(void* self, CHAR_T* b, CHAR_T* e); 
     183    int (*entityref)(void* self, CHAR_T* b, CHAR_T* e); 
     184    int (*charref)(void* self, CHAR_T* b, CHAR_T* e); 
     185    int (*comment)(void* self, CHAR_T* b, CHAR_T* e); 
    129186} Checker; 
    130187 
     
    148205 
    149206    /* buffer (holds incomplete tags) */ 
    150     Py_UNICODE* buffer; 
     207    CHAR_T* buffer; 
    151208    Py_ssize_t bufferlen; /* current amount of data */ 
    152209    Py_ssize_t buffertotal; /* actually allocated */ 
     
    174231    ); 
    175232static PyObject* attrparse( 
    176     FastParserObject* self, const Py_UNICODE *p, const Py_UNICODE *e 
     233    FastParserObject* self, const CHAR_T *p, const CHAR_T *e 
    177234    ); 
    178235static PyObject* attrexpand( 
    179     FastParserObject* self, const Py_UNICODE *p, const Py_UNICODE *e 
     236    FastParserObject* self, const CHAR_T *p, const CHAR_T *e 
    180237    ); 
    181238 
    182 static int entity(const Py_UNICODE* b, const Py_UNICODE *e); 
    183  
    184 static int wf_starttag(Checker* self, Py_UNICODE* b, Py_UNICODE* e); 
    185 static int wf_endtag(Checker* self, Py_UNICODE* b, Py_UNICODE* e); 
    186 static int wf_ok(Checker* self, Py_UNICODE* b, Py_UNICODE* e); 
     239static int entity(const CHAR_T* b, const CHAR_T *e); 
     240 
     241static int wf_starttag(Checker* self, CHAR_T* b, CHAR_T* e); 
     242static int wf_endtag(Checker* self, CHAR_T* b, CHAR_T* e); 
     243static int wf_ok(Checker* self, CHAR_T* b, CHAR_T* e); 
    187244 
    188245static Checker wf_checker = { 
     
    213270    case 0: 
    214271        Py_DECREF(list); 
    215         return PyUnicode_FromUnicode(NULL, 0); 
     272        return EMPTYSTRING(); 
    216273    case 1: 
    217274        result = PyList_GET_ITEM(list, 0); 
     
    422479 
    423480static PyObject* 
    424 feed(FastParserObject* self, Py_UNICODE* string, Py_ssize_t stringlen, int last) 
     481feed(FastParserObject* self, CHAR_T* string, Py_ssize_t stringlen, int last) 
    425482{ 
    426483    /* common subroutine for SGMLParser.feed and SGMLParser.close */ 
     
    438495    if (!self->buffer) { 
    439496        length = stringlen; 
    440         self->buffer = malloc((length + 1)*sizeof(Py_UNICODE)); 
     497        self->buffer = malloc((length + 1)*sizeof(CHAR_T)); 
    441498        self->bufferlen = self->shorttag = self->doctype = 0; 
    442499        self->buffertotal = stringlen; 
     
    444501        length = self->bufferlen + stringlen; 
    445502        if (length > self->buffertotal) { 
    446             self->buffer = realloc(self->buffer, (length + 1)*sizeof(Py_UNICODE)); 
     503            self->buffer = realloc(self->buffer, (length + 1)*sizeof(CHAR_T)); 
    447504            self->buffertotal = length; 
    448505        } 
     
    452509        return NULL; 
    453510    } 
    454     memcpy(self->buffer + self->bufferlen, string, stringlen*sizeof(Py_UNICODE)); 
     511    memcpy(self->buffer + self->bufferlen, string, stringlen*sizeof(CHAR_T)); 
    455512    self->bufferlen = length; 
    456513 
     
    474531        /* adjust buffer */ 
    475532        memmove(self->buffer, self->buffer + length, 
    476                 (self->bufferlen - length)*sizeof(Py_UNICODE)); 
     533                (self->bufferlen - length)*sizeof(CHAR_T)); 
    477534 
    478535    self->bufferlen -= length; 
     
    486543    } 
    487544 
    488     return Py_BuildValue("n", self->bufferlen); 
     545    return Py_BuildValue(INTFORMAT, self->bufferlen); 
    489546} 
    490547 
     
    494551    /* feed a chunk of data to the parser */ 
    495552 
    496     Py_UNICODE* string; 
     553    CHAR_T* string; 
    497554    Py_ssize_t stringlen; 
    498     if (!PyArg_ParseTuple(args, "u#", &string, &stringlen)) 
     555    if (!PyArg_ParseTuple(args, PARSEFORMAT ":feed", &string, &stringlen)) 
    499556        return NULL; 
    500557 
     
    506563{ 
    507564    /* flush parser buffers */ 
    508     Py_UNICODE ch = 0; 
     565    CHAR_T ch = 0; 
    509566 
    510567    if (!PyArg_ParseTuple(args, ":close")) 
     
    519576    /* feed a single chunk of data to the parser */ 
    520577 
    521     Py_UNICODE* string; 
     578    CHAR_T* string; 
    522579    Py_ssize_t stringlen; 
    523     if (!PyArg_ParseTuple(args, "u#", &string, &stringlen)) 
     580    if (!PyArg_ParseTuple(args, PARSEFORMAT ":parse", &string, &stringlen)) 
    524581        return NULL; 
    525582 
     
    593650/* well-formedness checker */ 
    594651 
    595 #define DIGIT(ch) ((ch) >= '0' && (ch) <= '9') 
    596  
    597 #define NAMECHAR(ch) (Py_UNICODE_ISALNUM(ch) || (ch) == '.' || (ch) == '-' || (ch) == '_' || (ch) == ':') 
    598  
    599652static int 
    600 wf_tag(Checker* self, Py_UNICODE* b, Py_UNICODE* e) 
     653wf_tag(Checker* self, CHAR_T* b, CHAR_T* e) 
    601654{ 
    602655    /* check that the start tag contains a valid name */ 
    603656    if (b >= e) 
    604657        goto err; 
    605     if (!Py_UNICODE_ISALPHA(*b) && *b != '_' && *b != ':') 
     658    if (!LETTER(*b) && *b != '_' && *b != ':') 
    606659        goto err; 
    607660    b++; 
     
    618671 
    619672static int 
    620 wf_starttag(Checker* self, Py_UNICODE* b, Py_UNICODE* e) 
     673wf_starttag(Checker* self, CHAR_T* b, CHAR_T* e) 
    621674{ 
    622675    if (!wf_tag(self, b, e)) 
     
    626679 
    627680static int 
    628 wf_endtag(Checker* self, Py_UNICODE* b, Py_UNICODE* e) 
     681wf_endtag(Checker* self, CHAR_T* b, CHAR_T* e) 
    629682{ 
    630683    if (!wf_tag(self, b, e)) 
     
    634687 
    635688static int 
    636 wf_ok(Checker* self, Py_UNICODE* b, Py_UNICODE* e) 
     689wf_ok(Checker* self, CHAR_T* b, CHAR_T* e) 
    637690{ 
    638691    return 1; 
     
    660713 
    661714static int 
    662 entity(const Py_UNICODE* b, const Py_UNICODE* e) 
     715entity(const CHAR_T* b, const CHAR_T* e) 
    663716{ 
    664717    /* resolve standard entity (return <0 if non-standard/malformed) */ 
     
    678731        else if (b[0] == '#') { 
    679732            /* character entity */ 
    680             const Py_UNICODE *p; 
     733            const CHAR_T *p; 
    681734            int ch = 0; 
    682735            b++; 
     
    712765fastfeed(FastParserObject* self) 
    713766{ 
    714     Py_UNICODE *end; /* tail */ 
    715     Py_UNICODE *p, *q, *s; /* scanning pointers */ 
    716     Py_UNICODE *b, *t, *e; /* token start/end */ 
     767    CHAR_T *end; /* tail */ 
     768    CHAR_T *p, *q, *s; /* scanning pointers */ 
     769    CHAR_T *b, *t, *e; /* token start/end */ 
    717770 
    718771    int token; 
     
    797850                if (++p >= end) 
    798851                    goto eol; 
    799             } else if (Py_UNICODE_ISSPACE(*p)) 
     852            } else if (ISSPACE(*p)) 
    800853                continue; 
    801854 
     
    803856            b = p; 
    804857            if (!self->xml) 
    805                 while (Py_UNICODE_ISALNUM(*p) || *p == '-' || *p == '.' || 
     858                while (ISALNUM(*p) || *p == '-' || *p == '.' || 
    806859                       *p == ':' || *p == '?') { 
    807                     *p = Py_UNICODE_TOLOWER(*p); 
     860                    *p = TOLOWER(*p); 
    808861                    if (++p >= end) 
    809862                        goto eol; 
    810863                } 
    811864            else 
    812                 while (*p != '>' && !Py_UNICODE_ISSPACE(*p) && *p != '/' && *p != '?') { 
     865                while (*p != '>' && !ISSPACE(*p) && *p != '/' && *p != '?') { 
    813866                    if (++p >= end) 
    814867                        goto eol; 
     
    842895                int last = 0; 
    843896                while ((*p != '>' && *p != '<') || quote) { 
    844                     if (!Py_UNICODE_ISSPACE(*p)) { 
     897                    if (!ISSPACE(*p)) { 
    845898                        has_attr = 1; 
    846899                        /* FIXME: note: end tags cannot have attributes! */ 
     
    910963                goto eol; 
    911964            b = t = p; 
    912             while (*p != ';' && !Py_UNICODE_ISSPACE(*p)) 
     965            while (*p != ';' && !ISSPACE(*p)) 
    913966                if (++p >= end) 
    914967                    goto eol; 
     
    927980                if (++p >= end) 
    928981                    goto eol; 
    929             } else if (Py_UNICODE_ISSPACE(*p)) 
     982            } else if (ISSPACE(*p)) 
    930983                continue; 
    931984            b = t = p; 
    932             while (*p != ';' && *p != '<' && *p != '>' && !Py_UNICODE_ISSPACE(*p)) 
     985            while (*p != ';' && *p != '<' && *p != '>' && !ISSPACE(*p)) 
    933986                if (++p >= end) 
    934987                    goto eol; 
     
    9531006            /* flush any raw data before this tag */ 
    9541007            PyObject* res; 
    955             res = PyObject_CallFunction(self->handle_data, "u#", s, q-s); 
     1008            res = PyObject_CallFunction(self->handle_data, BUILDFORMAT, s, q-s); 
    9561009            if (!res) 
    9571010                return -1; 
     
    9651018                    PyObject* res; 
    9661019                    res = PyObject_CallFunction( 
    967                         self->finish_endtag, "u#", b, t-b 
     1020                        self->finish_endtag, BUILDFORMAT, b, t-b 
    9681021                        ); 
    9691022                    if (!res) 
     
    9761029                if (self->handle_special) { 
    9771030                    PyObject* res; 
    978                     res = PyObject_CallFunction(self->handle_special, "u#", b, e-b); 
     1031                    res = PyObject_CallFunction( 
     1032                        self->handle_special, BUILDFORMAT, b, e-b 
     1033                        ); 
    9791034                    if (!res) 
    9801035                        return -1; 
     
    9851040                    PyObject* res; 
    9861041                    Py_ssize_t len = t-b; 
    987                     while (Py_UNICODE_ISSPACE(*t)) 
     1042                    while (ISSPACE(*t)) 
    9881043                        t++; 
    989                     res = PyObject_CallFunction(self->handle_proc, "u#u#", b, len, t, e-t); 
     1044                    res = PyObject_CallFunction( 
     1045                        self->handle_proc, BUILDFORMAT BUILDFORMAT, b, len, t, e-t 
     1046                        ); 
    9901047                    if (!res) 
    9911048                        return -1; 
     
    9971054                    PyObject* attr; 
    9981055                    Py_ssize_t len = t-b; 
    999                     if (self->check && !self->check->starttag(self->check, b, t)) 
    1000                         return -1; 
    1001                     while (Py_UNICODE_ISSPACE(*t)) 
     1056                    if (self->check && !self->check->starttag( 
     1057                        self->check, b, t 
     1058                        )) 
     1059                    return -1; 
     1060                    while (ISSPACE(*t)) 
    10021061                        t++; 
    10031062                    attr = attrparse(self, t, e); 
    10041063                    if (!attr) 
    10051064                        return -1; 
    1006                     res = PyObject_CallFunction(self->finish_starttag, "u#O", b, len, attr); 
     1065                    res = PyObject_CallFunction( 
     1066                        self->finish_starttag, BUILDFORMAT "O", b, len, attr 
     1067                        ); 
    10071068                    Py_DECREF(attr); 
    10081069                    if (!res) 
     
    10101071                    Py_DECREF(res); 
    10111072                    if (token == TAG_EMPTY && self->finish_endtag) { 
    1012                         if (self->check && !self->check->endtag(self->check, b, b+len)) 
     1073                        if (self->check && !self->check->endtag( 
     1074                            self->check, b, b+len 
     1075                            )) 
    10131076                            return -1; 
    1014                         res = PyObject_CallFunction(self->finish_endtag, "u#", b, len); 
     1077                        res = PyObject_CallFunction( 
     1078                            self->finish_endtag, BUILDFORMAT, b, len 
     1079                            ); 
    10151080                        if (!res) 
    10161081                            return -1; 
     
    10201085            } else { 
    10211086                /* can this really happen? */ 
    1022                 PyErr_Format(PyExc_RuntimeError, "unknown token: 0x%x", token); 
     1087                PyErr_Format( 
     1088                    PyExc_RuntimeError, "unknown token: 0x%x", token 
     1089                    ); 
    10231090                return -1; 
    10241091            } 
    10251092        } else if (token == ENTITYREF) { 
    1026             Py_UNICODE ch; 
     1093            CHAR_T ch; 
    10271094            int charref; 
    10281095  entity: 
     
    10311098                if (self->check && !self->check->entityref(self->check, b, e)) 
    10321099                    return -1; 
    1033                 res = PyObject_CallFunction(self->handle_entityref, "u#", b, e-b); 
     1100                res = PyObject_CallFunction( 
     1101                    self->handle_entityref, BUILDFORMAT, b, e-b 
     1102                    ); 
    10341103                if (!res) 
    10351104                    return -1; 
     
    10421111                if (self->handle_data) { 
    10431112                    PyObject* res; 
    1044                     ch = (Py_UNICODE) charref; 
    1045                     res = PyObject_CallFunction(self->handle_data, "u#", &charref, 1); 
     1113                    /* all builtin entities fit in a CHAR_T */ 
     1114                    ch = (CHAR_T) charref; 
     1115                    res = PyObject_CallFunction( 
     1116                        self->handle_data, BUILDFORMAT, &ch, 1 
     1117                        ); 
    10461118                    if (!res) 
    10471119                        return -1; 
     
    10571129                if (self->check && !self->check->entityref(self->check, b, e)) 
    10581130                    return -1; 
    1059                 ent = PyObject_CallFunction(self->resolve_entityref, "u#", b, e-b); 
     1131                ent = PyObject_CallFunction( 
     1132                    self->resolve_entityref, BUILDFORMAT, b, e-b 
     1133                    ); 
    10601134                if (!ent) 
    10611135                    return -1; 
    10621136                if (ent != Py_None) { 
    10631137                    PyObject* res; 
    1064                     res = PyObject_CallFunction(self->handle_data, "O", ent); 
     1138                    res = PyObject_CallFunction( 
     1139                        self->handle_data, "O", ent 
     1140                        ); 
    10651141                    Py_DECREF(ent); 
    10661142                    if (!res) 
     
    10731149                /* if the user wants data, but we cannot resolve this 
    10741150                   entity, flag it as configuration error */ 
    1075                 PyErr_SetString(PyExc_SyntaxError, "unresolvable entity"); 
     1151                PyErr_SetString( 
     1152                    PyExc_SyntaxError, "unresolvable entity" 
     1153                    ); 
    10761154                return -1; 
    10771155            } 
    1078         } else if (token == CHARREF && (self->handle_charref || self->handle_data)) { 
     1156        } else if (token == CHARREF && (self->handle_charref || 
     1157                                        self->handle_data)) { 
    10791158            if (self->check && !self->check->charref(self->check, b, e)) 
    10801159                return -1; 
    10811160            if (self->handle_charref) { 
    10821161                PyObject* res; 
    1083                 res = PyObject_CallFunction(self->handle_charref, "u#", b, e-b); 
     1162                res = PyObject_CallFunction( 
     1163                    self->handle_charref, BUILDFORMAT, b, e-b 
     1164                    ); 
    10841165                if (!res) 
    10851166                    return -1; 
     
    10871168            } else { 
    10881169                /* fallback: handle charref's as data */ 
    1089                 Py_UNICODE ch; 
     1170                CHAR_T ch; 
    10901171                int charref = entity(b-1, e); 
    10911172                if (charref < 0) { 
     
    10931174                    goto entity; 
    10941175                } 
    1095                 PyObject* res; 
    1096                 ch = charref; 
    1097                 res = PyObject_CallFunction(self->handle_data, "u#", &ch, 1); 
    1098                 if (!res) 
    1099                     return -1; 
    1100                 Py_DECREF(res); 
     1176                if (charref > 255) { 
     1177                    /* FIXME: return as unicode */ 
     1178                    if (self->handle_data && self->strict) { 
     1179                        /* if the user wants data, but we cannot resolve this 
     1180                           entity, flag it as configuration error */ 
     1181                        PyErr_SetString( 
     1182                            PyExc_SyntaxError, "character entity too large" 
     1183                            ); 
     1184                        return -1; 
     1185                    } 
     1186                } else { 
     1187                    PyObject* res; 
     1188                    ch = charref; 
     1189                    res = PyObject_CallFunction( 
     1190                        self->handle_data, BUILDFORMAT, &ch, 1 
     1191                        ); 
     1192                    if (!res) 
     1193                        return -1; 
     1194                    Py_DECREF(res); 
     1195                } 
    11011196            } 
    1102         } else if (token == CDATA && (self->handle_cdata || self->handle_data)) { 
     1197        } else if (token == CDATA && (self->handle_cdata || 
     1198                                      self->handle_data)) { 
    11031199            PyObject* res; 
    11041200            if (self->handle_cdata) { 
    1105                 res = PyObject_CallFunction(self->handle_cdata, "u#", b, e-b); 
     1201                res = PyObject_CallFunction( 
     1202                    self->handle_cdata, BUILDFORMAT, b, e-b 
     1203                    ); 
    11061204            } else { 
    11071205                /* fallback: handle cdata as plain data */ 
    1108                 res = PyObject_CallFunction(self->handle_data, "u#", b, e-b); 
     1206                res = PyObject_CallFunction(self->handle_data, BUILDFORMAT, b, e-b); 
    11091207            } 
    11101208            if (!res) 
     
    11151213            if (self->check && !self->check->comment(self->check, b, e)) 
    11161214                return -1; 
    1117             res = PyObject_CallFunction(self->handle_comment, "u#", b, e-b); 
     1215            res = PyObject_CallFunction(self->handle_comment, BUILDFORMAT, b, e-b); 
    11181216            if (!res) 
    11191217                return -1; 
     
    11281226    if (q != s && self->handle_data) { 
    11291227        PyObject* res; 
    1130         res = PyObject_CallFunction(self->handle_data, "u#", s, q-s); 
     1228        res = PyObject_CallFunction(self->handle_data, BUILDFORMAT, s, q-s); 
    11311229        if (!res) 
    11321230            return -1; 
     
    11341232    } 
    11351233 
    1136     /* returns the number of chars consumed in this pass */ 
     1234    /* returns the number of characters consumed in this pass */ 
    11371235    return q - self->buffer; 
    11381236} 
    11391237 
    11401238static PyObject* 
    1141 attrparse(FastParserObject* self, const Py_UNICODE* p, const Py_UNICODE* end) 
     1239attrparse(FastParserObject* self, const CHAR_T* p, const CHAR_T* end) 
    11421240{ 
    11431241    PyObject* attrs; 
    11441242    PyObject* key = NULL; 
    11451243    PyObject* value = NULL; 
    1146     const Py_UNICODE* q; 
    1147     const Py_UNICODE* value_start; 
     1244    const CHAR_T* q; 
     1245    const CHAR_T* value_start; 
    11481246    Py_ssize_t value_length; 
    11491247    int has_entity; 
     
    11571255 
    11581256        /* skip leading space */ 
    1159         while (p < end && Py_UNICODE_ISSPACE(*p)) 
     1257        while (p < end && ISSPACE(*p)) 
    11601258            p++; 
    11611259        if (p >= end) 
     
    11641262        /* get attribute name (key) */ 
    11651263        q = p; 
    1166         while (p < end && *p != '=' && !Py_UNICODE_ISSPACE(*p)) 
     1264        while (p < end && *p != '=' && !ISSPACE(*p)) 
    11671265            p++; 
    11681266 
    1169         key = PyUnicode_FromUnicode(q, p-q); 
     1267        key = BUILDSTRING(q, p-q); 
    11701268        if (key == NULL) 
    11711269            goto err; 
     
    11781276        Py_INCREF(value); 
    11791277 
    1180         while (p < end && Py_UNICODE_ISSPACE(*p)) 
     1278        while (p < end && ISSPACE(*p)) 
    11811279            p++; 
    11821280 
     
    11911289            if (p < end) 
    11921290                p++; 
    1193             while (p < end && Py_UNICODE_ISSPACE(*p)) 
     1291            while (p < end && ISSPACE(*p)) 
    11941292                p++; 
    11951293 
     
    12071305                    p++; 
    12081306            } else { 
    1209                 while (p < end && !Py_UNICODE_ISSPACE(*p) && *p != '>') 
     1307                while (p < end && !ISSPACE(*p) && *p != '>') 
    12101308                    p++; 
    12111309                value_start = q; 
     
    12181316                    ); 
    12191317            } else 
    1220                 value = PyUnicode_FromUnicode(value_start, value_length); 
     1318                value = BUILDSTRING(value_start, value_length); 
    12211319 
    12221320            if (!value) 
     
    12671365 
    12681366static PyObject* 
    1269 attrexpand(FastParserObject* self, const Py_UNICODE* p, const Py_UNICODE* e) 
     1367attrexpand(FastParserObject* self, const CHAR_T* p, const CHAR_T* e) 
    12701368{ 
    12711369    /* expand entities in attribute string */ 
    12721370    PyObject* list; 
    12731371    PyObject* item; 
    1274     const Py_UNICODE* q; 
     1372    const CHAR_T* q; 
    12751373    int charref; 
    12761374    int status; 
     
    12831381 
    12841382    while (p < e) { 
     1383 
    12851384        /* find character run (q:p) */ 
    12861385        q = p; 
     
    12881387            p++; 
    12891388 
    1290         item = PyUnicode_FromUnicode(q, p-q); 
     1389        item = BUILDSTRING(q, p-q); 
    12911390        if (!item) 
    12921391            goto err; 
     
    13081407        if (charref >= 0) { 
    13091408            /* builtin entity or charref */ 
    1310             Py_UNICODE ch = (Py_UNICODE) charref; 
    1311             item = PyUnicode_FromUnicode(&ch, 1); 
     1409            if (charref > 255) { 
     1410                /* FIXME: return as unicode */ 
     1411                if (self->handle_data && self->strict) { 
     1412                    /* if the user wants data, but we cannot resolve this 
     1413                       entity, flag it as configuration error */ 
     1414                    PyErr_SetString( 
     1415                        PyExc_SyntaxError, "character entity too large" 
     1416                        ); 
     1417                    goto err; 
     1418                } 
     1419                if (self->resolve_entityref) 
     1420                    /* non-standard; use resolver */ 
     1421                    item = PyObject_CallFunction( 
     1422                        self->resolve_entityref, BUILDFORMAT, q, p-q 
     1423                        ); 
     1424                else { 
     1425                    /* ignore, for now */ 
     1426                    item = Py_None; 
     1427                    Py_INCREF(Py_None); 
     1428                } 
     1429            } else { 
     1430                CHAR_T ch = (CHAR_T) charref; 
     1431                item = BUILDSTRING(&ch, 1); 
     1432            } 
    13121433        } else if (self->resolve_entityref) { 
    13131434            /* non-standard; use resolver */ 
    1314             item = PyObject_CallFunction(self->resolve_entityref, "u#", q, p-q); 
     1435            item = PyObject_CallFunction( 
     1436                self->resolve_entityref, BUILDFORMAT, q, p-q 
     1437                ); 
    13151438        } else { 
    13161439            /* ignore */