#include "ep.h"
#include "epmacro.h"
struct
tEmbperlCmd
{
int
bValid ;
const
char
* * sPerlCode ;
const
char
* * sCompileTimePerlCode ;
const
char
* sCompileTimePerlCodeEnd ;
const
char
* sPerlCodeEnd ;
const
char
* sStackName ;
const
char
* sPushStack ;
const
char
* sPopStack ;
const
char
* sMatchStack ;
const
char
* sStackName2 ;
const
char
* sPushStack2 ;
const
char
* sPopStack2 ;
int
numPerlCode ;
int
numCompileTimePerlCode ;
int
bRemoveNode ;
int
bPerlCodeRemove ;
int
bCompileChilds ;
int
nNodeType ;
int
nSwitchCodeType ;
int
bCallReturn ;
const
char
* sMayJump ;
struct
tEmbperlCmd * pNext ;
} ;
typedef
struct
tEmbperlCmd tEmbperlCmd ;
struct
tEmbperlCompilerInfo
{
tStringIndex nMaxEmbperlCmd ;
tEmbperlCmd * pEmbperlCmds ;
} ;
typedef
struct
tEmbperlCompilerInfo tEmbperlCompilerInfo ;
static
int
embperl_CompileInit (
tApp * a,
tEmbperlCompilerInfo * * ppInfo)
{
epaTHX_
tEmbperlCompilerInfo * pInfo =
malloc
(
sizeof
(tEmbperlCompilerInfo)) ;
if
(!pInfo)
return
rcOutOfMemory ;
ArrayNewZero (a, &pInfo -> pEmbperlCmds, 256,
sizeof
(
struct
tEmbperlCmd)) ;
ArraySet (a, &pInfo -> pEmbperlCmds, 0) ;
pInfo -> nMaxEmbperlCmd = 1 ;
*ppInfo = pInfo ;
return
ok ;
}
int
embperl_CompileInitItem (
register
req * r,
HV * pHash,
int
nNodeName,
int
nNodeType,
int
nTagSet,
void
* * ppInfo)
{
epTHX_
SV * * ppSV ;
AV * pAV ;
tEmbperlCmd * pCmd ;
tEmbperlCompilerInfo * pInfo = (tEmbperlCompilerInfo *)*ppInfo ;
if
(!pInfo)
embperl_CompileInit (r -> pApp, (tEmbperlCompilerInfo * *)ppInfo) ;
pInfo = (tEmbperlCompilerInfo *)*ppInfo ;
ArraySet (r -> pApp, &pInfo -> pEmbperlCmds, nNodeName+1) ;
if
(pInfo -> nMaxEmbperlCmd < nNodeName)
pInfo -> nMaxEmbperlCmd = nNodeName ;
pCmd = &pInfo -> pEmbperlCmds[nNodeName] ;
if
(pCmd -> bValid)
{
tEmbperlCmd * pNewCmd ;
if
(pCmd -> bValid == nTagSet)
return
ok ;
while
(pCmd -> pNext)
{
if
(pCmd -> bValid == nTagSet)
return
ok ;
pCmd = pCmd -> pNext ;
}
if
(pCmd -> bValid == nTagSet)
return
ok ;
pNewCmd =
malloc
(
sizeof
(*pNewCmd)) ;
pCmd -> pNext = pNewCmd ;
pCmd = pNewCmd ;
memset
(pCmd, 0,
sizeof
(*pCmd)) ;
}
pCmd -> bValid = nTagSet ;
ppSV = hv_fetch(pHash,
"perlcode"
, 8, 0) ;
if
(ppSV != NULL && *ppSV != NULL &&
SvROK(*ppSV) && SvTYPE((pAV = (AV *)SvRV(*ppSV))) == SVt_PVAV)
{
int
f = AvFILL(pAV) + 1 ;
int
i ;
STRLEN l ;
pCmd -> sPerlCode =
malloc
(f *
sizeof
(
char
*)) ;
pCmd -> numPerlCode = f ;
for
(i = 0; i < f; i++)
{
ppSV = av_fetch (pAV, i, 0) ;
if
(ppSV && *ppSV)
pCmd -> sPerlCode[i] = strdup (SvPV (*ppSV, l)) ;
else
pCmd -> sPerlCode[i] = NULL ;
}
}
else
{
if
(ppSV)
{
STRLEN l ;
pCmd -> sPerlCode =
malloc
(
sizeof
(
char
*)) ;
pCmd -> numPerlCode = 1 ;
pCmd -> sPerlCode[0] = sstrdup (r, SvPV (*ppSV, l)) ;
}
}
ppSV = hv_fetch(pHash,
"compiletimeperlcode"
, 19, 0) ;
if
(ppSV != NULL && *ppSV != NULL &&
SvROK(*ppSV) && SvTYPE((pAV = (AV *)SvRV(*ppSV))) == SVt_PVAV)
{
int
f = AvFILL(pAV) + 1 ;
int
i ;
STRLEN l ;
pCmd -> sCompileTimePerlCode =
malloc
(f *
sizeof
(
char
*)) ;
pCmd -> numCompileTimePerlCode = f ;
for
(i = 0; i < f; i++)
{
ppSV = av_fetch (pAV, i, 0) ;
if
(ppSV && *ppSV)
pCmd -> sCompileTimePerlCode[i] = strdup (SvPV (*ppSV, l)) ;
else
pCmd -> sCompileTimePerlCode[i] = NULL ;
}
}
else
{
if
(ppSV)
{
STRLEN l ;
pCmd -> sCompileTimePerlCode =
malloc
(
sizeof
(
char
*)) ;
pCmd -> numCompileTimePerlCode = 1 ;
pCmd -> sCompileTimePerlCode[0] = sstrdup (r, SvPV (*ppSV, l)) ;
}
}
pCmd -> sPerlCodeEnd = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"perlcodeend"
, NULL) ;
pCmd -> sCompileTimePerlCodeEnd = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"compiletimeperlcodeend"
, NULL) ;
pCmd -> sStackName = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"stackname"
, NULL) ;
pCmd -> sPushStack = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"push"
, NULL) ;
pCmd -> sPopStack = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"pop"
, NULL) ;
pCmd -> sMatchStack = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"stackmatch"
, NULL) ;
pCmd -> sStackName2 = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"stackname2"
, NULL) ;
pCmd -> sPushStack2 = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"push2"
, NULL) ;
pCmd -> sPopStack2 = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"pop2"
, NULL) ;
pCmd -> bRemoveNode = GetHashValueInt (aTHX_ pHash,
"removenode"
, 0) ;
pCmd -> sMayJump = GetHashValueStrDup (aTHX_ r -> pThread -> pMainPool, pHash,
"mayjump"
, NULL) ;
pCmd -> bPerlCodeRemove = GetHashValueInt (aTHX_ pHash,
"perlcoderemove"
, 0) ;
pCmd -> bCompileChilds = GetHashValueInt (aTHX_ pHash,
"compilechilds"
, 1) ;
pCmd -> nSwitchCodeType = GetHashValueInt (aTHX_ pHash,
"switchcodetype"
, 0) ;
pCmd -> bCallReturn = GetHashValueInt (aTHX_ pHash,
"callreturn"
, 0) ;
pCmd -> nNodeType = nNodeType == ntypStartEndTag?ntypStartTag:nNodeType ;
pCmd -> pNext = NULL ;
pInfo -> pEmbperlCmds[nNodeName].bRemoveNode |= pCmd -> bRemoveNode ;
if
(pCmd -> nSwitchCodeType)
pInfo -> pEmbperlCmds[nNodeName].nSwitchCodeType = pCmd -> nSwitchCodeType ;
if
(pCmd -> sMayJump && !pInfo -> pEmbperlCmds[nNodeName].sMayJump)
pInfo -> pEmbperlCmds[nNodeName].sMayJump = pCmd -> sMayJump ;
if
(r -> Component.Config.bDebug & dbgBuildToken)
lprintf (r -> pApp,
"[%d]EPCOMP: InitItem %s (#%d) perlcode=%s (num=%d) perlcodeend=%s compilechilds=%d removenode=%d nodetype=%d\n"
,
r -> pThread -> nPid, Ndx2String(nNodeName), nNodeName,
pCmd -> sPerlCode?pCmd -> sPerlCode[0]:
""
,
pCmd -> numPerlCode,
pCmd -> sPerlCodeEnd?pCmd -> sPerlCodeEnd:
"<undef>"
,
pCmd -> bCompileChilds,
pCmd -> bRemoveNode,
pCmd -> nNodeType) ;
return
ok ;
}
static
const
char
* strstrn (
const
char
* s1,
const
char
* s2,
int
l)
{
while
(*s1)
{
if
((s1 =
strchr
(s1, *s2)) == NULL)
return
NULL ;
if
(
strncmp
(s1, s2, l) == 0)
return
s1 ;
s1++ ;
}
return
NULL ;
}
static
int
embperl_CompileAddValue (
tReq * r,
const
char
* sText,
const
char
* p,
const
char
* q,
const
char
* eq,
char
op,
char
out,
char
* * ppCode )
{
const
char
* or ;
const
char
* e ;
if
(sText)
{
int
l =
strlen
(sText) ;
if
(out == 3)
{
out = 2 ;
while
(
isspace
(*sText))
sText++, l-- ;
while
(l > 0 &&
isspace
(sText[l-1]))
l-- ;
}
if
(op ==
'='
&& eq)
{
eq++ ;
do
{
or =
strchr
(eq + 1,
'|'
) ;
e = or?or:q ;
if
(strnicmp (sText, eq, e - eq) == 0)
break
;
if
(or == NULL)
return
0 ;
eq = or + 1 ;
}
while
(or) ;
}
else
if
(op ==
'~'
&& eq)
{
eq++ ;
do
{
char
* f ;
or =
strchr
(eq + 1,
'|'
) ;
e = or?or:q ;
if
((f = (
char
*)strstrn (sText, eq, e - eq)))
if
(!
isalnum
(f[e - eq]) && f[e - eq] !=
'_'
)
break
;
if
(or == NULL)
return
0 ;
eq = or + 1 ;
}
while
(or) ;
}
else
if
(op ==
'!'
&& sText)
{
return
0 ;
}
if
(out)
{
if
(out == 2)
{
const
char
* s = sText ;
StringAdd (r -> pApp, ppCode,
"'"
, 1) ;
while
(*s && l--)
{
if
(*s ==
'\''
)
{
if
(sText < s)
StringAdd (r -> pApp, ppCode, sText, s - sText) ;
StringAdd (r -> pApp, ppCode,
"\\'"
, 2) ;
sText = s + 1 ;
}
else
if
(*s ==
'\\'
)
{
if
(sText < s)
StringAdd (r -> pApp, ppCode, sText, s - sText) ;
StringAdd (r -> pApp, ppCode,
"\\\\"
, 2) ;
sText = s + 1 ;
}
s++ ;
}
if
(sText < s)
StringAdd (r -> pApp, ppCode, sText, s - sText) ;
StringAdd (r -> pApp, ppCode,
"'"
, 1) ;
}
else
if
(out)
StringAdd (r -> pApp, ppCode, sText, 0) ;
}
}
else
{
if
(op !=
'!'
&& op != 0)
return
0 ;
if
(out)
StringAdd (r -> pApp, ppCode,
"undef"
, 5) ;
}
return
1 ;
}
static
void
embperl_CompilePushStack (
tReq * r,
tDomTree * pDomTree,
const
char
* sStackName,
const
char
* sStackValue)
{
epTHX_
SV ** ppSV ;
SV * pSV ;
AV * pAV ;
ppSV = hv_fetch((HV *)(pDomTree -> pSV), (
char
*)sStackName,
strlen
(sStackName), 1) ;
if
(ppSV == NULL)
return
;
if
(*ppSV == NULL || !SvROK (*ppSV))
{
if
(*ppSV)
SvREFCNT_dec (*ppSV) ;
*ppSV = newRV_noinc ((SV *)(pAV = newAV ())) ;
}
else
pAV = (AV *)SvRV (*ppSV) ;
pSV = newSVpv ((
char
*)sStackValue,
strlen
(sStackValue)) ;
SvUPGRADE (pSV, SVt_PVIV) ;
SvIVX (pSV) = 0 ;
av_push (pAV, pSV) ;
}
static
void
embperl_CompilePopStack (
tReq * r,
tDomTree * pDomTree,
const
char
* sStackName)
{
epTHX_
SV ** ppSV ;
SV * pSV ;
ppSV = hv_fetch((HV *)(pDomTree -> pSV), (
char
*)sStackName,
strlen
(sStackName), 0) ;
if
(ppSV == NULL || *ppSV == NULL || !SvROK (*ppSV))
return
;
pSV = av_pop ((AV *)SvRV (*ppSV)) ;
SvREFCNT_dec (pSV) ;
}
static
int
embperl_CompileMatchStack (
tReq * r,
tDomTree * pDomTree,
tNodeData * pNode,
const
char
* sStackName,
const
char
* sStackValue)
{
epTHX_
SV ** ppSV ;
SV * pSV ;
STRLEN l ;
char
* s ;
ppSV = hv_fetch((HV *)(pDomTree -> pSV), (
char
*)sStackName,
strlen
(sStackName), 0) ;
if
(ppSV == NULL || *ppSV == NULL || !SvROK (*ppSV))
{
strcpy
(r -> errdat1,
"CompileMatchStack"
) ;
strncat
(r -> errdat1, (
char
*)sStackName,
sizeof
(r -> errdat1) - 20) ;
return
rcHashError ;
}
pSV = av_pop ((AV *)SvRV (*ppSV)) ;
s = SvPV (pSV, l) ;
if
(
strcmp
(s, sStackValue) == 0)
{
SvREFCNT_dec (pSV) ;
return
ok ;
}
strncpy
(r -> errdat1, Node_selfNodeName (pNode),
sizeof
(r -> errdat1)) ;
sprintf
(r -> errdat2,
"'%s', starttag should be '%s' or there is a 'end%s' missing"
, s, sStackValue, s) ;
r -> Component.pCurrPos = NULL ;
r -> Component.nSourceline = pNode -> nLinenumber ;
SvREFCNT_dec (pSV) ;
return
rcTagMismatch ;
}
static
int
embperl_CompileAddStack (
tReq * r,
tDomTree * pDomTree,
const
char
* p,
const
char
* q,
char
op,
char
out,
char
str,
char
* * ppCode )
{
epTHX_
const
char
* eq =
strchr
(p,
':'
) ;
const
char
* e = eq && eq < q?eq:q;
STRLEN l ;
const
char
* sText = NULL ;
SV ** ppSV ;
AV * pAV ;
ppSV = hv_fetch((HV *)(pDomTree -> pSV), (
char
*)p, e - p, 0) ;
if
(ppSV == NULL || *ppSV == NULL || !SvROK (*ppSV))
return
op ==
'!'
?1:0 ;
pAV = (AV *)SvRV (*ppSV) ;
if
(SvTYPE (pAV) != SVt_PVAV)
return
op ==
'!'
?1:0 ;
ppSV = av_fetch (pAV, av_len (pAV), 0) ;
if
(ppSV == NULL || *ppSV == NULL)
return
op ==
'!'
?1:0 ;
if
(str)
{
sText = SvPV (*ppSV, l) ;
(SvIVX (*ppSV))++ ;
}
else
sText = SvIVX (*ppSV)?
"1"
:NULL ;
return
embperl_CompileAddValue (r, sText, p, q, eq, op, out, ppCode) ;
}
static
int
embperl_CompileAddChildNode (
tReq * r,
tDomTree * pDomTree,
tNodeData * pNode,
const
char
* p,
const
char
* q,
char
op,
char
out,
char
* * ppCode )
{
const
char
* eq =
strchr
(p,
':'
) ;
int
nChildNo =
atoi
(p) ;
struct
tNodeData * pChildNode = Node_selfNthChild (r -> pApp, pDomTree, pNode, 0, nChildNo) ;
const
char
* sText = NULL ;
if
(pChildNode)
sText = Node_selfNodeName(pChildNode) ;
return
embperl_CompileAddValue (r, sText, p, q, eq, op, out, ppCode) ;
}
static
int
embperl_CompileAddSiblingNode (
tReq * r,
tDomTree * pDomTree,
tNodeData * pNode,
const
char
* p,
const
char
* q,
char
op,
char
out,
char
* * ppCode )
{
const
char
* eq =
strchr
(p,
':'
) ;
int
nChildNo =
atoi
(p) ;
struct
tNodeData * pChildNode ;
const
char
* sText = NULL ;
if
(nChildNo == 0)
pChildNode = pNode ;
else
if
(nChildNo > 0)
{
nChildNo-- ;
pChildNode = Node_selfNextSibling (r -> pApp, pDomTree, pNode, 0) ;
while
(pChildNode && nChildNo-- > 0)
pChildNode = Node_selfNextSibling (r -> pApp, pDomTree, pChildNode, 0) ;
}
else
{
nChildNo++ ;
pChildNode = Node_selfPreviousSibling (r -> pApp, pDomTree, pNode, 0) ;
while
(pChildNode && nChildNo++ < 0)
pChildNode = Node_selfPreviousSibling (r -> pApp, pDomTree, pChildNode, 0) ;
}
if
(pChildNode)
sText = Node_selfNodeName(pChildNode) ;
return
embperl_CompileAddValue (r, sText, p, q, eq, op, out, ppCode) ;
}
static
int
embperl_CompileAddAttribut (
tReq * r,
tDomTree * pDomTree,
tNodeData * pNode,
const
char
* p,
const
char
* q,
char
op,
char
out,
char
* * ppCode )
{
const
char
* eq =
strchr
(p,
':'
) ;
const
char
* e = eq && eq < q?eq:q;
tAttrData * pChildNode = Element_selfGetAttribut (r -> pApp, pDomTree, pNode, p, e - p) ;
const
char
* sText = NULL ;
char
buf [128] ;
if
(pChildNode)
{
if
(pChildNode -> bFlags & aflgAttrChilds)
{
sprintf
(buf,
"XML::Embperl::DOM::Attr::iValue ($_ep_DomTree,%ld)"
, pChildNode -> xNdx) ;
sText = buf ;
if
(out == 2)
out = 1 ;
}
else
{
sText = Ndx2String (pChildNode -> xValue) ;
}
}
return
embperl_CompileAddValue (r, sText, p, q, eq, op, out, ppCode) ;
}
static
int
embperl_CompileToPerlCode (
tReq * r,
tDomTree * pDomTree,
tNodeData * pNode,
const
char
* sPerlCode,
char
* * ppCode )
{
const
char
* p ;
const
char
* q ;
int
valid = 1 ;
tNode xCurrNode = 0 ;
StringNew (r -> pApp, ppCode, 512) ;
if
(sPerlCode)
{
p =
strchr
(sPerlCode,
'%'
) ;
while
(p)
{
int
n = p - sPerlCode ;
if
(n)
StringAdd (r -> pApp, ppCode, sPerlCode, n) ;
q =
strchr
(p+1,
'%'
) ;
if
(q)
{
char
type ;
char
op ;
char
out = 1 ;
p++ ;
type = *p ;
p++ ;
op = *p ;
if
(op !=
'='
&& op !=
'*'
&& op !=
'!'
&& op !=
'~'
)
op = 0 ;
else
p++ ;
if
(*p ==
'-'
)
out = 0, p++ ;
else
if
(*p ==
'\''
)
out = 2, p++ ;
else
if
(*p ==
'"'
)
out = 3, p++ ;
if
(type ==
'#'
)
{
if
(!embperl_CompileAddChildNode (r, pDomTree, pNode ,p, q, op, out, ppCode))
{
valid = 0 ;
break
;
}
}
else
if
(type ==
'>'
)
{
if
(!embperl_CompileAddSiblingNode (r, pDomTree, pNode ,p, q, op, out, ppCode))
{
valid = 0 ;
break
;
}
}
else
if
(type ==
'&'
)
{
if
(!embperl_CompileAddAttribut (r, pDomTree, pNode ,p, q, op, out, ppCode))
{
valid = 0 ;
break
;
}
}
else
if
(type ==
'^'
)
{
if
(!embperl_CompileAddStack (r, pDomTree, p, q, op, out, 1, ppCode))
{
valid = 0 ;
break
;
}
}
else
if
(type ==
'?'
)
{
if
(!embperl_CompileAddStack (r, pDomTree, p, q, op, out, 0, ppCode))
{
valid = 0 ;
break
;
}
}
else
if
(type ==
'%'
)
{
StringAdd (r -> pApp, ppCode,
"%"
, 1) ;
}
else
if
(type ==
'$'
)
{
if
(*p ==
'n'
)
{
char
s [20] ;
int
l =
sprintf
(s,
"$_ep_DomTree,%ld"
, pNode -> xNdx) ;
StringAdd (r -> pApp, ppCode, s, l) ;
}
else
if
(*p ==
't'
)
{
StringAdd (r -> pApp, ppCode,
"$_ep_DomTree"
, 0) ;
}
else
if
(*p ==
'x'
)
{
char
s [20] ;
int
l =
sprintf
(s,
"%ld"
, pNode -> xNdx) ;
StringAdd (r -> pApp, ppCode, s, l) ;
}
else
if
(*p ==
'l'
)
{
char
s [20] ;
int
l =
sprintf
(s,
"%ld"
, pDomTree -> xLastNode) ;
StringAdd (r -> pApp, ppCode, s, l) ;
}
else
if
(*p ==
'c'
)
{
char
s [20] ;
if
(pDomTree -> xLastNode != pDomTree -> xCurrNode)
{
int
l =
sprintf
(s,
"$_ep_node=%ld;"
, pDomTree -> xLastNode) ;
StringAdd (r -> pApp, ppCode, s, l) ;
xCurrNode = pDomTree -> xLastNode ;
}
}
else
if
(*p ==
'q'
)
{
char
s [20] ;
int
l =
sprintf
(s,
"%hd"
, pDomTree -> xNdx) ;
StringAdd (r -> pApp, ppCode, s, l) ;
}
else
if
(*p ==
'p'
)
{
char
s [20] ;
int
l =
sprintf
(s,
"%u"
, ArrayGetSize (r -> pApp, pDomTree -> pCheckpoints)) ;
StringAdd (r -> pApp, ppCode, s, l) ;
}
else
if
(*p ==
'k'
)
{
char
s [40] ;
int
l ;
tIndex nCheckpointArrayOffset = ArrayAdd (r -> pApp, &pDomTree -> pCheckpoints, 1) ;
pDomTree -> pCheckpoints[nCheckpointArrayOffset].xNode = pNode -> xNdx ;
l =
sprintf
(s,
" _ep_cp(%ld) ;\n"
, nCheckpointArrayOffset) ;
StringAdd (r -> pApp, ppCode, s, l) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Checkpoint\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber) ;
}
}
sPerlCode = q + 1 ;
p =
strchr
(sPerlCode,
'%'
) ;
}
else
{
sPerlCode = p ;
p = NULL ;
}
}
if
(valid)
{
StringAdd (r -> pApp, ppCode, sPerlCode, 0) ;
if
(xCurrNode)
pDomTree -> xCurrNode = xCurrNode ;
}
}
return
valid ;
}
static
int
embperl_CompileCleanupSpaces (
tReq * r,
tDomTree * pDomTree,
tNodeData * pNode,
tEmbperlCmd * pCmd)
{
if
((pCmd -> bRemoveNode & 6) && (r -> Component.Config.bOptions & optKeepSpaces) == 0)
{
tNodeData * pNextNode = Node_selfFirstChild (r -> pApp, pDomTree, pNode, 0) ;
if
((pCmd -> bRemoveNode & 1) || !pCmd -> bCompileChilds || pNextNode == NULL || (pNextNode -> nType != ntypText && pNextNode -> nType != ntypCDATA))
pNextNode = Node_selfNextSibling (r -> pApp, pDomTree, pNode, 0) ;
if
(pNextNode)
{
const
char
* sText = Node_selfNodeName (pNextNode) ;
const
char
* p = sText ;
while
(*p &&
isspace
(*p))
p++;
if
(p > sText && (pCmd -> bRemoveNode & 4))
p-- ;
if
(p > sText)
{
if
(*p)
Node_replaceChildWithCDATA(r -> pApp, pDomTree, pNextNode -> xNdx, 0, p,
strlen
(p), -1, 0) ;
else
Node_selfRemoveChild(r -> pApp, pDomTree, -1, pNextNode) ;
}
}
}
return
ok ;
}
static
int
embperl_CompileCmd (
tReq * r,
tDomTree * pDomTree,
tNodeData * pNode,
tEmbperlCmd * pCmd,
int
* nStartCodeOffset)
{
epTHX_
char
* pCode = NULL ;
char
* pCTCode = NULL ;
char
* sSourcefile ;
int
nSourcefile ;
int
i ;
SV * args[4] ;
int
nCodeLen = 0 ;
int
found = 0 ;
char
*use_utf8 =
""
;
if
(
strcmp
(r -> Component.Config.sInputCharset,
"utf8"
) == 0)
use_utf8 =
"use utf8;"
;
r -> Component.pCodeSV = NULL ;
Ndx2StringLen (pDomTree -> xFilename, sSourcefile, nSourcefile) ;
if
(pCmd -> nNodeType != pNode -> nType)
return
ok ;
for
(i = 0; i < pCmd -> numPerlCode; i++)
if
(embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sPerlCode[i], &pCode))
{
found = 1 ;
break
;
}
if
(found && pCode)
{
nCodeLen = ArrayGetSize (r -> pApp, pCode) ;
if
(nCodeLen)
{
char
buf [32] ;
if
(pNode -> nLinenumber && pNode -> nLinenumber != pDomTree -> nLastLinenumber )
{
int
l2 =
sprintf
(buf,
"#line %d \""
, pDomTree -> nLastLinenumber = pNode -> nLinenumber) ;
StringAdd (r -> pApp, r -> Component.pProg, buf, l2) ;
StringAdd (r -> pApp, r -> Component.pProg, sSourcefile, nSourcefile) ;
StringAdd (r -> pApp, r -> Component.pProg,
"\"\n"
, 2) ;
}
if
(pCmd -> bPerlCodeRemove)
*nStartCodeOffset = StringAdd (r -> pApp, r -> Component.pProg,
" "
, 1) ;
}
else
{
StringFree (r -> pApp, &pCode) ;
pCode = NULL ;
}
}
else
{
StringFree (r -> pApp, &pCode) ;
pCode = NULL ;
}
for
(i = 0; i < pCmd -> numCompileTimePerlCode; i++)
{
if
(embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sCompileTimePerlCode[i], &pCTCode))
{
SV * pSV ;
int
rc ;
if
(pCTCode)
{
int
l = ArrayGetSize (r -> pApp, pCTCode) ;
int
i = l ;
char
*p = pCTCode ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d CompileTimeCode: %*.*s\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber, l, l, pCTCode) ;
if
(p[0] ==
'#'
&& p[1] ==
'!'
&& p[2] ==
'-'
)
{
p[0] =
' '
;
p[1] =
' '
;
p[2] =
' '
;
while
(i--)
{
if
(*p ==
'\r'
|| *p ==
'\n'
)
*p =
' '
;
p++ ;
}
}
pSV = newSVpvf(
"package %s ; %s\n#line %d \"%s\"\n%*.*s"
,
r -> Component.sEvalPackage, use_utf8, pNode -> nLinenumber, sSourcefile, l,l, pCTCode) ;
newSVpvf2(pSV) ;
args[0] = r -> _perlsv ;
if
(pCode)
{
r -> Component.pCodeSV = newSVpv (pCode, nCodeLen) ;
}
else
r -> Component.pCodeSV = &sv_undef ;
SvTAINTED_off (pSV) ;
if
((rc = EvalDirect (r, pSV, 1, args)) != ok)
LogError (r, rc) ;
SvREFCNT_dec(pSV);
}
break
;
}
}
if
(r -> Component.pCodeSV && SvOK(r -> Component.pCodeSV))
{
STRLEN l ;
char
* p = SvPV (r -> Component.pCodeSV, l) ;
StringAdd (r -> pApp, r -> Component.pProg, p, l ) ;
StringAdd (r -> pApp, r -> Component.pProg,
"\n"
, 1) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Code: %s\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber, p) ;
}
else
if
(pCode)
{
StringAdd (r -> pApp, r -> Component.pProg, pCode, nCodeLen ) ;
StringAdd (r -> pApp, r -> Component.pProg,
"\n"
, 1) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Code: %*.*s\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber, nCodeLen, nCodeLen, pCode) ;
}
StringFree (r -> pApp, &pCode) ;
StringFree (r -> pApp, &pCTCode) ;
if
(r -> Component.pCodeSV)
{
SvREFCNT_dec(r -> Component.pCodeSV);
r -> Component.pCodeSV = NULL ;
}
return
ok ;
}
static
int
embperl_CompilePostProcess (
tReq * r,
tDomTree * pDomTree,
tNodeData * pNode,
tEmbperlCmd * pCmd,
int
nCheckpointCodeOffset,
int
nCheckpointArrayOffset,
int
* bCheckpointPending)
{
int
rc ;
char
* sStackValue = NULL ;
embperl_CompileCleanupSpaces (r, pDomTree, pNode, pCmd) ;
if
(pCmd -> sMayJump)
if
(embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sMayJump, &sStackValue))
{
if
(*bCheckpointPending <= 0)
*bCheckpointPending = -1 ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Set Checkpoint pending\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber) ;
}
if
(pCmd -> bRemoveNode & 1)
pNode -> bFlags = 0 ;
else
if
(pCmd -> bRemoveNode & 8)
pNode -> bFlags |= nflgIgnore ;
if
(pCmd -> bRemoveNode & 16)
{
tNodeData * pChild ;
while
((pChild = Node_selfFirstChild (r -> pApp, pDomTree, pNode, 0)))
{
Node_selfRemoveChild (r -> pApp, pDomTree, pNode -> xNdx, pChild) ;
}
}
else
if
(pCmd -> bRemoveNode & 32)
{
tNodeData * pChild = Node_selfFirstChild (r -> pApp, pDomTree, pNode, 0) ;
while
(pChild)
{
pChild -> bFlags |= nflgIgnore ;
pChild = Node_selfNextSibling (r -> pApp, pDomTree, pChild, 0) ;
}
}
if
(nCheckpointCodeOffset && (pNode -> bFlags == 0 || (pNode -> bFlags & nflgIgnore)))
{
(*r -> Component.pProg)[nCheckpointCodeOffset] =
'#'
;
nCheckpointArrayOffset = ArraySub (r -> pApp, &pDomTree -> pCheckpoints, 1) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Remove Checkpoint\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber) ;
nCheckpointCodeOffset = 0 ;
if
(*bCheckpointPending <= 0)
*bCheckpointPending = -1 ;
}
if
(*bCheckpointPending < 0 && (pNode -> bFlags & nflgIgnore))
{
int
l ;
char
buf [80] ;
nCheckpointArrayOffset = ArrayAdd (r -> pApp, &pDomTree -> pCheckpoints, 1) ;
pDomTree -> pCheckpoints[nCheckpointArrayOffset].xNode = pNode -> xNdx ;
*bCheckpointPending = 0 ;
l =
sprintf
(buf,
" _ep_cp(%d) ;\n"
, nCheckpointArrayOffset) ;
nCheckpointCodeOffset = StringAdd (r -> pApp, r -> Component.pProg, buf, l) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Checkpoint\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber) ;
}
if
(pCmd -> sPopStack)
embperl_CompilePopStack (r, pDomTree, pCmd -> sPopStack) ;
if
(pCmd -> sPopStack2)
embperl_CompilePopStack (r, pDomTree, pCmd -> sPopStack2) ;
if
(pCmd -> sStackName)
{
if
(pCmd -> sMatchStack && pNode -> nType != ntypStartTag && pNode -> nType != ntypDocument && pNode -> nType != ntypDocumentFraq)
{
if
(embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sMatchStack, &sStackValue))
if
((rc = embperl_CompileMatchStack (r, pDomTree, pNode, pCmd -> sStackName, sStackValue)) != ok)
{
StringFree (r -> pApp, &sStackValue) ;
return
rc ;
}
}
if
(pCmd -> sPushStack)
{
if
(embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sPushStack, &sStackValue))
embperl_CompilePushStack (r, pDomTree, pCmd -> sStackName, sStackValue) ;
}
}
if
(pCmd -> sStackName2 && pCmd -> sPushStack2)
{
if
(embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sPushStack2, &sStackValue))
{
embperl_CompilePushStack (r, pDomTree, pCmd -> sStackName2, sStackValue) ;
}
}
StringFree (r -> pApp, &sStackValue) ;
return
ok ;
}
static
int
embperl_CompileCmdEnd (
tReq * r,
tDomTree * pDomTree,
tNodeData * pNode,
tEmbperlCmd * pCmd,
int
nStartCodeOffset,
int
* bCheckpointPending)
{
epTHX_
int
rc ;
char
* sStackValue = NULL ;
char
* pCode = NULL ;
char
* pCTCode = NULL ;
SV * args[4] ;
STRLEN nCodeLen = 0 ;
char
*use_utf8 =
""
;
if
(
strcmp
(r -> Component.Config.sInputCharset,
"utf8"
) == 0)
use_utf8 =
"use utf8;"
;
if
(pCmd -> nNodeType != pNode -> nType)
return
ok ;
if
(pCmd)
{
if
(pCmd -> sPerlCodeEnd && embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sPerlCodeEnd, &pCode))
nCodeLen = ArrayGetSize (r -> pApp, pCode) ;
if
(embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sCompileTimePerlCodeEnd, &pCTCode))
{
SV * pSV ;
int
rc ;
if
(pCTCode && *pCTCode)
{
int
l = ArrayGetSize (r -> pApp, pCTCode) ;
char
* sSourcefile ;
int
nSourcefile ;
int
i = l ;
char
* p = pCTCode ;
Ndx2StringLen (pDomTree -> xFilename, sSourcefile, nSourcefile) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d CompileTimeCodeEnd: %*.*s\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber, l, l, pCTCode) ;
if
(p[0] ==
'#'
&& p[1] ==
'!'
&& p[2] ==
'-'
)
{
p[0] =
' '
;
p[1] =
' '
;
p[2] =
' '
;
while
(i--)
{
if
(*p ==
'\r'
|| *p ==
'\n'
)
*p =
' '
;
p++ ;
}
}
pSV = newSVpvf(
"package %s ; %s\n#line %d \"%s\"\n%*.*s"
,
r -> Component.sEvalPackage, use_utf8, pNode -> nLinenumber, sSourcefile, l,l, pCTCode) ;
newSVpvf2(pSV) ;
args[0] = r -> _perlsv ;
if
(pCode)
{
r -> Component.pCodeSV = newSVpv (pCode, nCodeLen) ;
}
else
r -> Component.pCodeSV = &sv_undef ;
if
((rc = EvalDirect (r, pSV, 1, args)) != ok)
LogError (r, rc) ;
SvREFCNT_dec(pSV);
}
}
if
(r -> Component.pCodeSV)
{
if
(SvOK (r -> Component.pCodeSV))
{
char
* p = SvPV (r -> Component.pCodeSV, nCodeLen) ;
if
(nCodeLen)
{
StringAdd (r -> pApp, r -> Component.pProg, p, nCodeLen ) ;
StringAdd (r -> pApp, r -> Component.pProg,
"\n"
, 1) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d CodeEnd: %s\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber, p) ;
}
}
}
else
if
(pCode && nCodeLen)
{
StringAdd (r -> pApp, r -> Component.pProg, pCode, nCodeLen ) ;
StringAdd (r -> pApp, r -> Component.pProg,
"\n"
, 1) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d CodeEnd: %*.*s\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber, nCodeLen, nCodeLen, pCode) ;
}
if
(nCodeLen == 0)
{
if
(pCmd -> bPerlCodeRemove && nStartCodeOffset)
{
(*r -> Component.pProg)[nStartCodeOffset] =
'#'
;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Remove Codeblock\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber) ;
}
}
if
(pCmd -> sPerlCodeEnd && pCmd -> sMayJump)
if
(embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sMayJump, &sStackValue))
{
if
(*bCheckpointPending <= 0)
*bCheckpointPending = -1 ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Set Checkpoint pending\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber) ;
}
if
(pCmd -> sStackName && (pNode -> nType == ntypStartTag || pNode -> nType == ntypDocument || pNode -> nType == ntypDocumentFraq))
{
if
(pCmd -> sMatchStack)
{
if
(embperl_CompileToPerlCode (r, pDomTree, pNode, pCmd -> sMatchStack, &sStackValue))
{
if
((rc = embperl_CompileMatchStack (r, pDomTree, pNode, pCmd -> sStackName, sStackValue)) != ok)
{
StringFree (r -> pApp, &pCode) ;
StringFree (r -> pApp, &pCTCode) ;
StringFree (r -> pApp, &sStackValue) ;
return
rc ;
}
}
}
else
if
(pCmd -> sPushStack && pCmd -> sPerlCodeEnd)
embperl_CompilePopStack (r, pDomTree, pCmd -> sStackName) ;
}
if
(pCmd -> sStackName2 && pCmd -> sPushStack2 && pCmd -> sPerlCodeEnd)
embperl_CompilePopStack (r, pDomTree, pCmd -> sStackName2) ;
if
(pCmd -> nSwitchCodeType == 1)
{
r -> Component.pProg = &r -> Component.pProgRun ;
if
(*bCheckpointPending <= 0)
*bCheckpointPending = -1 ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Set Checkpoint pending (switch to ProgRun)\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber) ;
}
}
StringFree (r -> pApp, &pCode) ;
StringFree (r -> pApp, &pCTCode) ;
if
(r -> Component.pCodeSV)
{
SvREFCNT_dec(r -> Component.pCodeSV);
r -> Component.pCodeSV = NULL ;
}
StringFree (r -> pApp, &sStackValue) ;
return
ok ;
}
int
embperl_CompileNode (
tReq * r,
tDomTree * pDomTree,
tNode xNode,
int
* bCheckpointPending)
{
int
rc ;
tNode xChildNode ;
tStringIndex nNdx ;
tEmbperlCmd * pCmd ;
tEmbperlCmd * pCmdHead ;
tEmbperlCmd * pCmdLast ;
tEmbperlCmd * pCmdNext ;
tEmbperlCmd * pCmdIter ;
tNodeData * pNode = Node_self (pDomTree, xNode) ;
tAttrData * pAttr ;
int
nAttr = 0 ;
int
nStartCodeOffset = 0 ;
int
nCheckpointCodeOffset = 0 ;
int
nCheckpointArrayOffset = 0 ;
tEmbperlCompilerInfo * pInfo = (tEmbperlCompilerInfo *)(*(
void
* *)r -> Component.pTokenTable) ;
tIndex xDomTree = pDomTree -> xNdx ;
pCmd = NULL ;
nNdx = Node_selfNodeNameNdx (pNode) ;
if
(nNdx <= pInfo -> nMaxEmbperlCmd)
{
pCmd = pCmdHead = &(pInfo -> pEmbperlCmds[nNdx]) ;
pCmdLast = NULL ;
}
else
pCmd = pCmdHead = pCmdLast = NULL ;
if
(r -> Component.Config.bDebug & dbgCompile)
{
char
buf[20] ;
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d -------> parent=%d node=%d type=%d text=%s (#%d,%s) %s\n"
,
r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber,
Node_parentNode (r -> pApp, pDomTree, pNode -> xNdx, 0), pNode -> xNdx,
pNode -> nType, Node_selfNodeName(pNode), nNdx, pCmd?
"compile"
:
"-"
, (pCmd && pCmd -> bRemoveNode)?(
sprintf
(buf,
"removenode=%d"
, pCmd -> bRemoveNode), buf):
""
) ;
}
if
(pCmd == NULL || (pCmd -> bRemoveNode & 1) == 0)
pDomTree -> xLastNode = xNode ;
if
(*bCheckpointPending < 0 && !(pCmd && pCmd -> nSwitchCodeType == 2) && pNode -> bFlags && (pNode -> bFlags & nflgIgnore) == 0)
{
int
l ;
char
buf [80] ;
nCheckpointArrayOffset = ArrayAdd (r -> pApp, &pDomTree -> pCheckpoints, 1) ;
pDomTree -> pCheckpoints[nCheckpointArrayOffset].xNode = xNode ;
*bCheckpointPending = 0 ;
l =
sprintf
(buf,
" _ep_cp(%d) ;\n"
, nCheckpointArrayOffset) ;
nCheckpointCodeOffset = StringAdd (r -> pApp, r -> Component.pProg, buf, l) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d L%d Checkpoint\n"
, r -> pThread -> nPid, pNode -> xNdx, pNode -> nLinenumber) ;
}
if
(pCmd && pCmd -> nSwitchCodeType == 2)
{
r -> Component.pProg = &r -> Component.pProgDef ;
nCheckpointArrayOffset = 0 ;
nCheckpointCodeOffset = 0 ;
}
if
(pCmd == NULL || (pCmd -> bRemoveNode & 8) == 0 || (pCmd -> bRemoveNode & 64))
{
int
bSaveCP = *bCheckpointPending ;
if
(pCmd && (pCmd -> bRemoveNode & 64))
*bCheckpointPending = 1 ;
while
((pAttr = Element_selfGetNthAttribut (r -> pApp, pDomTree, pNode, nAttr++)))
{
if
(pAttr -> bFlags & aflgAttrChilds)
{
tNodeData * pChild = Node_selfFirstChild (r -> pApp, pDomTree, (tNodeData *)pAttr, 0) ;
tNodeData * pNext ;
while
(pChild)
{
embperl_CompileNode (r, pDomTree, pChild -> xNdx, bCheckpointPending) ;
pDomTree = DomTree_self (xDomTree) ;
pNext = Node_selfNextSibling (r -> pApp, pDomTree, pChild, 0) ;
if
(pChild -> bFlags == 0)
Node_selfRemoveChild(r -> pApp, pDomTree, -1, pChild) ;
pChild = pNext ;
}
}
}
if
(pCmd && (pCmd -> bRemoveNode & 64))
*bCheckpointPending = bSaveCP ;
}
while
(pCmd)
{
if
((rc = embperl_CompileCmd (r, pDomTree, pNode, pCmd, &nStartCodeOffset)) != ok)
return
rc ;
pDomTree = DomTree_self (xDomTree) ;
pCmdLast = pCmd ;
pCmd = pCmd -> pNext ;
}
pCmd = pCmdLast ;
if
(pCmd)
if
((rc = embperl_CompilePostProcess (r, pDomTree, pNode, pCmd, nCheckpointCodeOffset, nCheckpointArrayOffset, bCheckpointPending)) != ok)
return
rc ;
if
(pCmd == NULL || pCmd -> bCompileChilds)
{
tNodeData * pChildNode ;
xChildNode = pNode -> bFlags?Node_firstChild (r -> pApp, pDomTree, xNode, 0):0 ;
while
(xChildNode)
{
if
((rc = embperl_CompileNode (r, pDomTree, xChildNode, bCheckpointPending)) != ok)
return
rc ;
pDomTree = DomTree_self (xDomTree) ;
pChildNode = Node_self (pDomTree, xChildNode) ;
xChildNode = Node_nextSibling (r -> pApp, pDomTree, xChildNode, 0) ;
if
(pChildNode -> bFlags == 0)
Node_selfRemoveChild(r -> pApp, pDomTree, -1, pChildNode) ;
}
}
while
(pCmd)
{
if
((rc = embperl_CompileCmdEnd (r, pDomTree, pNode, pCmd, nStartCodeOffset, bCheckpointPending)) != ok)
return
rc ;
pCmdIter = pCmdHead ;
pCmdNext = NULL ;
while
(pCmdIter && pCmdIter != pCmd)
{
pCmdNext = pCmdIter ;
pCmdIter = pCmdIter -> pNext ;
}
pCmd = pCmdNext ;
}
if
(pCmdHead && pCmdHead -> nSwitchCodeType == 2)
{
r -> Component.pProg = &r -> Component.pProgRun ;
nCheckpointArrayOffset = 0 ;
nCheckpointCodeOffset = 0 ;
}
return
ok ;
}
static
int
embperl_CompileDomTree (
tReq * r,
tDomTree * pDomTree)
{
int
rc ;
int
bCheckpointPending = 0 ;
tIndex xDomTree = pDomTree -> xNdx ;
pDomTree -> xCurrNode = 0 ;
if
((rc = embperl_CompileNode (r, pDomTree, pDomTree -> xDocument, &bCheckpointPending)) != ok)
return
rc ;
pDomTree = DomTree_self (xDomTree) ;
if
(bCheckpointPending)
{
int
l ;
char
buf [80] ;
int
nCheckpointArrayOffset = ArrayAdd (r -> pApp, &pDomTree -> pCheckpoints, 1) ;
pDomTree -> pCheckpoints[nCheckpointArrayOffset].xNode = -1 ;
l =
sprintf
(buf,
" _ep_cp(%d) ;\n"
, nCheckpointArrayOffset) ;
StringAdd (r -> pApp, r -> Component.pProg, buf, l) ;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: #%d Checkpoint\n"
, r -> pThread -> nPid, -1) ;
}
return
ok ;
}
int
embperl_Compile (
tReq * r,
tIndex xDomTree,
tIndex * pxResultDomTree,
SV * * pProg)
{
epTHX_
int
rc ;
tDomTree * pDomTree = DomTree_self (*pxResultDomTree = xDomTree) ;
char
* sSourcefile = DomTree_selfFilename (pDomTree) ;
clock_t
cl1 =
clock
() ;
clock_t
cl2 ;
clock_t
cl3 ;
clock_t
cl4 ;
STRLEN l ;
SV * pSV ;
SV * args[2] ;
int
nStep = 8192 ;
char
*use_utf8 =
""
;
if
(
strcmp
(r -> Component.Config.sInputCharset,
"utf8"
) == 0)
use_utf8 =
"use utf8;"
;
if
(r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: Start compiling %s DomTree = %d\n"
, r -> pThread -> nPid, sSourcefile, xDomTree) ;
if
(r -> Component.Config.bOptions & optChdirToSource)
ChdirToSource (r, sSourcefile) ;
r -> Component.nPhase = phCompile ;
r -> Component.pProgRun = NULL ;
r -> Component.pProgDef = NULL ;
StringNew (r -> pApp, &r -> Component.pProgRun, nStep ) ;
StringNew (r -> pApp, &r -> Component.pProgDef, nStep ) ;
r -> Component.pProg = &r -> Component.pProgRun ;
pDomTree -> pSV = (SV *)newHV () ;
if
(pDomTree -> pCheckpoints)
ArraySetSize (r -> pApp, &pDomTree -> pCheckpoints, 0) ;
else
ArrayNew (r -> pApp, &pDomTree -> pCheckpoints, 256,
sizeof
(tDomTreeCheckpoint)) ;
ArrayAdd (r -> pApp, &pDomTree -> pCheckpoints, 1) ;
pDomTree -> pCheckpoints[0].xNode = 0 ;
if
((rc = embperl_CompileDomTree (r, pDomTree)) != ok)
{
StringFree (r -> pApp, &r -> Component.pProgRun) ;
StringFree (r -> pApp, &r -> Component.pProgDef) ;
ArrayFree (r -> pApp, &pDomTree -> pCheckpoints) ;
pDomTree -> pCheckpoints = NULL ;
pDomTree = DomTree_self (xDomTree) ;
DomTree_delete (r -> pApp, pDomTree) ;
*pxResultDomTree = 0 ;
return
rc ;
}
pDomTree = DomTree_self (xDomTree) ;
SvREFCNT_dec (pDomTree -> pSV) ;
pDomTree -> pSV = NULL ;
StringAdd (r -> pApp, &r -> Component.pProgRun,
""
, 1) ;
StringAdd (r -> pApp, &r -> Component.pProgDef, r -> Component.Config.sTopInclude?r -> Component.Config.sTopInclude:
""
, 0) ;
cl2 =
clock
() ;
r -> Component.nPhase = phRunAfterCompile ;
l = ArrayGetSize (r -> pApp, r -> Component.pProgDef) ;
if
(l > 1 && r -> Component.Config.bDebug & dbgCompile)
lprintf (r -> pApp,
"[%d]EPCOMP: AfterCompileTimeCode: %*.*s\n"
, r -> pThread -> nPid, l, l, r -> Component.pProgDef) ;
if
(l > 1)
{
pSV = newSVpvf(
"package %s ; %s\n%*.*s"
, r -> Component.sEvalPackage, use_utf8, (
int
)l,(
int
)l, r -> Component.pProgDef) ;
newSVpvf2(pSV) ;
args[0] = r -> _perlsv ;
args[1] = pDomTree -> pDomTreeSV ;
if
((rc = EvalDirect (r, pSV, 0, args)) != ok)
LogError (r, rc) ;
SvREFCNT_dec(pSV);
}
cl3 =
clock
() ;
r -> Component.nPhase = phPerlCompile ;
if
(PERLDB_LINE)
{
GV * pGVFile = gv_fetchfile (sSourcefile) ;
AV * pDebugArray = GvAV (pGVFile) ;
char
* p = r -> Component.pBuf ;
char
* end ;
I32 i = 1 ;
while
(*p)
{
end =
strchr
(p,
'\n'
) ;
if
(end)
{
SV * pLine ;
pLine = newSVpv (p, end - p + 1) ;
SvUPGRADE (pLine, SVt_PVMG) ;
av_store (pDebugArray, i++, pLine) ;
p = end + 1 ;
}
else
if
(p < r -> Component.pEndPos)
{
SV * pLine ;
pLine = newSVpv (p, r -> Component.pEndPos - p + 1) ;
SvUPGRADE (pLine, SVt_PVMG) ;
av_store (pDebugArray, i++, pLine) ;
break
;
}
}
if
(r -> Component.Config.bDebug)
lprintf (r -> pApp,
"Setup source code for interactive debugger\n"
) ;
}
#if PERL_VERSION < 14
UndefSub (r, r -> Component.sMainSub, r -> Component.sCurrPackage) ;
#endif
rc = EvalOnly (r, r -> Component.pProgRun, pProg, G_SCALAR, r -> Component.sMainSub) ;
StringFree (r -> pApp, &r -> Component.pProgRun) ;
StringFree (r -> pApp, &r -> Component.pProgDef) ;
if
(rc != ok && xDomTree)
{
pDomTree = DomTree_self (xDomTree) ;
if
(pDomTree)
DomTree_delete (r -> pApp, pDomTree) ;
*pxResultDomTree = 0 ;
}
cl4 =
clock
() ;
#ifdef CLOCKS_PER_SEC
if
(r -> Component.Config.bDebug)
{
lprintf (r -> pApp,
"[%d]PERF: Compile Start Time: %d ms \n"
, r -> pThread -> nPid, ((cl1 - r -> startclock) * 1000 / CLOCKS_PER_SEC)) ;
lprintf (r -> pApp,
"[%d]PERF: Compile End Time: %d ms \n"
, r -> pThread -> nPid, ((cl2 - r -> startclock) * 1000 / CLOCKS_PER_SEC)) ;
lprintf (r -> pApp,
"[%d]PERF: After Compile Exec End Time: %d ms \n"
, r -> pThread -> nPid, ((cl3 - r -> startclock) * 1000 / CLOCKS_PER_SEC)) ;
lprintf (r -> pApp,
"[%d]PERF: Perl Compile End Time: %d ms \n"
, r -> pThread -> nPid, ((cl4 - r -> startclock) * 1000 / CLOCKS_PER_SEC)) ;
lprintf (r -> pApp,
"[%d]PERF: Compile Time: %d ms \n"
, r -> pThread -> nPid, ((cl4 - cl1) * 1000 / CLOCKS_PER_SEC)) ;
DomStats (r -> pApp) ;
}
#endif
return
rc ;
}
static
int
embperl_Execute2 (
tReq * r,
tIndex xSrcDomTree,
CV * pCV,
tIndex * pResultDomTree)
{
epTHX_
int
rc ;
tDomTree * pCurrDomTree ;
clock_t
cl1 =
clock
() ;
clock_t
cl2 ;
SV * pSV ;
char
* sSubName ;
tainted = 0 ;
r -> Component.xCurrDomTree = xSrcDomTree ;
sSubName = r -> Component.Param.sSub ;
if
(sSubName && !*sSubName)
sSubName = NULL ;
rc = ok ;
cl1 =
clock
() ;
r -> Component.nPhase = phRun ;
r -> Component.nCurrCheckpoint = 1 ;
r -> Component.nCurrRepeatLevel = 0 ;
r -> Component.xSourceDomTree = r -> Component.xCurrDomTree ;
if
(!(r -> Component.xCurrDomTree = DomTree_clone (r -> pApp, DomTree_self (xSrcDomTree), &pCurrDomTree, sSubName?1:0)))
return
1 ;
*pResultDomTree = r -> Component.xCurrDomTree ;
pCurrDomTree = DomTree_self (r -> Component.xCurrDomTree) ;
ArrayNewZero (r -> pApp, &pCurrDomTree -> pCheckpointStatus, ArrayGetSize (r -> pApp, pCurrDomTree -> pCheckpoints),
sizeof
(tDomTreeCheckpointStatus)) ;
if
(pCV)
{
SV * args[2] ;
STRLEN l ;
SV * sDomTreeSV = newSVpvf (
"%s::%s"
, r -> Component.sEvalPackage,
"_ep_DomTree"
) ;
SV * pDomTreeSV = perl_get_sv (SvPV (sDomTreeSV, l), TRUE) ;
IV xOldDomTree = 0 ;
newSVpvf2(sDomTreeSV) ;
if
(SvIOK (pDomTreeSV))
xOldDomTree = SvIVX (pDomTreeSV) ;
sv_setiv (pDomTreeSV, r -> Component.xCurrDomTree) ;
SvREFCNT_dec (sDomTreeSV) ;
av_push (r -> pCleanupAV, newRV_inc (pDomTreeSV)) ;
args[0] = r -> _perlsv ;
if
(sSubName)
{
SV * pSVName = newSVpvf (
"%s::_ep_sub_%s"
, r -> Component.sEvalPackage, sSubName) ;
newSVpvf2(pSVName) ;
pCurrDomTree -> xDocument = 0 ;
rc = CallStoredCV (r, r -> Component.pProgRun, (CV *)pSVName, 1, args, 0, &pSV) ;
if
(pSVName)
SvREFCNT_dec (pSVName) ;
if
(pSV)
SvREFCNT_dec (pSV) ;
}
else
{
rc = CallStoredCV (r, r -> Component.pProgRun, (CV *)pCV, 1, args, 0, &pSV) ;
if
(pSV)
SvREFCNT_dec (pSV) ;
}
pCurrDomTree = DomTree_self (r -> Component.xCurrDomTree) ;
cl2 =
clock
() ;
#ifdef CLOCKS_PER_SEC
if
(r -> Component.Config.bDebug)
{
lprintf (r -> pApp,
"[%d]PERF: Run Start Time: %d ms \n"
, r -> pThread -> nPid, ((cl1 - r -> startclock) * 1000 / CLOCKS_PER_SEC)) ;
lprintf (r -> pApp,
"[%d]PERF: Run End Time: %d ms \n"
, r -> pThread -> nPid, ((cl2 - r -> startclock) * 1000 / CLOCKS_PER_SEC)) ;
lprintf (r -> pApp,
"[%d]PERF: Run Time: %d ms \n"
, r -> pThread -> nPid, ((cl2 - cl1) * 1000 / CLOCKS_PER_SEC)) ;
DomStats (r -> pApp) ;
}
#endif
sv_setiv (pDomTreeSV, xOldDomTree) ;
}
ArrayFree (r -> pApp, &pCurrDomTree -> pCheckpointStatus) ;
if
(rc != ok && rc != rcEvalErr)
return
rc ;
r -> Component.nPhase = phTerm ;
return
ok ;
}
int
embperl_Execute (
tReq * r,
tIndex xSrcDomTree,
CV * pCV,
tIndex * pResultDomTree)
{
epTHX_
int
rc = ok ;
char
* sSourcefile = r -> Component.sSourcefile ;
tainted = 0 ;
if
(!r -> bError)
{
tComponent * c = &r -> Component ;
GV * gv ;
HV * pStash = gv_stashpv (c -> sCurrPackage, 1) ;
if
(r -> Component.Config.nCleanup > -1 && (r -> Component.Config.bOptions & optDisableVarCleanup) == 0)
SetHashValueInt (r, r -> pCleanupPackagesHV, r -> Component.sCurrPackage, 1) ;
if
(r -> Component.Config.bOptions & optChdirToSource)
ChdirToSource (r, sSourcefile) ;
if
(c -> Param.pParam)
{
gv = *((GV **)hv_fetch (pStash,
"param"
, 5, 0)) ;
save_ary (gv) ;
SvREFCNT_dec((SV *)GvAV(gv)) ;
GvAV(gv) = (AV *)SvREFCNT_inc(c -> Param.pParam) ;
}
if
(c -> Param.pFormHash)
{
gv = *((GV **)hv_fetch (pStash,
"fdat"
, 4, 0)) ;
save_hash (gv) ;
SvREFCNT_dec((SV *)GvHV(gv)) ;
GvHV(gv) = (HV *)SvREFCNT_inc(c -> Param.pFormHash) ;
}
if
(c -> Param.pFormArray || c -> Param.pFormHash)
{
gv = *((GV **)hv_fetch (pStash,
"ffld"
, 4, 0)) ;
save_ary (gv) ;
SvREFCNT_dec((SV *)GvAV(gv)) ;
if
(c -> Param.pFormArray)
GvAV(gv) = (AV *)SvREFCNT_inc(c -> Param.pFormArray) ;
else
{
AV * pAV = newAV ();
HE * pEntry ;
char
* pKey ;
I32 l ;
GvAV(gv) = pAV ;
hv_iterinit (c -> Param.pFormHash) ;
while
((pEntry = hv_iternext (c -> Param.pFormHash)))
{
pKey = hv_iterkey (pEntry, &l) ;
av_push (pAV, newSVpv(pKey, l)) ;
}
}
}
else
{
}
rc = embperl_Execute2 (r, xSrcDomTree, pCV, pResultDomTree) ;
if
(r -> Component.sResetDir[0])
{
#ifdef WIN32
_chdrive (r -> Component.nResetDrive) ;
#endif
chdir (r -> Component.sResetDir) ;
strcpy
(r -> Component.sCWD,r -> Component.sResetDir) ;
r -> Component.sResetDir[0] =
'\0'
;
}
}
else
*pResultDomTree = 0 ;
r -> Component.nPhase = phTerm ;
return
rc ;
}
int
embperl_ExecuteSubStart (
tReq * r,
SV * pDomTreeSV,
tIndex xDomTree,
AV * pSaveAV)
{
epTHX_
tIndex xOrgDomTree = -1 ;
tIndex xOldDomTree ;
tDomTree * pDomTree ;
tDomTree * pCurrDomTree ;
if
(!r || !r -> Component.bReqRunning)
{
LogErrorParam (r?r -> pApp:NULL, rcSubCallNotRequest,
""
,
""
) ;
return
rcSubCallNotRequest ;
}
av_push (pSaveAV, newSViv (r -> Component.xCurrDomTree)) ;
av_push (pSaveAV, newSViv (r -> Component.xCurrNode)) ;
av_push (pSaveAV, newSViv (r -> Component.nCurrRepeatLevel)) ;
av_push (pSaveAV, newSViv (r -> Component.nCurrCheckpoint)) ;
av_push (pSaveAV, newSViv (r -> Component.bSubNotEmpty)) ;
pDomTree = DomTree_self (xDomTree) ;
xOldDomTree = r -> Component.xCurrDomTree ;
if
(!(r -> Component.xCurrDomTree = DomTree_clone (r -> pApp, pDomTree, &pCurrDomTree, 1)))
return
0 ;
ArrayNewZero (r -> pApp, &pCurrDomTree -> pCheckpointStatus, ArrayGetSize (r -> pApp, pCurrDomTree -> pCheckpoints),
sizeof
(tDomTreeCheckpointStatus)) ;
r -> Component.nCurrCheckpoint = 1 ;
r -> Component.nCurrRepeatLevel = 0 ;
r -> Component.xCurrNode = 0 ;
r -> Component.bSubNotEmpty = 0 ;
pCurrDomTree -> xDocument = 0 ;
av_push (r -> pDomTreeAV, pCurrDomTree -> pDomTreeSV) ;
av_push (r -> pCleanupAV, newRV_inc (pDomTreeSV)) ;
sv_setiv (pDomTreeSV, r -> Component.xCurrDomTree) ;
if
(r -> Component.Config.bDebug & dbgRun)
lprintf (r -> pApp,
"[%d]SUB: Enter from DomTree=%d into new DomTree=%d, Source DomTree=%d (org=%d)\n"
, r -> pThread -> nPid, xOldDomTree, r -> Component.xCurrDomTree, xDomTree, xOrgDomTree) ;
return
r -> Component.xCurrDomTree ;
}
int
embperl_ExecuteSubEnd (
tReq * r,
SV * pDomTreeSV,
AV * pSaveAV)
{
epTHX_
tIndex xSubDomTree = r -> Component.xCurrDomTree ;
tIndex xDocFraq ;
int
bSubNotEmpty = r -> Component.bSubNotEmpty ;
tDomTree * pCallerDomTree ;
tDomTree * pSubDomTree = DomTree_self (xSubDomTree) ;
if
(AvFILL (pSaveAV) < 1)
return
ok ;
if
(r -> Component.xCurrNode == 0)
bSubNotEmpty = 1 ;
ArrayFree (r -> pApp, &pSubDomTree -> pCheckpointStatus) ;
r -> Component.xCurrDomTree = SvIV (* av_fetch (pSaveAV, 0, 0)) ;
r -> Component.xCurrNode = SvIV (* av_fetch (pSaveAV, 1, 0)) ;
r -> Component.nCurrRepeatLevel = (tRepeatLevel)SvIV (* av_fetch (pSaveAV, 2, 0)) ;
r -> Component.nCurrCheckpoint = SvIV (* av_fetch (pSaveAV, 3, 0)) ;
r -> Component.bSubNotEmpty = SvIV (* av_fetch (pSaveAV, 4, 0)) + bSubNotEmpty;
sv_setiv (pDomTreeSV, r -> Component.xCurrDomTree) ;
pCallerDomTree = DomTree_self (r -> Component.xCurrDomTree) ;
if
(bSubNotEmpty && r -> Component.xCurrNode)
r -> Component.xCurrNode = xDocFraq = Node_insertAfter (r -> pApp, pSubDomTree, pSubDomTree -> xDocument, 0, pCallerDomTree, r -> Component.xCurrNode, r -> Component.nCurrRepeatLevel) ;
if
(r -> Component.Config.bDebug & dbgRun)
lprintf (r -> pApp,
"[%d]SUB: Leave from DomTree=%d back to DomTree=%d RepeatLevel=%d\n"
, r -> pThread -> nPid, xSubDomTree, r -> Component.xCurrDomTree, r -> Component.nCurrRepeatLevel) ;
return
ok ;
}