#include <expat.h>
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#undef convert
#include "patchlevel.h"
#include "encoding.h"
#if PATCHLEVEL < 5
#define PL_sv_undef sv_undef
#define PL_sv_no sv_no
#define PL_sv_yes sv_yes
#define PL_na na
#endif
#define BUFSIZE 32768
#define NSDELIM '|'
#define XMLP_UPD(fld) \
RETVAL = cbv->fld ? newSVsv(cbv->fld) : &PL_sv_undef;\
if
(cbv->fld) {\
if
(cbv->fld != fld)\
sv_setsv(cbv->fld, fld);\
}\
else
\
cbv->fld = newSVsv(fld)
#define PUSHRET \
ST(0) = RETVAL;\
if
(RETVAL != &PL_sv_undef && SvREFCNT(RETVAL)) sv_2mortal(RETVAL)
typedef
struct
{
SV* self_sv;
XML_Parser p;
AV* context;
AV* new_prefix_list;
HV *nstab;
AV *nslst;
unsigned
int
st_serial;
unsigned
int
st_serial_stackptr;
unsigned
int
st_serial_stacksize;
unsigned
int
* st_serial_stack;
unsigned
int
skip_until;
SV *recstring;
char
* delim;
STRLEN delimlen;
unsigned ns:1;
unsigned no_expand:1;
unsigned parseparam:1;
SV* start_sv;
SV* end_sv;
SV* char_sv;
SV* proc_sv;
SV* cmnt_sv;
SV* dflt_sv;
SV* entdcl_sv;
SV* eledcl_sv;
SV* attdcl_sv;
SV* doctyp_sv;
SV* doctypfin_sv;
SV* xmldec_sv;
SV* unprsd_sv;
SV* notation_sv;
SV* extent_sv;
SV* extfin_sv;
SV* startcd_sv;
SV* endcd_sv;
} CallbackVector;
static
HV* EncodingTable = NULL;
static
XML_Char nsdelim[] = {NSDELIM,
'\0'
};
static
char
*QuantChar[] = {
""
,
"?"
,
"*"
,
"+"
};
static
void
suspend_callbacks(CallbackVector *);
static
void
resume_callbacks(CallbackVector *);
#if PATCHLEVEL < 5 && SUBVERSION < 5
static
SV *
newSVpvn(
char
*s, STRLEN len)
{
register
SV *sv;
sv = newSV(0);
sv_setpvn(sv, s, len);
return
sv;
}
#define ERRSV GvSV(errgv)
#endif
#ifdef SvUTF8_on
static
SV *
newUTF8SVpv(
char
*s, STRLEN len) {
register
SV *sv;
sv = newSVpv(s, len);
SvUTF8_on(sv);
return
sv;
}
static
SV *
newUTF8SVpvn(
char
*s, STRLEN len) {
register
SV *sv;
sv = newSV(0);
sv_setpvn(sv, s, len);
SvUTF8_on(sv);
return
sv;
}
#else /* SvUTF8_on not defined */
#define newUTF8SVpv newSVpv
#define newUTF8SVpvn newSVpvn
#endif
static
void
*
mymalloc(
size_t
size) {
#ifndef LEAKTEST
return
safemalloc(size);
#else
return
safexmalloc(328,size);
#endif
}
static
void
*
myrealloc(
void
*p,
size_t
s) {
#ifndef LEAKTEST
return
saferealloc(p, s);
#else
return
safexrealloc(p, s);
#endif
}
static
void
myfree(
void
*p) {
Safefree(p);
}
static
XML_Memory_Handling_Suite ms = {mymalloc, myrealloc, myfree};
static
void
append_error(XML_Parser parser,
char
* err)
{
dSP;
CallbackVector * cbv;
SV ** errstr;
cbv = (CallbackVector*) XML_GetUserData(parser);
errstr = hv_fetch((HV*)SvRV(cbv->self_sv),
"ErrorMessage"
, 12, 0);
if
(errstr && SvPOK(*errstr)) {
SV ** errctx = hv_fetch((HV*) SvRV(cbv->self_sv),
"ErrorContext"
, 12, 0);
int
dopos = !err && errctx && SvOK(*errctx);
if
(! err)
err = (
char
*) XML_ErrorString(XML_GetErrorCode(parser));
sv_catpvf(*errstr,
"\n%s at line %d, column %d, byte %d%s"
,
err,
XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser),
XML_GetCurrentByteIndex(parser),
dopos ?
":\n"
:
""
);
if
(dopos)
{
int
count;
ENTER ;
SAVETMPS ;
PUSHMARK(sp);
XPUSHs(cbv->self_sv);
XPUSHs(*errctx);
PUTBACK ;
count = perl_call_method(
"position_in_context"
, G_SCALAR);
SPAGAIN ;
if
(count >= 1) {
sv_catsv(*errstr, POPs);
}
PUTBACK ;
FREETMPS ;
LEAVE ;
}
}
}
static
SV *
generate_model(XML_Content *model) {
HV * hash = newHV();
SV * obj = newRV_noinc((SV *) hash);
sv_bless(obj, gv_stashpv(
"XML::Parser::ContentModel"
, 1));
hv_store(hash,
"Type"
, 4, newSViv(model->type), 0);
if
(model->quant != XML_CQUANT_NONE) {
hv_store(hash,
"Quant"
, 5, newSVpv(QuantChar[model->quant], 1), 0);
}
switch
(model->type) {
case
XML_CTYPE_NAME:
hv_store(hash,
"Tag"
, 3, newSVpv((
char
*)model->name, 0), 0);
break
;
case
XML_CTYPE_MIXED:
case
XML_CTYPE_CHOICE:
case
XML_CTYPE_SEQ:
if
(model->children && model->numchildren)
{
AV * children = newAV();
int
i;
for
(i = 0; i < model->numchildren; i++) {
av_push(children, generate_model(&model->children[i]));
}
hv_store(hash,
"Children"
, 8, newRV_noinc((SV *) children), 0);
}
break
;
}
return
obj;
}
static
int
parse_stream(XML_Parser parser, SV * ioref)
{
dSP;
SV * tbuff;
SV * tsiz;
char
* linebuff;
STRLEN lblen;
STRLEN br = 0;
int
buffsize;
int
done = 0;
int
ret = 1;
char
* msg = NULL;
CallbackVector * cbv;
char
*buff = (
char
*) 0;
cbv = (CallbackVector*) XML_GetUserData(parser);
ENTER;
SAVETMPS;
if
(cbv->delim) {
int
cnt;
SV * tline;
PUSHMARK(SP);
XPUSHs(ioref);
PUTBACK ;
cnt = perl_call_method(
"getline"
, G_SCALAR);
SPAGAIN;
if
(cnt != 1)
croak(
"getline method call failed"
);
tline = POPs;
if
(! SvOK(tline)) {
lblen = 0;
}
else
{
char
* chk;
linebuff = SvPV(tline, lblen);
chk = &linebuff[lblen - cbv->delimlen - 1];
if
(lblen > cbv->delimlen + 1
&& *chk == *cbv->delim
&& chk[cbv->delimlen] ==
'\n'
&& strnEQ(++chk, cbv->delim + 1, cbv->delimlen - 1))
lblen -= cbv->delimlen + 1;
}
PUTBACK ;
buffsize = lblen;
done = lblen == 0;
}
else
{
tbuff = newSV(0);
tsiz = newSViv(BUFSIZE);
buffsize = BUFSIZE;
}
while
(! done)
{
char
*buffer = XML_GetBuffer(parser, buffsize);
if
(! buffer)
croak(
"Ran out of memory for input buffer"
);
SAVETMPS;
if
(cbv->delim) {
Copy(linebuff, buffer, lblen,
char
);
br = lblen;
done = 1;
}
else
{
int
cnt;
SV * rdres;
char
* tb;
PUSHMARK(SP);
EXTEND(SP, 3);
PUSHs(ioref);
PUSHs(tbuff);
PUSHs(tsiz);
PUTBACK ;
cnt = perl_call_method(
"read"
, G_SCALAR);
SPAGAIN ;
if
(cnt != 1)
croak(
"read method call failed"
);
rdres = POPs;
if
(! SvOK(rdres))
croak(
"read error"
);
tb = SvPV(tbuff, br);
if
(br > 0)
Copy(tb, buffer, br,
char
);
else
done = 1;
PUTBACK ;
}
ret = XML_ParseBuffer(parser, br, done);
SPAGAIN;
if
(! ret)
break
;
FREETMPS;
}
if
(! ret)
append_error(parser, msg);
if
(! cbv->delim) {
SvREFCNT_dec(tsiz);
SvREFCNT_dec(tbuff);
}
FREETMPS;
LEAVE;
return
ret;
}
static
SV *
gen_ns_name(
const
char
* name, HV * ns_table, AV * ns_list)
{
char
*pos =
strchr
(name, NSDELIM);
SV * ret;
if
(pos && pos > name)
{
SV ** name_ent = hv_fetch(ns_table, (
char
*) name,
pos - name, TRUE);
ret = newUTF8SVpv(&pos[1], 0);
if
(name_ent)
{
int
index;
if
(SvOK(*name_ent))
{
index = SvIV(*name_ent);
}
else
{
av_push(ns_list, newUTF8SVpv((
char
*) name, pos - name));
index = av_len(ns_list);
sv_setiv(*name_ent, (IV) index);
}
sv_setiv(ret, (IV) index);
SvPOK_on(ret);
}
}
else
ret = newUTF8SVpv((
char
*) name, 0);
return
ret;
}
static
void
characterData(
void
*userData,
const
char
*s,
int
len)
{
dSP;
CallbackVector* cbv = (CallbackVector*) userData;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 2);
PUSHs(cbv->self_sv);
PUSHs(sv_2mortal(newUTF8SVpvn((
char
*)s,len)));
PUTBACK;
perl_call_sv(cbv->char_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
startElement(
void
*userData,
const
char
*name,
const
char
**atts)
{
dSP;
CallbackVector* cbv = (CallbackVector*) userData;
SV ** pcontext;
unsigned do_ns = cbv->ns;
unsigned skipping = 0;
SV ** pnstab;
SV ** pnslst;
SV * elname;
cbv->st_serial++;
if
(cbv->skip_until) {
skipping = cbv->st_serial < cbv->skip_until;
if
(! skipping) {
resume_callbacks(cbv);
cbv->skip_until = 0;
}
}
if
(cbv->st_serial_stackptr >= cbv->st_serial_stacksize) {
unsigned
int
newsize = cbv->st_serial_stacksize + 512;
Renew(cbv->st_serial_stack, newsize, unsigned
int
);
cbv->st_serial_stacksize = newsize;
}
cbv->st_serial_stack[++cbv->st_serial_stackptr] = cbv->st_serial;
if
(do_ns)
elname = gen_ns_name(name, cbv->nstab, cbv->nslst);
else
elname = newUTF8SVpv((
char
*)name, 0);
if
(! skipping && SvTRUE(cbv->start_sv))
{
const
char
**attlim = atts;
while
(*attlim)
attlim++;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, attlim - atts + 2);
PUSHs(cbv->self_sv);
PUSHs(elname);
while
(*atts)
{
SV * attname;
attname = (do_ns ? gen_ns_name(*atts, cbv->nstab, cbv->nslst)
: newUTF8SVpv((
char
*) *atts, 0));
atts++;
PUSHs(sv_2mortal(attname));
if
(*atts)
PUSHs(sv_2mortal(newUTF8SVpv((
char
*)*atts++,0)));
}
PUTBACK;
perl_call_sv(cbv->start_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
av_push(cbv->context, elname);
if
(cbv->ns) {
av_clear(cbv->new_prefix_list);
}
}
static
void
endElement(
void
*userData,
const
char
*name)
{
dSP;
CallbackVector* cbv = (CallbackVector*) userData;
SV *elname;
elname = av_pop(cbv->context);
if
(! cbv->st_serial_stackptr) {
croak(
"endElement: Start tag serial number stack underflow"
);
}
if
(! cbv->skip_until && SvTRUE(cbv->end_sv))
{
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 2);
PUSHs(cbv->self_sv);
PUSHs(elname);
PUTBACK;
perl_call_sv(cbv->end_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
cbv->st_serial_stackptr--;
SvREFCNT_dec(elname);
}
static
void
processingInstruction(
void
*userData,
const
char
*target,
const
char
*data)
{
dSP;
CallbackVector* cbv = (CallbackVector*) userData;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 3);
PUSHs(cbv->self_sv);
PUSHs(sv_2mortal(newUTF8SVpv((
char
*)target,0)));
PUSHs(sv_2mortal(newUTF8SVpv((
char
*)data,0)));
PUTBACK;
perl_call_sv(cbv->proc_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
commenthandle(
void
*userData,
const
char
*string)
{
dSP;
CallbackVector * cbv = (CallbackVector*) userData;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 2);
PUSHs(cbv->self_sv);
PUSHs(sv_2mortal(newUTF8SVpv((
char
*) string, 0)));
PUTBACK;
perl_call_sv(cbv->cmnt_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
startCdata(
void
*userData)
{
dSP;
CallbackVector* cbv = (CallbackVector*) userData;
if
(cbv->startcd_sv) {
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(cbv->self_sv);
PUTBACK;
perl_call_sv(cbv->startcd_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
}
static
void
endCdata(
void
*userData)
{
dSP;
CallbackVector* cbv = (CallbackVector*) userData;
if
(cbv->endcd_sv) {
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(cbv->self_sv);
PUTBACK;
perl_call_sv(cbv->endcd_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
}
static
void
nsStart(
void
*userdata,
const
XML_Char *prefix,
const
XML_Char *uri){
dSP;
CallbackVector* cbv = (CallbackVector*) userdata;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 3);
PUSHs(cbv->self_sv);
PUSHs(prefix ? sv_2mortal(newUTF8SVpv((
char
*)prefix, 0)) : &PL_sv_undef);
PUSHs(uri ? sv_2mortal(newUTF8SVpv((
char
*)uri, 0)) : &PL_sv_undef);
PUTBACK;
perl_call_method(
"NamespaceStart"
, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
nsEnd(
void
*userdata,
const
XML_Char *prefix) {
dSP;
CallbackVector* cbv = (CallbackVector*) userdata;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 2);
PUSHs(cbv->self_sv);
PUSHs(prefix ? sv_2mortal(newUTF8SVpv((
char
*)prefix, 0)) : &PL_sv_undef);
PUTBACK;
perl_call_method(
"NamespaceEnd"
, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
defaulthandle(
void
*userData,
const
char
*string,
int
len)
{
dSP;
CallbackVector* cbv = (CallbackVector*) userData;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 2);
PUSHs(cbv->self_sv);
PUSHs(sv_2mortal(newUTF8SVpvn((
char
*)string, len)));
PUTBACK;
perl_call_sv(cbv->dflt_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
elementDecl(
void
*data,
const
char
*name,
XML_Content *model) {
dSP;
CallbackVector *cbv = (CallbackVector*) data;
SV *cmod;
ENTER;
SAVETMPS;
cmod = generate_model(model);
Safefree(model);
PUSHMARK(sp);
EXTEND(sp, 3);
PUSHs(cbv->self_sv);
PUSHs(sv_2mortal(newUTF8SVpv((
char
*)name, 0)));
PUSHs(sv_2mortal(cmod));
PUTBACK;
perl_call_sv(cbv->eledcl_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
attributeDecl(
void
*data,
const
char
* elname,
const
char
* attname,
const
char
* att_type,
const
char
* dflt,
int
reqorfix) {
dSP;
CallbackVector *cbv = (CallbackVector*) data;
SV * dfltsv;
if
(dflt) {
dfltsv = newUTF8SVpv(
"'"
, 1);
sv_catpv(dfltsv, (
char
*) dflt);
sv_catpv(dfltsv,
"'"
);
}
else
{
dfltsv = newUTF8SVpv(reqorfix ?
"#REQUIRED"
:
"#IMPLIED"
, 0);
}
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 5);
PUSHs(cbv->self_sv);
PUSHs(sv_2mortal(newUTF8SVpv((
char
*)elname, 0)));
PUSHs(sv_2mortal(newUTF8SVpv((
char
*)attname, 0)));
PUSHs(sv_2mortal(newUTF8SVpv((
char
*)att_type, 0)));
PUSHs(sv_2mortal(dfltsv));
if
(dflt && reqorfix)
XPUSHs(&PL_sv_yes);
PUTBACK;
perl_call_sv(cbv->attdcl_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
entityDecl(
void
*data,
const
char
*name,
int
isparam,
const
char
*value,
int
vlen,
const
char
*base,
const
char
*sysid,
const
char
*pubid,
const
char
*notation) {
dSP;
CallbackVector *cbv = (CallbackVector*) data;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 6);
PUSHs(cbv->self_sv);
PUSHs(sv_2mortal(newUTF8SVpv((
char
*)name, 0)));
PUSHs(value ? sv_2mortal(newUTF8SVpvn((
char
*)value, vlen)) : &PL_sv_undef);
PUSHs(sysid ? sv_2mortal(newUTF8SVpv((
char
*)sysid, 0)) : &PL_sv_undef);
PUSHs(pubid ? sv_2mortal(newUTF8SVpv((
char
*)pubid, 0)) : &PL_sv_undef);
PUSHs(notation ? sv_2mortal(newUTF8SVpv((
char
*)notation, 0)) : &PL_sv_undef);
if
(isparam)
XPUSHs(&PL_sv_yes);
PUTBACK;
perl_call_sv(cbv->entdcl_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
doctypeStart(
void
*userData,
const
char
* name,
const
char
* sysid,
const
char
* pubid,
int
hasinternal) {
dSP;
CallbackVector *cbv = (CallbackVector*) userData;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 5);
PUSHs(cbv->self_sv);
PUSHs(sv_2mortal(newUTF8SVpv((
char
*)name, 0)));
PUSHs(sysid ? sv_2mortal(newUTF8SVpv((
char
*)sysid, 0)) : &PL_sv_undef);
PUSHs(pubid ? sv_2mortal(newUTF8SVpv((
char
*)pubid, 0)) : &PL_sv_undef);
PUSHs(hasinternal ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
perl_call_sv(cbv->doctyp_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
doctypeEnd(
void
*userData) {
dSP;
CallbackVector *cbv = (CallbackVector*) userData;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 1);
PUSHs(cbv->self_sv);
PUTBACK;
perl_call_sv(cbv->doctypfin_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
xmlDecl(
void
*userData,
const
char
*version,
const
char
*encoding,
int
standalone) {
dSP;
CallbackVector *cbv = (CallbackVector*) userData;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 4);
PUSHs(cbv->self_sv);
PUSHs(version ? sv_2mortal(newUTF8SVpv((
char
*)version, 0))
: &PL_sv_undef);
PUSHs(encoding ? sv_2mortal(newUTF8SVpv((
char
*)encoding, 0))
: &PL_sv_undef);
PUSHs(standalone == -1 ? &PL_sv_undef
: (standalone ? &PL_sv_yes : &PL_sv_no));
PUTBACK;
perl_call_sv(cbv->xmldec_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
unparsedEntityDecl(
void
*userData,
const
char
* entity,
const
char
* base,
const
char
* sysid,
const
char
* pubid,
const
char
* notation)
{
dSP;
CallbackVector* cbv = (CallbackVector*) userData;
ENTER;
SAVETMPS;
PUSHMARK(sp);
EXTEND(sp, 6);
PUSHs(cbv->self_sv);
PUSHs(sv_2mortal(newUTF8SVpv((
char
*) entity, 0)));
PUSHs(base ? sv_2mortal(newUTF8SVpv((
char
*) base, 0)) : &PL_sv_undef);
PUSHs(sv_2mortal(newUTF8SVpv((
char
*) sysid, 0)));
PUSHs(pubid ? sv_2mortal(newUTF8SVpv((
char
*) pubid, 0)) : &PL_sv_undef);
PUSHs(sv_2mortal(newUTF8SVpv((
char
*) notation, 0)));
PUTBACK;
perl_call_sv(cbv->unprsd_sv, G_DISCARD);
FREETMPS;
LEAVE;
}
static
void
notationDecl(
void
*userData,
const
char
*name,
const
char
*base,
const
char
*sysid,
const
char
*pubid)
{
dSP;
CallbackVector* cbv = (CallbackVector*) userData;
PUSHMARK(sp);
XPUSHs(cbv->self_sv);
XPUSHs(sv_2mortal(newUTF8SVpv((
char
*) name, 0)));
if
(base)
{
XPUSHs(sv_2mortal(newUTF8SVpv((
char
*) base, 0)));
}
else
if
(sysid || pubid)
{
XPUSHs(&PL_sv_undef);
}
if
(sysid)
{
XPUSHs(sv_2mortal(newUTF8SVpv((
char
*) sysid, 0)));
}
else
if
(pubid)
{
XPUSHs(&PL_sv_undef);
}
if
(pubid)
XPUSHs(sv_2mortal(newUTF8SVpv((
char
*) pubid, 0)));
PUTBACK;
perl_call_sv(cbv->notation_sv, G_DISCARD);
}
static
int
externalEntityRef(XML_Parser parser,
const
char
* open,
const
char
* base,
const
char
* sysid,
const
char
* pubid)
{
dSP;
#if defined(USE_THREADS) && PATCHLEVEL==6
dTHX;
#endif
int
count;
int
ret = 0;
int
parse_done = 0;
CallbackVector* cbv = (CallbackVector*) XML_GetUserData(parser);
if
(! cbv->extent_sv)
return
0;
ENTER ;
SAVETMPS ;
PUSHMARK(sp);
EXTEND(sp, pubid ? 4 : 3);
PUSHs(cbv->self_sv);
PUSHs(base ? sv_2mortal(newUTF8SVpv((
char
*) base, 0)) : &PL_sv_undef);
PUSHs(sv_2mortal(newSVpv((
char
*) sysid, 0)));
if
(pubid)
PUSHs(sv_2mortal(newUTF8SVpv((
char
*) pubid, 0)));
PUTBACK ;
count = perl_call_sv(cbv->extent_sv, G_SCALAR);
SPAGAIN ;
if
(count >= 1) {
SV * result = POPs;
int
type;
if
(result && (type = SvTYPE(result)) > 0) {
SV **pval = hv_fetch((HV*) SvRV(cbv->self_sv),
"Parser"
, 6, 0);
if
(! pval || ! SvIOK(*pval))
append_error(parser,
"Can't find parser entry in XML::Parser object"
);
else
{
XML_Parser entpar;
char
*errmsg = (
char
*) 0;
entpar = XML_ExternalEntityParserCreate(parser, open, 0);
XML_SetBase(entpar, XML_GetBase(parser));
sv_setiv(*pval, (IV) entpar);
cbv->p = entpar;
PUSHMARK(sp);
EXTEND(sp, 2);
PUSHs(*pval);
PUSHs(result);
PUTBACK;
count = perl_call_pv(
"XML::Parser::Expat::Do_External_Parse"
,
G_SCALAR | G_EVAL);
SPAGAIN;
if
(SvTRUE(ERRSV)) {
char
*hold;
int
len;
POPs;
hold = SvPV(ERRSV, len);
New(326, errmsg, len + 1,
char
);
if
(len)
Copy(hold, errmsg, len,
char
);
goto
Extparse_Cleanup;
}
if
(count > 0)
ret = POPi;
parse_done = 1;
Extparse_Cleanup:
cbv->p = parser;
sv_setiv(*pval, (IV) parser);
XML_ParserFree(entpar);
if
(cbv->extfin_sv) {
PUSHMARK(sp);
PUSHs(cbv->self_sv);
PUTBACK;
perl_call_sv(cbv->extfin_sv, G_DISCARD);
SPAGAIN;
}
if
(SvTRUE(ERRSV))
append_error(parser, SvPV(ERRSV, PL_na));
}
}
}
if
(! ret && ! parse_done)
append_error(parser,
"Handler couldn't resolve external entity"
);
PUTBACK ;
FREETMPS ;
LEAVE ;
return
ret;
}
static
int
convert_to_unicode(
void
*data,
const
char
*seq) {
Encinfo *enc = (Encinfo *) data;
PrefixMap *curpfx;
int
count;
int
index = 0;
for
(count = 0; count < 4; count++) {
unsigned
char
byte = (unsigned
char
) seq[count];
unsigned
char
bndx;
unsigned
char
bmsk;
int
offset;
curpfx = &enc->prefixes[index];
offset = ((
int
) byte) - curpfx->min;
if
(offset < 0)
break
;
if
(offset >= curpfx->len && curpfx->len != 0)
break
;
bndx = byte >> 3;
bmsk = 1 << (byte & 0x7);
if
(curpfx->ispfx[bndx] & bmsk) {
index = enc->bytemap[curpfx->bmap_start + offset];
}
else
if
(curpfx->ischar[bndx] & bmsk) {
return
enc->bytemap[curpfx->bmap_start + offset];
}
else
break
;
}
return
-1;
}
static
int
unknownEncoding(
void
*unused,
const
char
*name, XML_Encoding *info)
{
SV ** encinfptr;
Encinfo *enc;
int
namelen;
int
i;
char
buff[42];
namelen =
strlen
(name);
if
(namelen > 40)
return
0;
for
(i = 0; i < namelen; i++) {
char
c = name[i];
if
(c >=
'a'
&& c <=
'z'
)
c -=
'a'
-
'A'
;
buff[i] = c;
}
if
(! EncodingTable) {
EncodingTable = perl_get_hv(
"XML::Parser::Expat::Encoding_Table"
, FALSE);
if
(! EncodingTable)
croak(
"Can't find XML::Parser::Expat::Encoding_Table"
);
}
encinfptr = hv_fetch(EncodingTable, buff, namelen, 0);
if
(! encinfptr || ! SvOK(*encinfptr)) {
dSP;
int
count;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSVpvn(buff,namelen)));
PUTBACK;
perl_call_pv(
"XML::Parser::Expat::load_encoding"
, G_DISCARD);
encinfptr = hv_fetch(EncodingTable, buff, namelen, 0);
FREETMPS;
LEAVE;
if
(! encinfptr || ! SvOK(*encinfptr))
return
0;
}
if
(! sv_derived_from(*encinfptr,
"XML::Parser::Encinfo"
))
croak(
"Entry in XML::Parser::Expat::Encoding_Table not an Encinfo object"
);
enc = (Encinfo *) SvIV((SV*)SvRV(*encinfptr));
Copy(enc->firstmap, info->map, 256,
int
);
info->release = NULL;
if
(enc->prefixes_size) {
info->data = (
void
*) enc;
info->convert = convert_to_unicode;
}
else
{
info->data = NULL;
info->convert = NULL;
}
return
1;
}
static
void
recString(
void
*userData,
const
char
*string,
int
len)
{
CallbackVector *cbv = (CallbackVector*) userData;
if
(cbv->recstring) {
sv_catpvn(cbv->recstring, (
char
*) string, len);
}
else
{
cbv->recstring = newUTF8SVpvn((
char
*) string, len);
}
}
static
void
suspend_callbacks(CallbackVector *cbv) {
if
(SvTRUE(cbv->char_sv)) {
XML_SetCharacterDataHandler(cbv->p,
(XML_CharacterDataHandler) 0);
}
if
(SvTRUE(cbv->proc_sv)) {
XML_SetProcessingInstructionHandler(cbv->p,
(XML_ProcessingInstructionHandler) 0);
}
if
(SvTRUE(cbv->cmnt_sv)) {
XML_SetCommentHandler(cbv->p,
(XML_CommentHandler) 0);
}
if
(SvTRUE(cbv->startcd_sv)
|| SvTRUE(cbv->endcd_sv)) {
XML_SetCdataSectionHandler(cbv->p,
(XML_StartCdataSectionHandler) 0,
(XML_EndCdataSectionHandler) 0);
}
if
(SvTRUE(cbv->unprsd_sv)) {
XML_SetUnparsedEntityDeclHandler(cbv->p,
(XML_UnparsedEntityDeclHandler) 0);
}
if
(SvTRUE(cbv->notation_sv)) {
XML_SetNotationDeclHandler(cbv->p,
(XML_NotationDeclHandler) 0);
}
if
(SvTRUE(cbv->extent_sv)) {
XML_SetExternalEntityRefHandler(cbv->p,
(XML_ExternalEntityRefHandler) 0);
}
}
static
void
resume_callbacks(CallbackVector *cbv) {
if
(SvTRUE(cbv->char_sv)) {
XML_SetCharacterDataHandler(cbv->p, characterData);
}
if
(SvTRUE(cbv->proc_sv)) {
XML_SetProcessingInstructionHandler(cbv->p, processingInstruction);
}
if
(SvTRUE(cbv->cmnt_sv)) {
XML_SetCommentHandler(cbv->p, commenthandle);
}
if
(SvTRUE(cbv->startcd_sv)
|| SvTRUE(cbv->endcd_sv)) {
XML_SetCdataSectionHandler(cbv->p, startCdata, endCdata);
}
if
(SvTRUE(cbv->unprsd_sv)) {
XML_SetUnparsedEntityDeclHandler(cbv->p, unparsedEntityDecl);
}
if
(SvTRUE(cbv->notation_sv)) {
XML_SetNotationDeclHandler(cbv->p, notationDecl);
}
if
(SvTRUE(cbv->extent_sv)) {
XML_SetExternalEntityRefHandler(cbv->p, externalEntityRef);
}
}
MODULE = XML::Parser::Expat PACKAGE = XML::Parser::Expat PREFIX = XML_
XML_Parser
XML_ParserCreate(self_sv, enc_sv, namespaces)
SV * self_sv
SV * enc_sv
int
namespaces
CODE:
{
CallbackVector *cbv;
enum
XML_ParamEntityParsing pep = XML_PARAM_ENTITY_PARSING_NEVER;
char
*enc = (
char
*) (SvTRUE(enc_sv) ? SvPV(enc_sv,PL_na) : 0);
SV ** spp;
Newz(320, cbv, 1, CallbackVector);
cbv->self_sv = SvREFCNT_inc(self_sv);
Newz(325, cbv->st_serial_stack, 1024, unsigned
int
);
spp = hv_fetch((HV*)SvRV(cbv->self_sv),
"NoExpand"
, 8, 0);
if
(spp && SvTRUE(*spp))
cbv->no_expand = 1;
spp = hv_fetch((HV*)SvRV(cbv->self_sv),
"Context"
, 7, 0);
if
(! spp || ! *spp || !SvROK(*spp))
croak(
"XML::Parser instance missing Context"
);
cbv->context = (AV*) SvRV(*spp);
cbv->ns = (unsigned) namespaces;
if
(namespaces)
{
spp = hv_fetch((HV*)SvRV(cbv->self_sv),
"New_Prefixes"
, 12, 0);
if
(! spp || ! *spp || !SvROK(*spp))
croak(
"XML::Parser instance missing New_Prefixes"
);
cbv->new_prefix_list = (AV *) SvRV(*spp);
spp = hv_fetch((HV*)SvRV(cbv->self_sv),
"Namespace_Table"
,
15, FALSE);
if
(! spp || ! *spp || !SvROK(*spp))
croak(
"XML::Parser instance missing Namespace_Table"
);
cbv->nstab = (HV *) SvRV(*spp);
spp = hv_fetch((HV*)SvRV(cbv->self_sv),
"Namespace_List"
,
14, FALSE);
if
(! spp || ! *spp || !SvROK(*spp))
croak(
"XML::Parser instance missing Namespace_List"
);
cbv->nslst = (AV *) SvRV(*spp);
RETVAL = XML_ParserCreate_MM(enc, &ms, nsdelim);
XML_SetNamespaceDeclHandler(RETVAL,nsStart, nsEnd);
}
else
{
RETVAL = XML_ParserCreate_MM(enc, &ms, NULL);
}
cbv->p = RETVAL;
XML_SetUserData(RETVAL, (
void
*) cbv);
XML_SetElementHandler(RETVAL, startElement, endElement);
XML_SetUnknownEncodingHandler(RETVAL, unknownEncoding, 0);
spp = hv_fetch((HV*)SvRV(cbv->self_sv),
"ParseParamEnt"
,
13, FALSE);
if
(spp && SvTRUE(*spp)) {
pep = XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE;
cbv->parseparam = 1;
}
XML_SetParamEntityParsing(RETVAL, pep);
}
OUTPUT:
RETVAL
void
XML_ParserRelease(parser)
XML_Parser parser
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
SvREFCNT_dec(cbv->self_sv);
}
void
XML_ParserFree(parser)
XML_Parser parser
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
Safefree(cbv->st_serial_stack);
if
(cbv->recstring)
SvREFCNT_dec(cbv->recstring);
if
(cbv->start_sv)
SvREFCNT_dec(cbv->start_sv);
if
(cbv->end_sv)
SvREFCNT_dec(cbv->end_sv);
if
(cbv->char_sv)
SvREFCNT_dec(cbv->char_sv);
if
(cbv->proc_sv)
SvREFCNT_dec(cbv->proc_sv);
if
(cbv->cmnt_sv)
SvREFCNT_dec(cbv->cmnt_sv);
if
(cbv->dflt_sv)
SvREFCNT_dec(cbv->dflt_sv);
if
(cbv->entdcl_sv)
SvREFCNT_dec(cbv->entdcl_sv);
if
(cbv->eledcl_sv)
SvREFCNT_dec(cbv->eledcl_sv);
if
(cbv->attdcl_sv)
SvREFCNT_dec(cbv->attdcl_sv);
if
(cbv->doctyp_sv)
SvREFCNT_dec(cbv->doctyp_sv);
if
(cbv->doctypfin_sv)
SvREFCNT_dec(cbv->doctypfin_sv);
if
(cbv->xmldec_sv)
SvREFCNT_dec(cbv->xmldec_sv);
if
(cbv->unprsd_sv)
SvREFCNT_dec(cbv->unprsd_sv);
if
(cbv->notation_sv)
SvREFCNT_dec(cbv->notation_sv);
if
(cbv->extent_sv)
SvREFCNT_dec(cbv->extent_sv);
if
(cbv->extfin_sv)
SvREFCNT_dec(cbv->extfin_sv);
if
(cbv->startcd_sv)
SvREFCNT_dec(cbv->startcd_sv);
if
(cbv->endcd_sv)
SvREFCNT_dec(cbv->endcd_sv);
Safefree(cbv);
XML_ParserFree(parser);
}
int
XML_ParseString(parser, s)
XML_Parser parser
char
* s
int
len = PL_na;
CODE:
{
CallbackVector * cbv;
cbv = (CallbackVector *) XML_GetUserData(parser);
RETVAL = XML_Parse(parser, s, len, 1);
SPAGAIN;
if
(! RETVAL)
append_error(parser, NULL);
}
OUTPUT:
RETVAL
int
XML_ParseStream(parser, ioref, delim)
XML_Parser parser
SV * ioref
SV * delim
CODE:
{
SV **delimsv;
CallbackVector * cbv;
cbv = (CallbackVector *) XML_GetUserData(parser);
if
(SvOK(delim)) {
cbv->delim = SvPV(delim, cbv->delimlen);
}
else
{
cbv->delim = (
char
*) 0;
}
RETVAL = parse_stream(parser, ioref);
SPAGAIN;
}
OUTPUT:
RETVAL
int
XML_ParsePartial(parser, s)
XML_Parser parser
char
* s
int
len = PL_na;
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
RETVAL = XML_Parse(parser, s, len, 0);
if
(! RETVAL)
append_error(parser, NULL);
}
OUTPUT:
RETVAL
int
XML_ParseDone(parser)
XML_Parser parser
CODE:
{
RETVAL = XML_Parse(parser,
""
, 0, 1);
if
(! RETVAL)
append_error(parser, NULL);
}
OUTPUT:
RETVAL
SV *
XML_SetStartElementHandler(parser, start_sv)
XML_Parser parser
SV * start_sv
CODE:
{
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(start_sv);
PUSHRET;
}
SV *
XML_SetEndElementHandler(parser, end_sv)
XML_Parser parser
SV * end_sv
CODE:
{
CallbackVector *cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(end_sv);
PUSHRET;
}
SV *
XML_SetCharacterDataHandler(parser, char_sv)
XML_Parser parser
SV * char_sv
CODE:
{
XML_CharacterDataHandler charhndl = (XML_CharacterDataHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(char_sv);
if
(SvTRUE(char_sv))
charhndl = characterData;
XML_SetCharacterDataHandler(parser, charhndl);
PUSHRET;
}
SV *
XML_SetProcessingInstructionHandler(parser, proc_sv)
XML_Parser parser
SV * proc_sv
CODE:
{
XML_ProcessingInstructionHandler prochndl =
(XML_ProcessingInstructionHandler) 0;
CallbackVector* cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(proc_sv);
if
(SvTRUE(proc_sv))
prochndl = processingInstruction;
XML_SetProcessingInstructionHandler(parser, prochndl);
PUSHRET;
}
SV *
XML_SetCommentHandler(parser, cmnt_sv)
XML_Parser parser
SV * cmnt_sv
CODE:
{
XML_CommentHandler cmnthndl = (XML_CommentHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(cmnt_sv);
if
(SvTRUE(cmnt_sv))
cmnthndl = commenthandle;
XML_SetCommentHandler(parser, cmnthndl);
PUSHRET;
}
SV *
XML_SetDefaultHandler(parser, dflt_sv)
XML_Parser parser
SV * dflt_sv
CODE:
{
XML_DefaultHandler dflthndl = (XML_DefaultHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(dflt_sv);
if
(SvTRUE(dflt_sv))
dflthndl = defaulthandle;
if
(cbv->no_expand)
XML_SetDefaultHandler(parser, dflthndl);
else
XML_SetDefaultHandlerExpand(parser, dflthndl);
PUSHRET;
}
SV *
XML_SetUnparsedEntityDeclHandler(parser, unprsd_sv)
XML_Parser parser
SV * unprsd_sv
CODE:
{
XML_UnparsedEntityDeclHandler unprsdhndl =
(XML_UnparsedEntityDeclHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(unprsd_sv);
if
(SvTRUE(unprsd_sv))
unprsdhndl = unparsedEntityDecl;
XML_SetUnparsedEntityDeclHandler(parser, unprsdhndl);
PUSHRET;
}
SV *
XML_SetNotationDeclHandler(parser, notation_sv)
XML_Parser parser
SV * notation_sv
CODE:
{
XML_NotationDeclHandler nothndlr = (XML_NotationDeclHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(notation_sv);
if
(SvTRUE(notation_sv))
nothndlr = notationDecl;
XML_SetNotationDeclHandler(parser, nothndlr);
PUSHRET;
}
SV *
XML_SetExternalEntityRefHandler(parser, extent_sv)
XML_Parser parser
SV * extent_sv
CODE:
{
XML_ExternalEntityRefHandler exthndlr =
(XML_ExternalEntityRefHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(extent_sv);
if
(SvTRUE(extent_sv))
exthndlr = externalEntityRef;
XML_SetExternalEntityRefHandler(parser, exthndlr);
PUSHRET;
}
SV *
XML_SetExtEntFinishHandler(parser, extfin_sv)
XML_Parser parser
SV * extfin_sv
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
XMLP_UPD(extfin_sv);
PUSHRET;
}
SV *
XML_SetEntityDeclHandler(parser, entdcl_sv)
XML_Parser parser
SV * entdcl_sv
CODE:
{
XML_EntityDeclHandler enthndlr =
(XML_EntityDeclHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(entdcl_sv);
if
(SvTRUE(entdcl_sv))
enthndlr = entityDecl;
XML_SetEntityDeclHandler(parser, enthndlr);
PUSHRET;
}
SV *
XML_SetElementDeclHandler(parser, eledcl_sv)
XML_Parser parser
SV * eledcl_sv
CODE:
{
XML_ElementDeclHandler eldeclhndlr =
(XML_ElementDeclHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(eledcl_sv);
if
(SvTRUE(eledcl_sv))
eldeclhndlr = elementDecl;
XML_SetElementDeclHandler(parser, eldeclhndlr);
PUSHRET;
}
SV *
XML_SetAttListDeclHandler(parser, attdcl_sv)
XML_Parser parser
SV * attdcl_sv
CODE:
{
XML_AttlistDeclHandler attdeclhndlr =
(XML_AttlistDeclHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(attdcl_sv);
if
(SvTRUE(attdcl_sv))
attdeclhndlr = attributeDecl;
XML_SetAttlistDeclHandler(parser, attdeclhndlr);
PUSHRET;
}
SV *
XML_SetDoctypeHandler(parser, doctyp_sv)
XML_Parser parser
SV * doctyp_sv
CODE:
{
XML_StartDoctypeDeclHandler dtsthndlr =
(XML_StartDoctypeDeclHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
int
set = 0;
XMLP_UPD(doctyp_sv);
if
(SvTRUE(doctyp_sv))
dtsthndlr = doctypeStart;
XML_SetStartDoctypeDeclHandler(parser, dtsthndlr);
PUSHRET;
}
SV *
XML_SetEndDoctypeHandler(parser, doctypfin_sv)
XML_Parser parser
SV * doctypfin_sv
CODE:
{
XML_EndDoctypeDeclHandler dtendhndlr =
(XML_EndDoctypeDeclHandler) 0;
CallbackVector * cbv = (CallbackVector*) XML_GetUserData(parser);
XMLP_UPD(doctypfin_sv);
if
(SvTRUE(doctypfin_sv))
dtendhndlr = doctypeEnd;
XML_SetEndDoctypeDeclHandler(parser, dtendhndlr);
PUSHRET;
}
SV *
XML_SetXMLDeclHandler(parser, xmldec_sv)
XML_Parser parser
SV * xmldec_sv
CODE:
{
XML_XmlDeclHandler xmldechndlr =
(XML_XmlDeclHandler) 0;
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
XMLP_UPD(xmldec_sv);
if
(SvTRUE(xmldec_sv))
xmldechndlr = xmlDecl;
XML_SetXmlDeclHandler(parser, xmldechndlr);
PUSHRET;
}
void
XML_SetBase(parser, base)
XML_Parser parser
SV * base
CODE:
{
char
* b;
if
(! SvOK(base)) {
b = (
char
*) 0;
}
else
{
b = SvPV(base, PL_na);
}
XML_SetBase(parser, b);
}
SV *
XML_GetBase(parser)
XML_Parser parser
CODE:
{
const
char
*ret = XML_GetBase(parser);
if
(ret) {
ST(0) = sv_newmortal();
sv_setpv(ST(0), ret);
}
else
{
ST(0) = &PL_sv_undef;
}
}
void
XML_PositionContext(parser, lines)
XML_Parser parser
int
lines
PREINIT:
int
parsepos;
int
size;
const
char
*pos = XML_GetInputContext(parser, &parsepos, &size);
const
char
*markbeg;
const
char
*limit;
const
char
*markend;
int
length, relpos;
int
cnt;
PPCODE:
if
(! pos)
return
;
for
(markbeg = &pos[parsepos], cnt = 0; markbeg >= pos; markbeg--)
{
if
(*markbeg ==
'\n'
)
{
cnt++;
if
(cnt > lines)
break
;
}
}
markbeg++;
relpos = 0;
limit = &pos[size];
for
(markend = &pos[parsepos + 1], cnt = 0;
markend < limit;
markend++)
{
if
(*markend ==
'\n'
)
{
if
(cnt == 0)
relpos = (markend - markbeg) + 1;
cnt++;
if
(cnt > lines)
{
markend++;
break
;
}
}
}
length = markend - markbeg;
if
(relpos == 0)
relpos = length;
EXTEND(sp, 2);
PUSHs(sv_2mortal(newSVpvn((
char
*) markbeg, length)));
PUSHs(sv_2mortal(newSViv(relpos)));
SV *
GenerateNSName(name,
namespace
, table, list)
SV * name
SV *
namespace
SV * table
SV * list
CODE:
{
STRLEN nmlen, nslen;
char
* nmstr;
char
* nsstr;
char
* buff;
char
* bp;
char
* blim;
nmstr = SvPV(name, nmlen);
nsstr = SvPV(
namespace
, nslen);
New(321, buff, nmlen + nslen + 2,
char
);
bp = buff;
blim = bp + nslen;
while
(bp < blim)
*bp++ = *nsstr++;
*bp++ = NSDELIM;
blim = bp + nmlen;
while
(bp < blim)
*bp++ = *nmstr++;
*bp =
'\0'
;
RETVAL = gen_ns_name(buff, (HV *) SvRV(table), (AV *) SvRV(list));
Safefree(buff);
}
OUTPUT:
RETVAL
void
XML_DefaultCurrent(parser)
XML_Parser parser
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
XML_DefaultCurrent(parser);
}
SV *
XML_RecognizedString(parser)
XML_Parser parser
CODE:
{
XML_DefaultHandler dflthndl = (XML_DefaultHandler) 0;
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
if
(cbv->dflt_sv) {
dflthndl = defaulthandle;
}
if
(cbv->recstring) {
sv_setpvn(cbv->recstring,
""
, 0);
}
if
(cbv->no_expand)
XML_SetDefaultHandler(parser, recString);
else
XML_SetDefaultHandlerExpand(parser, recString);
XML_DefaultCurrent(parser);
if
(cbv->no_expand)
XML_SetDefaultHandler(parser, dflthndl);
else
XML_SetDefaultHandlerExpand(parser, dflthndl);
RETVAL = newSVsv(cbv->recstring);
}
OUTPUT:
RETVAL
int
XML_GetErrorCode(parser)
XML_Parser parser
int
XML_GetCurrentLineNumber(parser)
XML_Parser parser
int
XML_GetCurrentColumnNumber(parser)
XML_Parser parser
long
XML_GetCurrentByteIndex(parser)
XML_Parser parser
int
XML_GetSpecifiedAttributeCount(parser)
XML_Parser parser
char
*
XML_ErrorString(code)
int
code
CODE:
const
char
*ret = XML_ErrorString(code);
ST(0) = sv_newmortal();
sv_setpv((SV*)ST(0), ret);
SV *
XML_LoadEncoding(data, size)
char
* data
int
size
CODE:
{
Encmap_Header *emh = (Encmap_Header *) data;
unsigned pfxsize, bmsize;
if
(size <
sizeof
(Encmap_Header)
|| ntohl(emh->magic) != ENCMAP_MAGIC) {
RETVAL = &PL_sv_undef;
}
else
{
Encinfo *entry;
SV *sv;
PrefixMap *pfx;
unsigned
short
*bm;
int
namelen;
int
i;
pfxsize = ntohs(emh->pfsize);
bmsize = ntohs(emh->bmsize);
if
(size != (
sizeof
(Encmap_Header)
+ pfxsize *
sizeof
(PrefixMap)
+ bmsize *
sizeof
(unsigned
short
))) {
RETVAL = &PL_sv_undef;
}
else
{
for
(i = 0; i <
sizeof
(emh->name); i++) {
char
c = emh->name[i];
if
(c == (
char
) 0)
break
;
if
(c >=
'a'
&& c <=
'z'
)
emh->name[i] -=
'a'
-
'A'
;
}
namelen = i;
RETVAL = newSVpvn(emh->name, namelen);
New(322, entry, 1, Encinfo);
entry->prefixes_size = pfxsize;
entry->bytemap_size = bmsize;
for
(i = 0; i < 256; i++) {
entry->firstmap[i] = ntohl(emh->map[i]);
}
pfx = (PrefixMap *) &data[
sizeof
(Encmap_Header)];
bm = (unsigned
short
*) (((
char
*) pfx)
+
sizeof
(PrefixMap) * pfxsize);
New(323, entry->prefixes, pfxsize, PrefixMap);
New(324, entry->bytemap, bmsize, unsigned
short
);
for
(i = 0; i < pfxsize; i++, pfx++) {
PrefixMap *dest = &entry->prefixes[i];
dest->min = pfx->min;
dest->len = pfx->len;
dest->bmap_start = ntohs(pfx->bmap_start);
Copy(pfx->ispfx, dest->ispfx,
sizeof
(pfx->ispfx) +
sizeof
(pfx->ischar), unsigned
char
);
}
for
(i = 0; i < bmsize; i++)
entry->bytemap[i] = ntohs(bm[i]);
sv = newSViv(0);
sv_setref_pv(sv,
"XML::Parser::Encinfo"
, (
void
*) entry);
if
(! EncodingTable) {
EncodingTable
= perl_get_hv(
"XML::Parser::Expat::Encoding_Table"
,
FALSE);
if
(! EncodingTable)
croak(
"Can't find XML::Parser::Expat::Encoding_Table"
);
}
hv_store(EncodingTable, emh->name, namelen, sv, 0);
}
}
}
OUTPUT:
RETVAL
void
XML_FreeEncoding(enc)
Encinfo * enc
CODE:
Safefree(enc->bytemap);
Safefree(enc->prefixes);
Safefree(enc);
SV *
XML_OriginalString(parser)
XML_Parser parser
CODE:
{
int
parsepos, size;
const
char
*buff = XML_GetInputContext(parser, &parsepos, &size);
if
(buff) {
RETVAL = newSVpvn((
char
*) &buff[parsepos],
XML_GetCurrentByteCount(parser));
}
else
{
RETVAL = newSVpv(
""
, 0);
}
}
OUTPUT:
RETVAL
SV *
XML_SetStartCdataHandler(parser, startcd_sv)
XML_Parser parser
SV * startcd_sv
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
XML_StartCdataSectionHandler scdhndl =
(XML_StartCdataSectionHandler) 0;
XMLP_UPD(startcd_sv);
if
(SvTRUE(startcd_sv))
scdhndl = startCdata;
XML_SetStartCdataSectionHandler(parser, scdhndl);
PUSHRET;
}
SV *
XML_SetEndCdataHandler(parser, endcd_sv)
XML_Parser parser
SV * endcd_sv
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
XML_EndCdataSectionHandler ecdhndl =
(XML_EndCdataSectionHandler) 0;
XMLP_UPD(endcd_sv);
if
(SvTRUE(endcd_sv))
ecdhndl = endCdata;
XML_SetEndCdataSectionHandler(parser, ecdhndl);
PUSHRET;
}
void
XML_UnsetAllHandlers(parser)
XML_Parser parser
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
suspend_callbacks(cbv);
if
(cbv->ns) {
XML_SetNamespaceDeclHandler(cbv->p,
(XML_StartNamespaceDeclHandler) 0,
(XML_EndNamespaceDeclHandler) 0);
}
XML_SetElementHandler(parser,
(XML_StartElementHandler) 0,
(XML_EndElementHandler) 0);
XML_SetUnknownEncodingHandler(parser,
(XML_UnknownEncodingHandler) 0,
(
void
*) 0);
}
int
XML_ElementIndex(parser)
XML_Parser parser
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
RETVAL = cbv->st_serial_stack[cbv->st_serial_stackptr];
}
OUTPUT:
RETVAL
void
XML_SkipUntil(parser, index)
XML_Parser parser
unsigned
int
index
CODE:
{
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
if
(index <= cbv->st_serial)
return
;
cbv->skip_until = index;
suspend_callbacks(cbv);
}
int
XML_Do_External_Parse(parser, result)
XML_Parser parser
SV * result
CODE:
{
int
type;
CallbackVector * cbv = (CallbackVector *) XML_GetUserData(parser);
if
(SvROK(result) && SvOBJECT(SvRV(result))) {
RETVAL = parse_stream(parser, result);
}
else
if
(isGV(result)) {
RETVAL = parse_stream(parser,
sv_2mortal(newRV((SV*) GvIOp(result))));
}
else
if
(SvPOK(result)) {
STRLEN eslen;
int
pret;
char
*entstr = SvPV(result, eslen);
RETVAL = XML_Parse(parser, entstr, eslen, 1);
}
}
OUTPUT:
RETVAL