/***************************************************************** DataLine::close() closes the resource attached to this data line. *****************************************************************/ eFlag DataLine::close(Sit S) { sabassert(mode != DLMODE_NONE); switch(scheme) { case URI_FILE: { sabassert(f); if (!fileIsStd) { if (fclose(f)) Err1(S, E1_URI_CLOSE, fullUri); }; f = NULL; }; break; case URI_ARG: break; case URI_EXTENSION: { if (gotWholeDocument) { NZ(handler) -> freeMemory(handlerUD, S.getProcessor(), buffer); } else { if(NZ(handler) -> close(handlerUD, S.getProcessor(), handle)) Err1(S, E1_URI_CLOSE, fullUri); } }; break; }; mode = DLMODE_CLOSED; return OK; }
eFlag DataLine::save(Sit S, const char *data, int length) { sabassert(mode == DLMODE_WRITE); // assume the file open for writing // int length = utf16Encoded ? my_wcslen(data) : strlen(data); switch (scheme) // choose the output procedure { case URI_FILE: // file: scheme { sabassert(f); // the file must be open // fputs(data, f); fwrite(data, 1, length, f); }; break; case URI_ARG: // arg: scheme { sabassert(outBuf); // the output buffer must exist outBuf -> nadd(data, length); }; break; case URI_EXTENSION: // external handler { int actual = length; if( NZ(handler) -> put(handlerUD, S.getProcessor(), handle, data, &actual) ) Err1(S, E1_URI_WRITE, fullUri); }; } return OK; }
eFlag Tree::insertRule(Sit S, XSLElement *tmpl) { double prio; Attribute *a = tmpl -> atts.find(XSLA_PRIORITY); if (!a) prio = defaultPriority(tmpl); else { if (a -> cont.toDouble(prio)) Err(S, ET_BAD_NUMBER); }; QName q; GP( QName ) mode = NULL; if (!!(a = tmpl -> atts.find(XSLA_NAME))) E( tmpl -> setLogical(S, q, a -> cont, FALSE) ); if (q.getLocal() != UNDEF_PHRASE && subtrees.getCurrent() -> getStructure() -> rules().findByName(*this, q)) { Str fullName; expandQStr(q, fullName); Err1(S, ET_DUPLICATE_RULE_NAME, fullName); }; if (!!(a = tmpl -> atts.find(XSLA_MODE))) E( tmpl -> setLogical(S, *(mode = new QName), a -> cont, FALSE) ); subtrees.getCurrent() -> getStructure() -> rules().insert(new RuleItem(tmpl,prio,q,mode.keep())); return OK; }
eFlag Tree::pushNamespacePrefixes(Sit S, Str& prefixes, XSL_ATT att) { if (!XSLTree) return OK; PList<Str*> tokens; char *p, *q; q = (char*) prefixes; skipWhite(q); p = q; int i = strcspn(q, theWhitespace); while (*q && i) { q += i; char save = *q; *q = 0; Str* aux = new Str(p); tokens.append(aux); *q = save; skipWhite(q); p = q; i = strcspn(q, theWhitespace); } //add to list SubtreeInfo *info = getCurrentInfo(); for (i = 0; i < tokens.number(); i++) { Str tok = *(tokens[i]); Phrase prefix = tok == (const char*) "#default" ? UNDEF_PHRASE : unexpand(tok); int idx = pendingNS().findNdx(prefix); if (idx != -1) { switch (att) { case XSLA_EXT_ELEM_PREFIXES: { info -> getExtensionNS().append(toNS(pendingNS()[idx]) -> uri); }; //no break case XSLA_EXCL_RES_PREFIXES: { info -> getExcludedNS().append(toNS(pendingNS()[idx]) -> uri); }; break; } } else { Str aux = *(tokens[i]); tokens.freeall(FALSE); Err1(S, E_EX_NAMESPACE_UNKNOWN, (char*) aux); } } tokens.freeall(FALSE); //printf("----------------------------\n"); return OK; }
eFlag AttSetList::executeAttSet(Sit S, QName &name, Context *c, Tree &sheet, QNameList& history, Bool resolvingGlobals) { int ndx = findNdx(name); if (ndx == -1) { Str fullName; sheet.expandQStr(name, fullName); Err1(S, E1_NONEX_ASET_NAME, fullName); } E( (*this)[ndx] -> execute(S, c, sheet, history, resolvingGlobals) ); return OK; }
eFlag Recoder::open(Sit S, const Str& enc, Bool toUTF8, CDesc& cd) { GP(ConvInfo) newitem = new ConvInfo; (*newitem).method = ENC_NONE; (*newitem).physCD = NULL; #ifdef HAVE_ICONV_H iconv_t icd = toUTF8 ? iconv_open("UTF-8", enc) : iconv_open(enc, "UTF-8"); // switch off transliteration in iconv: // sadly non-standard, only works in windows port // int val = 0; // iconvctl(icd, ICONV_SET_TRANSLITERATE, &val); if (icd != (iconv_t) -1) { (*newitem).method = ENC_ICONV; (*newitem).physCD = (void *) icd; } else #endif { // try to open internal recode void *physcd; physcd = encInternalOpen(enc, toUTF8); if (physcd != (void*)-1) { (*newitem).method = ENC_INTERNAL; (*newitem).physCD = physcd; } else { // try the encoding handler as a last resort void* enchlrUD = NULL; EncHandler *enchlr = NULL; if (S.getProcessor()) enchlr = S.getProcessor() -> getEncHandler(&enchlrUD); if (enchlr) { void *physcd = enchlr -> open(enchlrUD, S.getProcessor(), toUTF8 ? EH_TO_UTF8 : EH_FROM_UTF8, enc); if (physcd != (void*) -1) { (*newitem).method = ENC_HANDLER; (*newitem).physCD = physcd; } } } }; if ((*newitem).method != ENC_NONE) items.append(cd = newitem.keep()); else Err1(S, E1_UNKNOWN_ENC, enc); return OK; }
eFlag Tree::insertAttSet(Sit S, XSLElement *tmpl) { QName q; Attribute *a; GP( QName ) sets = NULL; if (!!(a = tmpl -> atts.find(XSLA_NAME))) E( tmpl -> setLogical(S, q, a -> cont, FALSE) ); if (q.getLocal() != UNDEF_PHRASE && attSets().findByName(q)) { Str fullName; expandQStr(q, fullName); Err1(S, ET_DUPLICATE_ASET_NAME, fullName); }; attSets().append(new AttSet(q)); return OK; }
eFlag AttSet::execute(Sit S, Context *c, Tree& sheet, QNameList& history, Bool resolvingGlobals) { if (history.findNdx(name) != -1) { Str fullName; sheet.expandQStr(name, fullName); Err1(S, E1_CIRCULAR_ASET_REF, fullName); } history.append(&name); int i; for (i = 0; i < usedSets.number(); i++) E( sheet.attSets().executeAttSet(S, *(usedSets[i]), c, sheet, history, resolvingGlobals) ); history.deppend(); for (i = 0; i < number(); i++) { XSLElement *def = (*this)[i] -> getAttributeDef(); //execute the content E( def -> execute(S, c, resolvingGlobals) ); } return OK; }
eFlag VarDirectory::insert(Sit S, QName &name, XSLElement* var) { int i = findNdx(name); if (i == -1) append(new VarDirectoryItem(name, var)); else { // if precedences are equal, raise error int oldPrec = (*this)[i] -> getElement() -> getImportPrecedence(), newPrec = var -> getImportPrecedence(); // due to immediate resolution of xsl:import, new must be <= old sabassert(newPrec <= oldPrec); (*this)[i] -> setElement(var); if (newPrec == oldPrec) { Str fullName; var -> getOwner().expandQStr(name, fullName); Err1(S, E1_MULT_ASSIGNMENT, fullName); } } return OK; }
eFlag Tree::startSubtree(Sit S, const Str& baseURI, XSL_OP dependency, Bool isInline /* = FALSE */) { // look if the URI is on the way to root of the include tree if (subtrees.findAmongPredecessors(baseURI)) Err1(S, E1_CIRCULAR_INCLUSION, baseURI); StylesheetStructure *structure; if (dependency == XSL_IMPORT) structure = createStylesheetStructure(S); else // find structure of current subtree (always defined since Tree::Tree) structure = NZ(subtrees.getCurrent()) -> getStructure(); subtrees.push( new SubtreeInfo( baseURI, dependency, structure, isInline)); excludeStdNamespaces(); //set parent tree (closest non-inline) if (isInline) for (SubtreeInfo *nfo = subtrees.getCurrent(); nfo; nfo = nfo -> getParentSubtree()) { if (!nfo -> isInline()) { subtrees.getCurrent() -> setMasterSubtree(nfo); break; } } return OK; }
eFlag Tree::processVertexAfterParse(Sit S, Vertex *v, TreeConstructer* tc) { //be careful with this test, it might be moved deeper inside this //function if needed if (v -> vt & VT_TOP_FOREIGN) { popVertex(); return OK; } XSL_OP theOp; if (isXSLElement(v)) { XSLElement *x = toX(v); theOp = x -> op; if (theOp != XSL_IMPORT) updateImportStatus(); switch(theOp) { //catch xsl:use-attribute-sets case XSL_ELEMENT: case XSL_COPY: { E( extractUsedSets(S, toE(v)) ); popVertex(); }; break; case XSL_IMPORT: { if (subtrees.getCurrent() -> getStructure() -> getTopLevelFound()) { Err2(S, E_ELEM_CONTAINS_ELEM, xslOpNames[XSL_STYLESHEET], xslOpNames[XSL_IMPORT]); } }; // no break case XSL_INCLUDE: { Attribute *a = NZ( x -> atts.find(XSLA_HREF) ); GP( Tree ) srcTree; const Str& base = S.findBaseURI(a -> getSubtreeInfo() -> getBaseURI()); Str absolute; makeAbsoluteURI(S, a -> cont, base, absolute); if (S.getProcessor()) { E( S.getProcessor() -> readTreeFromURI(S, srcTree, a -> cont, base, FALSE) ); srcTree.keep(); } else { //Str absolute; //makeAbsoluteURI(a -> cont, base, absolute); srcTree = new Tree(absolute, FALSE); DataLine d; E( d.open(S, absolute, DLMODE_READ, /* argList = */ NULL) ); E( (*srcTree).parse(S, &d) ); E( d.close(S) ); } Element *theSheet=(*srcTree).findStylesheet((*srcTree).getRoot()); if (!theSheet) Warn1(S, W_NO_STYLESHEET, (char*)(a -> cont)); dropCurrentElement(v); if (!theSheet) // to prevent segfault after include/import failure break; OutputterObj source; //we start a subtree to record where the nodes come from //when including, we use the old structure //when importing, Tree creates a new one E( startSubtree(S, (*srcTree).getURI(), theOp) ); //set extension namespaces for subtree //(*srcTree).speakDebug(); //merge it into the current tree E( tc -> parseUsingSAXForAWhile(S, source, absolute, TRUE, (Tree*)srcTree, theSheet -> namespaces) ); //first we have to deal with ext. and excl. namespaces Attribute *attr; QName q; //exclusions q.setLocal((*srcTree).unexpand("exclude-result-prefixes")); attr = theSheet->atts.find(q); if (attr) E(pushNamespacePrefixes(S, attr->cont, XSLA_EXCL_RES_PREFIXES)); //extensions q.setLocal((*srcTree).unexpand("extension-element-prefixes")); attr = theSheet->atts.find(q); if (attr) E(pushNamespacePrefixes(S, attr->cont, XSLA_EXT_ELEM_PREFIXES)); if (theSheet) E( theSheet -> contents.copy(S, source) ); E( tc -> parseUsingSAXForAWhileDone(S, source, TRUE) ); // end the subtree E( endSubtree(S, theOp) ); }; break; case XSL_OUTPUT: { int i, attsNumber = x -> atts.number(); Attribute *theAtt; for (i = 0; i < attsNumber; i++) { theAtt = toA(x -> atts[i]); switch(theAtt -> op) { case XSLA_METHOD: { QName q; EQName eq; E( x -> setLogical(S, q, theAtt -> cont, FALSE) ); expandQ(q, eq); E( outputDef.setItemEQName(S, XSLA_METHOD, eq, v, v -> getImportPrecedence()) ); }; break; case XSLA_CDATA_SECT_ELEMS: { QName q; Bool someRemains; Str listPart; char *p = theAtt -> cont; do { someRemains = getWhDelimString(p, listPart); if (someRemains) { E( x -> setLogical(S, q, listPart, TRUE) ); EQName expanded; expandQ(q, expanded); E( outputDef.setItemEQName(S, XSLA_CDATA_SECT_ELEMS, expanded, v, v -> getImportPrecedence()) ); }; } while (someRemains); }; break; case XSLA_NONE: //skip other namespaces break; default: { E( outputDef.setItemStr(S, theAtt -> op, theAtt -> cont, theAtt, theAtt -> getImportPrecedence()) ); }; }; } popVertex(); }; break; case XSL_NAMESPACE_ALIAS: { Phrase style, result, sUri, rUri; Attribute *sp = NZ( x -> atts.find(XSLA_STYLESHEET_PREFIX) ); Attribute *rp = NZ( x -> atts.find(XSLA_RESULT_PREFIX) ); if (sp -> cont == "#default") style = UNDEF_PHRASE; else dict().insert(sp -> cont, style); if (rp -> cont == "#default") result = UNDEF_PHRASE; else dict().insert(rp -> cont, result); int i; i = pendingNS().findNdx(style); if (i != -1) sUri = toNS(pendingNS().operator[](i)) -> uri; else Err1(S, E_EX_NAMESPACE_UNKNOWN, (char*) sp -> cont); i = pendingNS().findNdx(result); if (i != -1) rUri = toNS(pendingNS().operator[](i)) -> uri; else Err1(S, E_EX_NAMESPACE_UNKNOWN, (char*) rp -> cont); aliases().insertAlias(sUri, rUri, result, v -> getImportPrecedence(), x); popVertex(); }; break; case XSL_TEMPLATE: { E( insertRule(S, x) ); popVertex(); }; break; case XSL_ATTRIBUTE_SET: { QName name; E( x -> setLogical(S, name, NZ( x -> atts.find(XSLA_NAME)) -> cont, FALSE) ); AttSet *ptr = attSets().insert(name); E( extractUsedSets(S, toE(v)) ); if (x -> attSetNames(FALSE)) { for (int i = 0; i < x -> attSetNames(FALSE) -> number(); i++) ptr -> insertUses(*(x -> attSetNames(FALSE) -> operator[] (i))); } XSLElement *son; for (int i = 0; i < x -> contents.number(); i++) { sabassert(isXSLElement(x -> contents[i]) && toX(x -> contents[i]) -> op == XSL_ATTRIBUTE); son = toX(x -> contents[i]); E( son -> setLogical(S, name, NZ( son -> atts.find(XSLA_NAME)) -> cont, FALSE) ); ptr -> insertAttributeDef(son, name); } popVertex(); }; break; case XSL_STYLESHEET: case XSL_TRANSFORM: { popVertex(); }; break; case XSL_VARIABLE: case XSL_PARAM: { // only look at top-levels Vertex *par = v -> parent; if (par && isXSLElement(par) && (toX(par) -> op == XSL_STYLESHEET || toX(par) -> op == XSL_TRANSFORM)) { // is top-level -> insert into directory, //with error if there already is an entry // with the same import precedence // find name first QName name; E( x -> setLogical(S, name, NZ( x -> atts.find(XSLA_NAME)) -> cont, FALSE) ); E( toplevelVars.insert(S, name, x) ); } popVertex(); }; break; case XSL_STRIP_SPACE: { SpaceNameList &foo = subtrees.getCurrent() -> getStructure() -> strippedNames(); E( getSpaceNames(S, *x, NZ(x -> atts.find(XSLA_ELEMENTS)) -> cont, foo) ); popVertex(); }; break; case XSL_PRESERVE_SPACE: { SpaceNameList &foo = subtrees.getCurrent() -> getStructure() -> preservedNames(); E( getSpaceNames(S, *x, NZ(x -> atts.find(XSLA_ELEMENTS)) -> cont, foo) ); popVertex(); }; break; default: popVertex(); } //the literal output element may have some xsl features } else { //isXSLElement updateImportStatus(); if (XSLTree) { E( extractUsedSets(S, toE(v)) ); popVertex(); } else { popVertex(); } } return OK; }
virtual void throw_Err1() { throw Err1(); }