From 162c34f4145dd86421665054329b8e5347075d77 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Wed, 11 Dec 2002 17:53:37 +0000 Subject: [PATCH] copied over the apibuild.py from libxml2, adapted a bit and regenerated * doc/Makefile.am doc/apibuild.py doc/libxslt-api.xml: copied over the apibuild.py from libxml2, adapted a bit and regenerated the API description in XML. Todo: libexslt-api.xml * libxslt/attributes.c libxslt/documents.c libxslt/extensions.c libxslt/imports.c libxslt/numbers.c libxslt/numbersInternals.h libxslt/pattern.c libxslt/preproc.c libxslt/security.c libxslt/templates.c libxslt/transform.c libxslt/transform.h libxslt/variables.c libxslt/xslt.c libxslt/xsltInternals.h libxslt/xsltutils.c libxslt/xsltutils.h: cleanup based on the report from the scripts. * libxslt.spec.in: make sure libxslt-api.xml ends up in the devel package Daniel --- ChangeLog | 15 + doc/Makefile.am | 7 +- doc/apibuild.py | 1463 ++++++++++++++++++++++++++++++ doc/libxslt-api.xml | 2163 +++++++++++++++++++++++--------------------- libxslt.spec.in | 1 + libxslt/attributes.c | 5 +- libxslt/documents.c | 6 +- libxslt/extensions.c | 2 +- libxslt/imports.c | 18 +- libxslt/numbers.c | 2 + libxslt/numbersInternals.h | 14 +- libxslt/pattern.c | 33 - libxslt/preproc.c | 3 + libxslt/security.c | 2 +- libxslt/templates.c | 1 - libxslt/transform.c | 227 ++++- libxslt/transform.h | 5 - libxslt/variables.c | 8 +- libxslt/xslt.c | 108 ++- libxslt/xsltInternals.h | 21 + libxslt/xsltutils.c | 11 +- libxslt/xsltutils.h | 9 +- python/libxsltclass.txt | 6 + 23 files changed, 2925 insertions(+), 1205 deletions(-) create mode 100755 doc/apibuild.py diff --git a/ChangeLog b/ChangeLog index c0970cd..1eaf699 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +Wed Dec 11 18:45:09 CET 2002 Daniel Veillard + + * doc/Makefile.am doc/apibuild.py doc/libxslt-api.xml: + copied over the apibuild.py from libxml2, adapted a bit and + regenerated the API description in XML. Todo: libexslt-api.xml + * libxslt/attributes.c libxslt/documents.c libxslt/extensions.c + libxslt/imports.c libxslt/numbers.c libxslt/numbersInternals.h + libxslt/pattern.c libxslt/preproc.c libxslt/security.c + libxslt/templates.c libxslt/transform.c libxslt/transform.h + libxslt/variables.c libxslt/xslt.c libxslt/xsltInternals.h + libxslt/xsltutils.c libxslt/xsltutils.h: cleanup based on the + report from the scripts. + * libxslt.spec.in: make sure libxslt-api.xml ends up in the devel + package + Thu Dec 5 18:05:44 CET 2002 Daniel Veillard * libxslt/transform.c: xsl:element generated superfluous xmlns diff --git a/doc/Makefile.am b/doc/Makefile.am index 912e3fe..9bacca8 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -2,7 +2,8 @@ EXTRA_DIST = \ libxslt-api.xml \ libxslt-decl.txt \ - xsltproc.xml + xsltproc.xml \ + apibuild.py # The name of the module. DOC_MODULE=libxslt-$(VERSION) @@ -56,8 +57,8 @@ xml: sgml -@(for s in sgml/*.sgml ; do name=`basename $$s .sgml` ; \ xmllint --sgml $$s > xml/"$$name".xml ; done) -libxslt-api.xml libxslt-refs.xml: xml parsedecl.py libxslt-decl.txt libxslt-decl-list.txt - -(./parsedecl.py) +libxslt-api.xml: apibuild.py ../libxslt/*.h ../libxslt/*.c + -(./apibuild.py) api: libxslt-api.xml libxslt-refs.xml diff --git a/doc/apibuild.py b/doc/apibuild.py new file mode 100755 index 0000000..926d691 --- /dev/null +++ b/doc/apibuild.py @@ -0,0 +1,1463 @@ +#!/usr/bin/python -u +# +# This is the API builder, it parses the C sources and build the +# API formal description in XML. +# +# See Copyright for the status of this software. +# +# daniel@veillard.com +# +import sys +import string +import glob + +def escape(raw): + raw = string.replace(raw, '&', '&') + raw = string.replace(raw, '<', '<') + raw = string.replace(raw, '>', '>') + raw = string.replace(raw, "'", ''') + raw = string.replace(raw, '"', '"') + return raw + +class identifier: + def __init__(self, name, module=None, type=None, info=None, extra=None): + self.name = name + self.module = module + self.type = type + self.info = info + self.extra = extra + self.static = 0 + + def __repr__(self): + r = "%s %s:" % (self.type, self.name) + if self.static: + r = r + " static" + if self.module != None: + r = r + " from %s" % (self.module) + if self.info != None: + r = r + " " + `self.info` + if self.extra != None: + r = r + " " + `self.extra` + return r + + + def set_module(self, module): + self.module = module + def set_type(self, type): + self.type = type + def set_info(self, info): + self.info = info + def set_extra(self, extra): + self.extra = extra + def set_static(self, static): + self.static = static + + def update(self, module, type = None, info = None, extra=None): + if module != None and self.module == None: + self.set_module(module) + if type != None and self.type == None: + self.set_type(type) + if info != None: + self.set_info(info) + if extra != None: + self.set_extra(extra) + + +class index: + def __init__(self, name = "noname"): + self.name = name; + self.identifiers = {} + self.functions = {} + self.variables = {} + self.includes = {} + self.structs = {} + self.enums = {} + self.typedefs = {} + self.macros = {} + self.references = {} + + def add(self, name, module, static, type, info=None, extra=None): + if name[0:2] == '__': + return None + d = None + try: + d = self.identifiers[name] + d.update(module, type, info, extra) + except: + d = identifier(name, module, type, info, extra) + self.identifiers[name] = d + + if d != None and static == 1: + d.set_static(1) + + if d != None and name != None and type != None: + if type == "function": + self.functions[name] = d + elif type == "functype": + self.functions[name] = d + elif type == "variable": + self.variables[name] = d + elif type == "include": + self.includes[name] = d + elif type == "struct": + self.structs[name] = d + elif type == "enum": + self.enums[name] = d + elif type == "typedef": + self.typedefs[name] = d + elif type == "macro": + self.macros[name] = d + else: + print "Unable to register type ", type + return d + + def merge(self, idx): + for id in idx.functions.keys(): + # + # macro might be used to override functions or variables + # definitions + # + if self.macros.has_key(id): + del self.macros[id] + if self.functions.has_key(id): + print "function %s from %s redeclared in %s" % ( + id, self.functions[id].module, idx.functions[id].module) + else: + self.functions[id] = idx.functions[id] + self.identifiers[id] = idx.functions[id] + for id in idx.variables.keys(): + # + # macro might be used to override functions or variables + # definitions + # + if self.macros.has_key(id): + del self.macros[id] + if self.variables.has_key(id): + print "variable %s from %s redeclared in %s" % ( + id, self.variables[id].module, idx.variables[id].module) + else: + self.variables[id] = idx.variables[id] + self.identifiers[id] = idx.variables[id] + for id in idx.structs.keys(): + if self.structs.has_key(id): + print "struct %s from %s redeclared in %s" % ( + id, self.structs[id].module, idx.structs[id].module) + else: + self.structs[id] = idx.structs[id] + self.identifiers[id] = idx.structs[id] + for id in idx.typedefs.keys(): + if self.typedefs.has_key(id): + print "typedef %s from %s redeclared in %s" % ( + id, self.typedefs[id].module, idx.typedefs[id].module) + else: + self.typedefs[id] = idx.typedefs[id] + self.identifiers[id] = idx.typedefs[id] + for id in idx.macros.keys(): + # + # macro might be used to override functions or variables + # definitions + # + if self.variables.has_key(id): + continue + if self.functions.has_key(id): + continue + if self.enums.has_key(id): + continue + if self.macros.has_key(id): + print "macro %s from %s redeclared in %s" % ( + id, self.macros[id].module, idx.macros[id].module) + else: + self.macros[id] = idx.macros[id] + self.identifiers[id] = idx.macros[id] + for id in idx.enums.keys(): + if self.enums.has_key(id): + print "enum %s from %s redeclared in %s" % ( + id, self.enums[id].module, idx.enums[id].module) + else: + self.enums[id] = idx.enums[id] + self.identifiers[id] = idx.enums[id] + + def merge_public(self, idx): + for id in idx.functions.keys(): + if self.functions.has_key(id): + up = idx.functions[id] + self.functions[id].update(None, up.type, up.info, up.extra) + else: + if idx.functions[id].static == 0: + self.functions[id] = idx.functions[id] + + def analyze_dict(self, type, dict): + count = 0 + public = 0 + for name in dict.keys(): + id = dict[name] + count = count + 1 + if id.static == 0: + public = public + 1 + if count != public: + print " %d %s , %d public" % (count, type, public) + elif count != 0: + print " %d public %s" % (count, type) + + + def analyze(self): + self.analyze_dict("functions", self.functions) + self.analyze_dict("variables", self.variables) + self.analyze_dict("structs", self.structs) + self.analyze_dict("typedefs", self.typedefs) + self.analyze_dict("macros", self.macros) + +# +# C parser analysis code +# +ignored_files = { + "trio": "too many non standard macros", + "trio.c": "too many non standard macros", + "trionan.c": "too many non standard macros", + "triostr.c": "too many non standard macros", + "acconfig.h": "generated portability layer", + "config.h": "generated portability layer", + "libxml.h": "internal only", +} + +ignored_words = { + "WINAPI": (0, "Windows keyword"), + "LIBXML_DLL_IMPORT": (0, "Special macro to flag external keywords"), + "__declspec": (3, "Windows keyword"), + "ATTRIBUTE_UNUSED": (0, "macro keyword"), +} + +class CLexer: + """A lexer for the C language, tokenize the input by reading and + analyzing it line by line""" + def __init__(self, input): + self.input = input + self.tokens = [] + self.line = "" + self.lineno = 0 + + def getline(self): + line = '' + while line == '': + line = self.input.readline() + if not line: + return None + self.lineno = self.lineno + 1 + line = string.lstrip(line) + line = string.rstrip(line) + if line == '': + continue + while line[-1] == '\\': + line = line[:-1] + n = self.input.readline() + self.lineno = self.lineno + 1 + n = string.lstrip(n) + n = string.rstrip(n) + if not n: + break + else: + line = line + n + return line + + def getlineno(self): + return self.lineno + + def push(self, token): + self.tokens.insert(0, token); + + def debug(self): + print "Last token: ", self.last + print "Token queue: ", self.tokens + print "Line %d end: " % (self.lineno), self.line + + def token(self): + while self.tokens == []: + if self.line == "": + line = self.getline() + else: + line = self.line + self.line = "" + if line == None: + return None + + if line[0] == '#': + self.tokens = map((lambda x: ('preproc', x)), + string.split(line)) + break; + l = len(line) + if line[0] == '"' or line[0] == "'": + end = line[0] + line = line[1:] + found = 0 + tok = "" + while found == 0: + i = 0 + l = len(line) + while i < l: + if line[i] == end: + self.line = line[i+1:] + line = line[:i] + l = i + found = 1 + break + if line[i] == '\\': + i = i + 1 + i = i + 1 + tok = tok + line + if found == 0: + line = self.getline() + if line == None: + return None + self.last = ('string', tok) + return self.last + + if l >= 2 and line[0] == '/' and line[1] == '*': + line = line[2:] + found = 0 + tok = "" + while found == 0: + i = 0 + l = len(line) + while i < l: + if line[i] == '*' and i+1 < l and line[i+1] == '/': + self.line = line[i+2:] + line = line[:i-1] + l = i + found = 1 + break + i = i + 1 + if tok != "": + tok = tok + "\n" + tok = tok + line + if found == 0: + line = self.getline() + if line == None: + return None + self.last = ('comment', tok) + return self.last + if l >= 2 and line[0] == '/' and line[1] == '/': + line = line[2:] + self.last = ('comment', line) + return self.last + i = 0 + while i < l: + if line[i] == '/' and i+1 < l and line[i+1] == '/': + self.line = line[i:] + line = line[:i] + break + if line[i] == '/' and i+1 < l and line[i+1] == '*': + self.line = line[i:] + line = line[:i] + break + if line[i] == '"' or line[i] == "'": + self.line = line[i:] + line = line[:i] + break + i = i + 1 + l = len(line) + i = 0 + while i < l: + if line[i] == ' ' or line[i] == '\t': + i = i + 1 + continue + o = ord(line[i]) + if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ + (o >= 48 and o <= 57): + s = i + while i < l: + o = ord(line[i]) + if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ + (o >= 48 and o <= 57) or string.find( + " \t(){}:;,+-*/%&!|[]=><", line[i]) == -1: + i = i + 1 + else: + break + self.tokens.append(('name', line[s:i])) + continue + if string.find("(){}:;,[]", line[i]) != -1: +# if line[i] == '(' or line[i] == ')' or line[i] == '{' or \ +# line[i] == '}' or line[i] == ':' or line[i] == ';' or \ +# line[i] == ',' or line[i] == '[' or line[i] == ']': + self.tokens.append(('sep', line[i])) + i = i + 1 + continue + if string.find("+-*><=/%&!|.", line[i]) != -1: +# if line[i] == '+' or line[i] == '-' or line[i] == '*' or \ +# line[i] == '>' or line[i] == '<' or line[i] == '=' or \ +# line[i] == '/' or line[i] == '%' or line[i] == '&' or \ +# line[i] == '!' or line[i] == '|' or line[i] == '.': + if line[i] == '.' and i + 2 < l and \ + line[i+1] == '.' and line[i+2] == '.': + self.tokens.append(('name', '...')) + i = i + 3 + continue + + j = i + 1 + if j < l and ( + string.find("+-*><=/%&!|", line[j]) != -1): +# line[j] == '+' or line[j] == '-' or line[j] == '*' or \ +# line[j] == '>' or line[j] == '<' or line[j] == '=' or \ +# line[j] == '/' or line[j] == '%' or line[j] == '&' or \ +# line[j] == '!' or line[j] == '|'): + self.tokens.append(('op', line[i:j+1])) + i = j + 1 + else: + self.tokens.append(('op', line[i])) + i = i + 1 + continue + s = i + while i < l: + o = ord(line[i]) + if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ + (o >= 48 and o <= 57) or ( + string.find(" \t(){}:;,+-*/%&!|[]=><", line[i]) == -1): +# line[i] != ' ' and line[i] != '\t' and +# line[i] != '(' and line[i] != ')' and +# line[i] != '{' and line[i] != '}' and +# line[i] != ':' and line[i] != ';' and +# line[i] != ',' and line[i] != '+' and +# line[i] != '-' and line[i] != '*' and +# line[i] != '/' and line[i] != '%' and +# line[i] != '&' and line[i] != '!' and +# line[i] != '|' and line[i] != '[' and +# line[i] != ']' and line[i] != '=' and +# line[i] != '*' and line[i] != '>' and +# line[i] != '<'): + i = i + 1 + else: + break + self.tokens.append(('name', line[s:i])) + + tok = self.tokens[0] + self.tokens = self.tokens[1:] + self.last = tok + return tok + +class CParser: + """The C module parser""" + def __init__(self, filename, idx = None): + self.filename = filename + if len(filename) > 2 and filename[-2:] == '.h': + self.is_header = 1 + else: + self.is_header = 0 + self.input = open(filename) + self.lexer = CLexer(self.input) + if idx == None: + self.index = index() + else: + self.index = idx + self.top_comment = "" + self.last_comment = "" + self.comment = None + + def lineno(self): + return self.lexer.getlineno() + + def error(self, msg, token=-1): + print "Parse Error: " + msg + if token != -1: + print "Got token ", token + self.lexer.debug() + sys.exit(1) + + def debug(self, msg, token=-1): + print "Debug: " + msg + if token != -1: + print "Got token ", token + self.lexer.debug() + + def parseComment(self, token): + if self.top_comment == "": + self.top_comment = token[1] + if self.comment == None or token[1][0] == '*': + self.comment = token[1]; + else: + self.comment = self.comment + token[1] + token = self.lexer.token() + return token + + # + # Parse a comment block associate to a macro + # + def parseMacroComment(self, name, quiet = 0): + if name[0:2] == '__': + quiet = 1 + + args = [] + desc = "" + + if self.comment == None: + if not quiet: + print "Missing comment for macro %s" % (name) + return((args, desc)) + if self.comment[0] != '*': + if not quiet: + print "Missing * in macro comment for %s" % (name) + return((args, desc)) + lines = string.split(self.comment, '\n') + if lines[0] == '*': + del lines[0] + if lines[0] != "* %s:" % (name): + if not quiet: + print "Misformatted macro comment for %s" % (name) + print " Expecting '* %s:' got '%s'" % (name, lines[0]) + return((args, desc)) + del lines[0] + while lines[0] == '*': + del lines[0] + while len(lines) > 0 and lines[0][0:3] == '* @': + l = lines[0][3:] + try: + (arg, desc) = string.split(l, ':', 1) + desc=string.strip(desc) + arg=string.strip(arg) + except: + if not quiet: + print "Misformatted macro comment for %s" % (name) + print " problem with '%s'" % (lines[0]) + del lines[0] + continue + del lines[0] + l = string.strip(lines[0]) + while len(l) > 2 and l[0:3] != '* @': + while l[0] == '*': + l = l[1:] + desc = desc + ' ' + string.strip(l) + del lines[0] + if len(lines) == 0: + break + l = lines[0] + args.append((arg, desc)) + while len(lines) > 0 and lines[0] == '*': + del lines[0] + desc = "" + while len(lines) > 0: + l = lines[0] + while len(l) > 0 and l[0] == '*': + l = l[1:] + l = string.strip(l) + desc = desc + " " + l + del lines[0] + + desc = string.strip(desc) + + if quiet == 0: + if desc == "": + print "Macro comment for %s lack description of the macro" % (name) + + return((args, desc)) + + # + # Parse a comment block and merge the informations found in the + # parameters descriptions, finally returns a block as complete + # as possible + # + def mergeFunctionComment(self, name, description, quiet = 0): + if name == 'main': + quiet = 1 + if name[0:2] == '__': + quiet = 1 + + (ret, args) = description + desc = "" + retdesc = "" + + if self.comment == None: + if not quiet: + print "Missing comment for function %s" % (name) + return(((ret[0], retdesc), args, desc)) + if self.comment[0] != '*': + if not quiet: + print "Missing * in function comment for %s" % (name) + return(((ret[0], retdesc), args, desc)) + lines = string.split(self.comment, '\n') + if lines[0] == '*': + del lines[0] + if lines[0] != "* %s:" % (name): + if not quiet: + print "Misformatted function comment for %s" % (name) + print " Expecting '* %s:' got '%s'" % (name, lines[0]) + return(((ret[0], retdesc), args, desc)) + del lines[0] + while lines[0] == '*': + del lines[0] + nbargs = len(args) + while len(lines) > 0 and lines[0][0:3] == '* @': + l = lines[0][3:] + try: + (arg, desc) = string.split(l, ':', 1) + desc=string.strip(desc) + arg=string.strip(arg) + except: + if not quiet: + print "Misformatted function comment for %s" % (name) + print " problem with '%s'" % (lines[0]) + del lines[0] + continue + del lines[0] + l = string.strip(lines[0]) + while len(l) > 2 and l[0:3] != '* @': + while l[0] == '*': + l = l[1:] + desc = desc + ' ' + string.strip(l) + del lines[0] + if len(lines) == 0: + break + l = lines[0] + i = 0 + while i < nbargs: + if args[i][1] == arg: + args[i] = (args[i][0], arg, desc) + break; + i = i + 1 + if i >= nbargs: + if not quiet: + print "Uname to find arg %s from function comment for %s" % ( + arg, name) + while len(lines) > 0 and lines[0] == '*': + del lines[0] + desc = "" + while len(lines) > 0: + l = lines[0] + while len(l) > 0 and l[0] == '*': + l = l[1:] + l = string.strip(l) + if len(l) >= 6 and l[0:6] == "return" or l[0:6] == "Return": + try: + l = string.split(l, ' ', 1)[1] + except: + l = "" + retdesc = string.strip(l) + del lines[0] + while len(lines) > 0: + l = lines[0] + while len(l) > 0 and l[0] == '*': + l = l[1:] + l = string.strip(l) + retdesc = retdesc + " " + l + del lines[0] + else: + desc = desc + " " + l + del lines[0] + + retdesc = string.strip(retdesc) + desc = string.strip(desc) + + if quiet == 0: + # + # report missing comments + # + i = 0 + while i < nbargs: + if args[i][2] == None and args[i][0] != "void" and args[i][1] != None: + print "Function comment for %s lack description of arg %s" % (name, args[i][1]) + i = i + 1 + if retdesc == "" and ret[0] != "void": + print "Function comment for %s lack description of return value" % (name) + if desc == "": + print "Function comment for %s lack description of the function" % (name) + + + return(((ret[0], retdesc), args, desc)) + + def parsePreproc(self, token): + name = token[1] + if name == "#include": + token = self.lexer.token() + if token == None: + return None + if token[0] == 'preproc': + self.index.add(token[1], self.filename, not self.is_header, + "include") + return self.lexer.token() + return token + if name == "#define": + token = self.lexer.token() + if token == None: + return None + if token[0] == 'preproc': + # TODO macros with arguments + name = token[1] + lst = [] + token = self.lexer.token() + while token != None and token[0] == 'preproc' and \ + token[1][0] != '#': + lst.append(token[1]) + token = self.lexer.token() + try: + name = string.split(name, '(') [0] + except: + pass + info = self.parseMacroComment(name, not self.is_header) + self.index.add(name, self.filename, not self.is_header, + "macro", info) + return token + token = self.lexer.token() + while token != None and token[0] == 'preproc' and \ + token[1][0] != '#': + token = self.lexer.token() + return token + + # + # token acquisition on top of the lexer, it handle internally + # preprocessor and comments since they are logically not part of + # the program structure. + # + def token(self): + global ignored_words + + token = self.lexer.token() + while token != None: + if token[0] == 'comment': + token = self.parseComment(token) + continue + elif token[0] == 'preproc': + token = self.parsePreproc(token) + continue + elif token[0] == "name" and ignored_words.has_key(token[1]): + (n, info) = ignored_words[token[1]] + i = 0 + while i < n: + token = self.lexer.token() + i = i + 1 + token = self.lexer.token() + continue + else: + #print "=> ", token + return token + return None + + # + # Parse a typedef, it records the type and its name. + # + def parseTypedef(self, token): + if token == None: + return None + token = self.parseType(token) + if token == None: + self.error("parsing typedef") + return None + base_type = self.type + type = base_type + #self.debug("end typedef type", token) + while token != None: + if token[0] == "name": + name = token[1] + signature = self.signature + if signature != None: + d = self.mergeFunctionComment(name, + ((type, None), signature), 1) + self.index.add(name, self.filename, not self.is_header, + "functype", d) + else: + if base_type == "struct": + self.index.add(name, self.filename, not self.is_header, + "struct", type) + base_type = "struct " + name + else: + self.index.add(name, self.filename, not self.is_header, + "typedef", type) + token = self.token() + else: + self.error("parsing typedef: expecting a name") + return token + #self.debug("end typedef", token) + if token != None and token[0] == 'sep' and token[1] == ',': + type = base_type + token = self.token() + while token != None and token[0] == "op": + type = type + token[1] + token = self.token() + elif token != None and token[0] == 'sep' and token[1] == ';': + break; + elif token != None and token[0] == 'name': + type = base_type + continue; + else: + self.error("parsing typedef: expecting ';'", token) + return token + token = self.token() + return token + + # + # Parse a C code block, used for functions it parse till + # the balancing } included + # + def parseBlock(self, token): + while token != None: + if token[0] == "sep" and token[1] == "{": + token = self.token() + token = self.parseBlock(token) + elif token[0] == "sep" and token[1] == "}": + self.comment = None + token = self.token() + return token + else: + token = self.token() + return token + + # + # Parse a C struct definition till the balancing } + # + def parseStruct(self, token): + fields = [] + #self.debug("start parseStruct", token) + while token != None: + if token[0] == "sep" and token[1] == "{": + token = self.token() + token = self.parseTypeBlock(token) + elif token[0] == "sep" and token[1] == "}": + self.struct_fields = fields + #self.debug("end parseStruct", token) + #print fields + token = self.token() + return token + else: + base_type = self.type + #self.debug("before parseType", token) + token = self.parseType(token) + #self.debug("after parseType", token) + if token != None and token[0] == "name": + fname = token[1] + token = self.token() + if token[0] == "sep" and token[1] == ";": + self.comment = None + token = self.token() + fields.append((self.type, fname, self.comment)) + self.comment = None + else: + self.error("parseStruct: expecting ;", token) + elif token != None and token[0] == "sep" and token[1] == "{": + token = self.token() + token = self.parseTypeBlock(token) + if token != None and token[0] == "name": + token = self.token() + if token != None and token[0] == "sep" and token[1] == ";": + token = self.token() + else: + self.error("parseStruct: expecting ;", token) + else: + self.error("parseStruct: name", token) + token = self.token() + self.type = base_type; + self.struct_fields = fields + #self.debug("end parseStruct", token) + #print fields + return token + + # + # Parse a C enum block, parse till the balancing } + # + def parseEnumBlock(self, token): + self.enums = [] + name = None + self.comment = None + comment = "" + value = "" + while token != None: + if token[0] == "sep" and token[1] == "{": + token = self.token() + token = self.parseTypeBlock(token) + elif token[0] == "sep" and token[1] == "}": + if name != None: + if self.comment != None: + comment = self.comment + self.comment = None + self.enums.append((name, value, comment)) + token = self.token() + return token + elif token[0] == "name": + if name != None: + if self.comment != None: + comment = string.strip(self.comment) + self.comment = None + self.enums.append((name, value, comment)) + name = token[1] + comment = "" + value = "" + token = self.token() + if token[0] == "op" and token[1][0] == "=": + if len(token[1]) > 1: + value = token[1][1:] + token = self.token() + while token[0] != "sep" or (token[1] != ',' and + token[1] != '}'): + value = value + token[1] + token = self.token() + if token[0] == "sep" and token[1] == ",": + token = self.token() + else: + token = self.token() + return token + + # + # Parse a C definition block, used for structs it parse till + # the balancing } + # + def parseTypeBlock(self, token): + while token != None: + if token[0] == "sep" and token[1] == "{": + token = self.token() + token = self.parseTypeBlock(token) + elif token[0] == "sep" and token[1] == "}": + token = self.token() + return token + else: + token = self.token() + return token + + # + # Parse a type: the fact that the type name can either occur after + # the definition or within the definition makes it a little harder + # if inside, the name token is pushed back before returning + # + def parseType(self, token): + self.type = "" + self.struct_fields = [] + self.signature = None + if token == None: + return token + + while token[0] == "name" and ( + token[1] == "const" or token[1] == "unsigned"): + if self.type == "": + self.type = token[1] + else: + self.type = self.type + " " + token[1] + token = self.token() + + if token[0] == "name" and (token[1] == "long" or token[1] == "short"): + if self.type == "": + self.type = token[1] + else: + self.type = self.type + " " + token[1] + if token[0] == "name" and token[1] == "int": + if self.type == "": + self.type = tmp[1] + else: + self.type = self.type + " " + tmp[1] + + elif token[0] == "name" and token[1] == "struct": + if self.type == "": + self.type = token[1] + else: + self.type = self.type + " " + token[1] + token = self.token() + nametok = None + if token[0] == "name": + nametok = token + token = self.token() + if token != None and token[0] == "sep" and token[1] == "{": + token = self.token() + token = self.parseStruct(token) + elif token != None and token[0] == "op" and token[1] == "*": + self.type = self.type + " " + nametok[1] + " *" + token = self.token() + while token != None and token[0] == "op" and token[1] == "*": + self.type = self.type + " *" + token = self.token() + if token[0] == "name": + nametok = token + token = self.token() + else: + self.error("struct : expecting name", token) + return token + elif token != None and token[0] == "name" and nametok != None: + self.type = self.type + " " + nametok[1] + return token + + if nametok != None: + self.lexer.push(token) + token = nametok + return token + + elif token[0] == "name" and token[1] == "enum": + if self.type == "": + self.type = token[1] + else: + self.type = self.type + " " + token[1] + self.enums = [] + token = self.token() + if token != None and token[0] == "sep" and token[1] == "{": + token = self.token() + token = self.parseEnumBlock(token) + else: + self.error("parsing enum: expecting '{'", token) + enum_type = None + if token != None and token[0] != "name": + self.lexer.push(token) + token = ("name", "enum") + else: + enum_type = token[1] + for enum in self.enums: + self.index.add(enum[0], self.filename, + not self.is_header, "enum", + (enum[1], enum[2], enum_type)) + return token + + elif token[0] == "name": + if self.type == "": + self.type = token[1] + else: + self.type = self.type + " " + token[1] + else: + self.error("parsing type %s: expecting a name" % (self.type), + token) + return token + token = self.token() + while token != None and (token[0] == "op" or + token[0] == "name" and token[1] == "const"): + self.type = self.type + " " + token[1] + token = self.token() + + # + # if there is a parenthesis here, this means a function type + # + if token != None and token[0] == "sep" and token[1] == '(': + self.type = self.type + token[1] + token = self.token() + while token != None and token[0] == "op" and token[1] == '*': + self.type = self.type + token[1] + token = self.token() + if token == None or token[0] != "name" : + self.error("parsing function type, name expected", token); + return token + self.type = self.type + token[1] + nametok = token + token = self.token() + if token != None and token[0] == "sep" and token[1] == ')': + self.type = self.type + token[1] + token = self.token() + if token != None and token[0] == "sep" and token[1] == '(': + token = self.token() + type = self.type; + token = self.parseSignature(token); + self.type = type; + else: + self.error("parsing function type, '(' expected", token); + return token + else: + self.error("parsing function type, ')' expected", token); + return token + self.lexer.push(token) + token = nametok + return token + + # + # do some lookahead for arrays + # + if token != None and token[0] == "name": + nametok = token + token = self.token() + if token != None and token[0] == "sep" and token[1] == '[': + self.type = self.type + nametok[1] + while token != None and token[0] == "sep" and token[1] == '[': + self.type = self.type + token[1] + token = self.token() + while token != None and token[0] != 'sep' and \ + token[1] != ']' and token[1] != ';': + self.type = self.type + token[1] + token = self.token() + if token != None and token[0] == 'sep' and token[1] == ']': + self.type = self.type + token[1] + token = self.token() + else: + self.error("parsing array type, ']' expected", token); + return token + elif token != None and token[0] == "sep" and token[1] == ':': + # remove :12 in case it's a limited int size + token = self.token() + token = self.token() + self.lexer.push(token) + token = nametok + + return token + + # + # Parse a signature: '(' has been parsed and we scan the type definition + # up to the ')' included + def parseSignature(self, token): + signature = [] + if token != None and token[0] == "sep" and token[1] == ')': + self.signature = [] + token = self.token() + return token + while token != None: + token = self.parseType(token) + if token != None and token[0] == "name": + signature.append((self.type, token[1], None)) + token = self.token() + elif token != None and token[0] == "sep" and token[1] == ',': + token = self.token() + continue + elif token != None and token[0] == "sep" and token[1] == ')': + # only the type was provided + if self.type == "...": + signature.append((self.type, "...", None)) + else: + signature.append((self.type, None, None)) + if token != None and token[0] == "sep": + if token[1] == ',': + token = self.token() + continue + elif token[1] == ')': + token = self.token() + break + self.signature = signature + return token + + # + # Parse a global definition, be it a type, variable or function + # the extern "C" blocks are a bit nasty and require it to recurse. + # + def parseGlobal(self, token): + static = 0 + if token[1] == 'extern': + token = self.token() + if token == None: + return token + if token[0] == 'string': + if token[1] == 'C': + token = self.token() + if token == None: + return token + if token[0] == 'sep' and token[1] == "{": + token = self.token() +# print 'Entering extern "C line ', self.lineno() + while token != None and (token[0] != 'sep' or + token[1] != "}"): + if token[0] == 'name': + token = self.parseGlobal(token) + else: + self.error( + "token %s %s unexpected at the top level" % ( + token[0], token[1])) + token = self.parseGlobal(token) +# print 'Exiting extern "C" line', self.lineno() + token = self.token() + return token + else: + return token + elif token[1] == 'static': + static = 1 + token = self.token() + if token == None or token[0] != 'name': + return token + + if token[1] == 'typedef': + token = self.token() + return self.parseTypedef(token) + else: + token = self.parseType(token) + type_orig = self.type + if token == None or token[0] != "name": + return token + type = type_orig + self.name = token[1] + token = self.token() + while token != None and (token[0] == "sep" or token[0] == "op"): + if token[0] == "sep": + if token[1] == "[": + type = type + token[1] + token = self.token() + while token != None and (token[0] != "sep" or \ + token[1] != ";"): + type = type + token[1] + token = self.token() + + if token != None and token[0] == "op" and token[1] == "=": + # + # Skip the initialization of the variable + # + token = self.token() + if token[0] == 'sep' and token[1] == '{': + token = self.token() + token = self.parseBlock(token) + else: + self.comment = None + while token != None and (token[0] != "sep" or \ + (token[1] != ';' and token[1] != ',')): + token = self.token() + self.comment = None + if token == None or token[0] != "sep" or (token[1] != ';' and + token[1] != ','): + self.error("missing ';' or ',' after value") + + if token != None and token[0] == "sep": + if token[1] == ";": + self.comment = None + token = self.token() + if type == "struct": + self.index.add(self.name, self.filename, + not self.is_header, "struct", self.struct_fields) + else: + self.index.add(self.name, self.filename, + not self.is_header, "variable", type) + break + elif token[1] == "(": + token = self.token() + token = self.parseSignature(token) + if token == None: + return None + if token[0] == "sep" and token[1] == ";": + d = self.mergeFunctionComment(self.name, + ((type, None), self.signature), 1) + self.index.add(self.name, self.filename, static, + "function", d) + token = self.token() + if token[0] == "sep" and token[1] == "{": + d = self.mergeFunctionComment(self.name, + ((type, None), self.signature), static) + self.index.add(self.name, self.filename, static, + "function", d) + token = self.token() + token = self.parseBlock(token); + elif token[1] == ',': + self.comment = None + self.index.add(self.name, self.filename, static, + "variable", type) + type = type_orig + token = self.token() + while token != None and token[0] == "sep": + type = type + token[1] + token = self.token() + if token != None and token[0] == "name": + self.name = token[1] + token = self.token() + else: + break + + return token + + def parse(self): + print "Parsing %s" % (self.filename) + token = self.token() + while token != None: + if token[0] == 'name': + token = self.parseGlobal(token) + else: + self.error("token %s %s unexpected at the top level" % ( + token[0], token[1])) + token = self.parseGlobal(token) + return + return self.index + + +class docBuilder: + """A documentation builder""" + def __init__(self, name, directories=['.'], excludes=[]): + self.name = name + self.directories = directories + self.excludes = excludes + ignored_files.keys() + self.modules = {} + self.headers = {} + self.idx = index() + + def analyze(self): + print "Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys())) + self.idx.analyze() + + def scanHeaders(self): + for header in self.headers.keys(): + parser = CParser(header) + idx = parser.parse() + self.headers[header] = idx; + self.idx.merge(idx) + + def scanModules(self): + for module in self.modules.keys(): + parser = CParser(module) + idx = parser.parse() + # idx.analyze() + self.modules[module] = idx + self.idx.merge_public(idx) + + def scan(self): + for directory in self.directories: + files = glob.glob(directory + "/*.c") + for file in files: + skip = 0 + for excl in self.excludes: + if string.find(file, excl) != -1: + skip = 1; + break + if skip == 0: + self.modules[file] = None; + files = glob.glob(directory + "/*.h") + for file in files: + skip = 0 + for excl in self.excludes: + if string.find(file, excl) != -1: + skip = 1; + break + if skip == 0: + self.headers[file] = None; + self.scanHeaders() + self.scanModules() + + def modulename_file(self, file): + module = string.split(file, '/')[-1] + if module[-2:] == '.h': + module = module[:-2] + return module + + def serialize_enum(self, output, name): + id = self.idx.enums[name] + output.write(" \n") + + def serialize_macro(self, output, name): + id = self.idx.macros[name] + output.write(" \n" % (name, + self.modulename_file(id.module))) + if id.info != None: + try: + (args, desc) = id.info + if desc != None and desc != "": + output.write(" %s\n" % (escape(desc))) + for arg in args: + (name, desc) = arg + if desc != None and desc != "": + output.write(" \n" % ( + name, escape(desc))) + else: + output.write(" \n" % (name)) + except: + pass + output.write(" \n") + + def serialize_typedef(self, output, name): + id = self.idx.typedefs[name] + if id.info[0:7] == 'struct ': + output.write(" \n"); + try: + for field in self.idx.structs[name].info: + print name, field + desc = field[2] + if desc == None: + desc = '' + else: + desc = escape(desc) + output.write(" \n" % (field[1] , field[0], desc)) + except: + print "Failed to serialize struct %s" % (name) + output.write(" \n") + else: + output.write("/>\n"); + else : + output.write(" \n" % ( + name, self.modulename_file(id.module), id.info)) + + def serialize_function(self, output, name): + id = self.idx.functions[name] + output.write(" <%s name='%s' file='%s'>\n" % (id.type, name, + self.modulename_file(id.module))) + try: + (ret, params, desc) = id.info + output.write(" %s\n" % (escape(desc))) + if ret[0] != None: + if ret[0] == "void": + output.write(" \n") + else: + output.write(" \n" % ( + ret[0], escape(ret[1]))) + for param in params: + if param[0] == 'void': + continue + if param[2] == None: + output.write(" \n" % (param[1], param[0])) + else: + output.write(" \n" % (param[1], param[0], escape(param[2]))) + except: + print "Failed to save function %s info: " % name, `id.info` + output.write(" \n" % (id.type)) + + def serialize_exports(self, output, file): + module = self.modulename_file(file) + output.write(" \n" % (module)) + dict = self.headers[file] + ids = dict.functions.keys() + dict.variables.keys() + \ + dict.macros.keys() + dict.typedefs.keys() + \ + dict.structs.keys() + dict.enums.keys() + ids.sort() + for id in ids: + output.write(" \n" % (id)) + output.write(" \n") + + + def serialize(self, filename = None): + if filename == None: + filename = "%s-api.xml" % self.name + print "Saving XML description %s" % (filename) + output = open(filename, "w") + output.write('\n') + output.write("\n" % self.name) + output.write(" \n") + for file in self.headers.keys(): + self.serialize_exports(output, file) + output.write(" \n") + output.write(" \n") + macros = self.idx.macros.keys() + macros.sort() + for macro in macros: + self.serialize_macro(output, macro) + enums = self.idx.enums.keys() + enums.sort() + for enum in enums: + self.serialize_enum(output, enum) + typedefs = self.idx.typedefs.keys() + typedefs.sort() + for typedef in typedefs: + self.serialize_typedef(output, typedef) + functions = self.idx.functions.keys() + functions.sort() + for function in functions: + self.serialize_function(output, function) + output.write(" \n") + output.write("\n") + output.close() + + +def rebuild(): + builder = None + if glob.glob("../parser.c") != [] : + print "Rebuilding API description for libxml2" + builder = docBuilder("libxml2", ["..", "../include/libxml"], + ["xmlwin32version.h", "tst.c"]) + elif glob.glob("../libxslt/transform.c") != [] : + print "Rebuilding API description for libxslt" + builder = docBuilder("libxslt", ["../libxslt"], + ["win32config.h", "libxslt.h", "tst.c"]) + else: + print "rebuild() failed, unable to guess the module" + return None + builder.scan() + builder.analyze() + builder.serialize() + return builder + +# +# for debugging the parser +# +def parse(filename): + parser = CParser(filename) + idx = parser.parse() + return idx + +if __name__ == "__main__": + rebuild() diff --git a/doc/libxslt-api.xml b/doc/libxslt-api.xml index 0320012..504372f 100644 --- a/doc/libxslt-api.xml +++ b/doc/libxslt-api.xml @@ -1,330 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + - - - - - + - + + + + + - - + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - + + + + - - - + - - - - - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - This macro is used to flag unused function parameters to GCC, useless here - Macro to check if the XSLT processing should be stopped. Will return from the function. @@ -334,52 +378,18 @@ Macro to check if the XSLT processing should be stopped. Will goto the error: label. - - should be activated only when debugging libxslt. It replaces the allocator with a collect and debug shell to the libc allocator. Use configure --with-mem-debug to activate it on both library - - - should be activated only when debugging libxslt. DEBUG_MEMORY_LOCATION should be activated only when libxml has been configured with --with-debug-mem too - Checks that the element pertains to XSLT namespace. - Checks the value of an element in XSLT namespace. - - Check that a node is a 'real' one: document, element, text or attribute. - - - - the version string like "1.2.3" - - This macro is needed on Win32 when using MSVC. It enables the client code to access exported variables. It should expand to nothing when compiling this library itself, but must expand to __declspec(dllimport) when a client includes the library header and that only if it links dynamically against this library. + + Macro used on Windows to tag public identifiers from shared libraries. - - the version number: 1.2.3 value is 1002003 - - - the version number string, 1.2.3 value is "1002003" - - - - - Activate the compilation of the debug reporting. Speed penalty is insignifiant and being able to run xsltpoc -v is useful. On by default - - - - - - - - - - - The XSLT "vendor" URL for this processor. @@ -389,39 +399,11 @@ The default version of XSLT supported. - - - - - - - - - - - - - - - - - - - - - - A macro to import intergers from the stylesheet cascading order. - - - A macro to import pointers from the stylesheet cascading order. - - - This is the libxslt namespace for specific extensions. @@ -432,54 +414,44 @@ The XSLT specification namespace. - - should be activated in the existing libc library lacks some of the string formatting function, in that case reuse the Trio ones already compiled in the libxml2 library. - This is Norm's namespace for SAXON extensions. - - - Specific value for pattern without priority expressed. Registering macro, not general purpose at all but used in different modules. - Registering macro, not general purpose at all but used in different modules. - - - + Macro used to define extra information stored in the context + + - - + Macro used to free extra information stored in the context + + - - + Macro used to access extra information stored in the context + + This is Michael Kay's Saxon processor namespace for extensions. - - - - - - - - + Macro to flag that a problem was detected internally. + Sampling precision for profiling + Macro to flag unimplemented blocks. This is the Apache project XALAN processor namespace for extensions. @@ -487,11 +459,90 @@ This is James Clark's XT processor namespace for extensions. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Add template "call" to call stack - - - + + + Drop the topmost item off the call stack @@ -500,181 +551,182 @@ If either cur or node are a breakpoint, or xslDebugStatus in state where debugging must occcur at this time then transfer control to the xslDebugBreak function - - - - + + + + - - - + + + + add a key definition to a stylesheet - - - - - - - + + + + + + + add the new element list at this level of the stack. - - - + + + - Register the XSLT pattern associated to cur - - - - - + Register the XSLT pattern associated to @cur + + + + + Allocate an extra runtime information slot statically while compiling the stylesheet and return its number - - + + Allocate an extra runtime information slot at run-time and return its number This make sure there is a slot ready in the transformation context - - + + Apply the xsl:use-attribute-sets - - - - + + + + Process the xslt apply-imports node on the source node - - - - + + + + Process the apply-templates node on the source node, if params are passed they are pushed on the variable stack but not popped, it's left to the caller to handle them back (they may be reused). - - - - - + + + + + Strip the unwanted ignorable spaces from the input tree - - + + Apply the stylesheet to the document NOTE: This may lead to a non-wellformed output XML wise ! - - - - + + + + Apply the stylesheet to the document and allow the user to provide its own transformation context. - - - - - - - + + + + + + + Process the apply-templates node on the source node - - - - + + + + Do a copy of an attribute list with attribute template processing - - - - + + + + Process the given attribute and return the new processed copy. - - - - + + + + Process the given node and return the new string value. - - - + + + Process the given string, allowing to pass a namespace mapping context and return the new string value. - - - - + + + + Process the xslt attribute node on the source node - - - - + + + + Used for to correct the calibration for xsltTimestamp() - + Process the xslt call-template node on the source node - - - - + + + + Check if the given prefix is one of the declared extensions - - - + + + - Check if the resource is allowed to be read Return 1 if read is allowed, 0 if not and -1 in case or error. - - - - + Check if the resource is allowed to be read + + + + - Check if the resource is allowed to be written, if necessary makes some preliminary work like creating directories Return 1 if write is allowed, 0 if not and -1 in case or error. - - - - + Check if the resource is allowed to be written, if necessary makes some preliminary work like creating directories + + + + Process the xslt choose node on the source node - - - - + + + + Unregister all global variables set up by the XSLT library @@ -683,732 +735,760 @@ Cleanup the state of the templates used by the stylesheet and the ones it imports. - + Process the xslt comment node on the source node - - - - + + + + - - - Compile the XSLT pattern and generates a list of precompiled form suitable for fast matching. [1] Pattern ::= LocationPathPattern | Pattern '|' LocationPathPattern - - - - - - + Compile the XSLT pattern and generates a list of precompiled form suitable for fast matching. [1] Pattern ::= LocationPathPattern | Pattern '|' LocationPathPattern + + + + + + + + + reorder the current node list accordingly to the set of sorting requirement provided by the array of nodes. + + + Process the xslt copy node on the source node - - - - + + + + - Do a copy of an namespace node. If node is non-NULL the new namespaces are added automatically. This handles namespaces aliases - - - - + Do a copy of an namespace node. If @node is non-NULL the new namespaces are added automatically. This handles namespaces aliases + + + + - Do a copy of an namespace list. If node is non-NULL the new namespaces are added automatically. This handles namespaces aliases - - - - + Do a copy of an namespace list. If @node is non-NULL the new namespaces are added automatically. This handles namespaces aliases + + + + Process the xslt copy-of node on the source node - - - - + + + + + + + Make a copy of the full tree under the element node @node and insert it as last child of @insert + + + + Process an debug node - - - - + + + + Dumps a list of the registered XSLT extension functions and elements - + - - Find decimal-format by name - - - + + + - - + reorder the current node list accordingly to the set of sorting requirement provided by the arry of nodes. - - - + + + + + + reorder the current node list accordingly to the set of sorting requirement provided by the arry of nodes. This is a wrapper function, the actual function used is specified using xsltSetCtxtSortFunc() to set the context specific sort function, or xsltSetSortFunc() to set the global sort function. If a sort function is set on the context, this will get called. Otherwise the global sort function is called. + + + + - Pre process an XSLT-1.1 document element - - - - + + + + Process an EXSLT/XSLT-1.1 document element - - - - + + + + Implement the document() XSLT function node-set document(object, node-set?) - - + + - - reorder the current node list list accordingly to the document order + reorder the current node list @list accordingly to the document order - + - + + - - Deallocates an xsltElemPreComp structure. - - + Deallocates an #xsltElemPreComp structure. + + - Process the xslt element node on the source node - - - - + + + + Implement the element-available() XSLT function boolean element-available(string) - - + + Evaluate a attribute value template, i.e. the attribute value can contain expressions contained in curly braces ({}) and those are substituted by they computed value. - - - - - + + + + + Evaluate the global variables of a stylesheet. This need to be done on parsed stylesheets before starting to apply transformations - - + + - ctxt: the XSLT transformation context name: a null terminated string giving the name of the parameter value a null terminated string giving the XPath expression to be evaluated This is normally called from xsltEvalUserParams to process a single parameter from a list of parameters. The value is evaluated as an XPath expression and the result is stored in the context's global variable/parameter hash table. To have a parameter treated literally (not as an XPath expression) use xsltQuoteUserParams (or xsltQuoteOneUserParam). For more details see description of xsltProcessOneUserParamInternal. - - - - + This is normally called from xsltEvalUserParams to process a single parameter from a list of parameters. The @value is evaluated as an XPath expression and the result is stored in the context's global variable/parameter hash table. To have a parameter treated literally (not as an XPath expression) use xsltQuoteUserParams (or xsltQuoteOneUserParam). For more details see description of xsltProcessOneUserParamInternal. + + + + Check if an attribute value template has a static value, i.e. the attribute value does not contain expressions contained in curly braces ({}) - - - - - - + + + + + + Evaluate a template string value, i.e. the parent list is interpreter as template content and the resulting tree string value is returned This is needed for example by xsl:comment and xsl:processing-instruction - - - - + + + + - ctxt: the XSLT transformation context params: a NULL terminated array of parameters name/value tuples Evaluate the global variables of a stylesheet. This needs to be done on parsed stylesheets before starting to apply transformations. Each of the parameters is evaluated as an XPath expression and stored in the global variables/parameter hash table. If you want your parameter used literally, use xsltQuoteUserParams. - - - + Evaluate the global variables of a stylesheet. This needs to be done on parsed stylesheets before starting to apply transformations. Each of the parameters is evaluated as an XPath expression and stored in the global variables/parameter hash table. If you want your parameter used literally, use xsltQuoteUserParams. + + + Process the expression using XPath and evaluate the result as an XPath predicate - - - - - + + + + + Process the expression using XPath and get a string - - - + + + Process the expression using XPath, allowing to pass a namespace mapping context and get a string - - - - - - - - Looks up an extension element. ctxt can be NULL to search only in module elements. - - - - + + + + + + + + Looks up an extension element. @ctxt can be NULL to search only in module elements. + + + + - - - - + + + + + A function called at initialization time of an XSLT extension module. - - - + + + Looks up an extension module element - - - + + + Looks up an extension module element pre-computation function - - - + + + Looks up an extension module function - - - + + + Looks up an extension module top-level element - - - + + + A function called at shutdown time of an XSLT extension module. - - - - + + + + Try to find a document within the XSLT transformation context - - - + + + Find strip-space or preserve-space informations for an element respect the import precedence or the wildcards - - - + + + Finds the named template, apply import precedence rule. - - - - + + + + Process the xslt for-each node on the source node - - - - + + + + - format-number() uses the JDK 1.1 DecimalFormat class: http://java.sun.com/products/jdk/1.1/docs/api/java.text.DecimalFormat.html Structure: pattern := subpattern{;subpattern} subpattern := {prefix}integer{.fraction}{suffix} prefix := '\\u0000'..'\\uFFFD' - specialCharacters suffix := '\\u0000'..'\\uFFFD' - specialCharacters integer := '#'* '0'* '0' fraction := '0'* '#'* Notation: X* 0 or more instances of X (X | Y) either X or Y. X..Y any character from X up to Y, inclusive. S - T characters in S, except those in T Special Characters: Symbol Meaning 0 a digit # a digit, zero shows as absent . placeholder for decimal separator , placeholder for grouping separator. ; separates formats. - default negative prefix. % multiply by 100 and show as percentage ? multiply by 1000 and show as per mille X any other characters can be used in the prefix or suffix ' used to quote special characters in a prefix or suffix. - - - - - + format-number() uses the JDK 1.1 DecimalFormat class: http://java.sun.com/products/jdk/1.1/docs/api/java.text.DecimalFormat.html Structure: pattern := subpattern{;subpattern} subpattern := {prefix}integer{.fraction}{suffix} prefix := '\\u0000'..'\\uFFFD' - specialCharacters suffix := '\\u0000'..'\\uFFFD' - specialCharacters integer := '#'* '0'* '0' fraction := '0'* '#'* Notation: X* 0 or more instances of X (X | Y) either X or Y. X..Y any character from X up to Y, inclusive. S - T characters in S, except those in T Special Characters: Symbol Meaning 0 a digit # a digit, zero shows as absent . placeholder for decimal separator , placeholder for grouping separator. ; separates formats. - default negative prefix. % multiply by 100 and show as percentage ? multiply by 1000 and show as per mille X any other characters can be used in the prefix or suffix ' used to quote special characters in a prefix or suffix. + + + + + Implement the format-number() XSLT function string format-number(number, string, string?) - - + + Free up the memory used by attribute sets - + - Free up the memory allocated by all the elements of comp + Free up the memory allocated by all the elements of @comp - + Free the XSLT extension data - + Free the keys associated to a document - + Free up all the space used by the loaded documents - + Free up the memory used by XSLT extensions in a stylesheet - + Free up the data associated to the global variables its value. - + Free up the memory used by XSLT keys in a stylesheet - + Free up the memory used by namespaces aliases - + Free up a security preference block - + - Free up the memory allocated by elem + Free up the memory allocated by @elem - + Free up all the space used by the loaded documents - + Free up the memory allocated by all precomputed blocks - + - Free up the memory allocated by sheet + Free up the memory allocated by @sheet - + Free up the memory used by xsltAddTemplate/xsltGetTemplate mechanism - + - Free up the memory allocated by ctxt + Free up the memory allocated by @ctxt - + Implement the function-available() XSLT function boolean function-available(string) - - + + - Implement the node-set() XSLT function node-set node-set(result-tree) This function is available in libxslt, saxon or xt namespace. + Implement the node-set() XSLT function node-set node-set(result-tree) This function is available in libxslt, saxon or xt namespace. - - + + Implement the generate-id() XSLT function string generate-id(node-set?) - - + + - + Get the default security preference application-wide + Retrieve the data associated to the extension module in this given transformation. - - - + + + Lookup a key - - - - - + + + + + Find the right namespace value for this prefix, if needed create and add a new namespace decalaration on the node Handle namespace aliases - - - - - + + + + + - Similar to xmlGetNsProp() but with a slightly different semantic Search and get the value of an attribute associated to a node This attribute has to be anchored in the namespace specified, or has no namespace and the element is in that namespace. This does the entity substitution. This function looks in DTD attribute declaration for FIXED or default declaration values unless DTD use has been turned off. - - - - + Similar to xmlGetNsProp() but with a slightly different semantic Search and get the value of an attribute associated to a node This attribute has to be anchored in the namespace specified, or has no namespace and the element is in that namespace. This does the entity substitution. This function looks in DTD attribute declaration for #FIXED or default declaration values unless DTD use has been turned off. + + + + This function should be called after the transformation completed to extract template processing profiling informations if availble. The informations are returned as an XML document tree like <?xml version="1.0"?> <profile> <template rank="1" match="*" name="" mode="" calls="6" time="48" average="8"/> <template rank="2" match="item2|item3" name="" mode="" calls="10" time="30" average="3"/> <template rank="3" match="item1" name="" mode="" calls="5" time="17" average="3"/> </profile> The caller will need to free up the returned tree with xmlFreeDoc() - - + + - This function analyzes name, if the name contains a prefix, the function seaches the associated namespace in scope for it. It will also replace name value with the NCName, the old value being freed. Errors in the prefix lookup are signalled by setting name to NULL. NOTE: the namespace returned is a pointer to the place where it is defined and hence has the same lifespan as the document holding it. - - - + This function analyzes @name, if the name contains a prefix, the function seaches the associated namespace in scope for it. It will also replace @name value with the NCName, the old value being freed. Errors in the prefix lookup are signalled by setting @name to NULL. NOTE: the namespace returned is a pointer to the place where it is defined and hence has the same lifespan as the document holding it. + + + Lookup the security option to get the callback checking function - - - + + + Find the right namespace value for this URI, if needed create and add a new namespace decalaration on the node - - - - - - + + + + + + - Finds the template applying to this node, if style is non-NULL it means one needs to look for the next imported template in scope. - - - - + Finds the template applying to this node, if @style is non-NULL it means one needs to look for the next imported template in scope. + + + + - Read one UTF8 Char from utf Function copied from libxml2 xmlGetUTF8Char() ... to discard ultimately and use the original API - - - + Read one UTF8 Char from @utf Function copied from libxml2 xmlGetUTF8Char() ... to discard ultimately and use the original API + + + - return the default state for XInclude processing - + Provides the default state for XInclude processing + - - - - - + + + + + + Process the xslt if node on the source node - - - - + + + + Initialize the set of modules with registered stylesheet data - - + + Computes all the keys tables for the current input document. Should be done before global varibales are initialized. - - + + - Initializes an existing xsltElemPreComp structure. This is usefull when extending an xsltElemPreComp to store precomputed data. This function MUST be called on any extension element precomputed data struct. + Initializes an existing #xsltElemPreComp structure. This is usefull when extending an #xsltElemPreComp to store precomputed data. This function MUST be called on any extension element precomputed data struct. - - - - - + + + + + Check if a string is ignorable - - + + Implement the key() XSLT function node-set key(string, object) - - + + Try to load a document (not a stylesheet) within the XSLT transformation context - - - + + + Try to load a stylesheet document within the XSLT transformation context - - - + + + - This function tries to locate the stylesheet PI in the given document If found, and if contained within the document, it will extract that subtree to build the stylesheet to process doc (doc itself will be modified). If found but referencing an external document it will attempt to load it and generate a stylesheet from it. In both cases, the resulting stylesheet and the document need to be freed once the transformation is done. - - + This function tries to locate the stylesheet PI in the given document If found, and if contained within the document, it will extract that subtree to build the stylesheet to process @doc (doc itself will be modified). If found but referencing an external document it will attempt to load it and generate a stylesheet from it. In both cases, the resulting stylesheet and the document need to be freed once the transformation is done. + + - Determine if a node matches a pattern. - - - - - - + + + + + + + Process and xsl:message construct - - - + + + Read the stylesheet-prefix and result-prefix attributes, register them as well as the corresponding namespace. - - + + - Returns whether that stylesheet requires white-space stripping - - + Checks whether that stylesheet requires white-space stripping + + Register a new document, apply key computations - - - + + + - Creates and initializes an xsltElemPreComp - - - - + Creates and initializes an #xsltElemPreComp + + + + Create a new security preference block - + Register a new document, apply key computations - - - + + + Create a new XSLT Stylesheet - + Create a new XSLT TransformContext - - - + + + Find the next stylesheet in import precedence. - - + + Process the xslt number node on the source node - - - - + + + + Convert one number. - - - + + + - parse an XSLT transformation param declaration and record its value. - - + + parse an XSLT transformation variable declaration and record its value. - - + + - parse an XSLT stylesheet preserve-space element and record elements needing preserving + parse an XSLT stylesheet attribute-set element - - + + - parse an XSLT transformation param declaration, compute its value but doesn't record it. It returns the new xsltStackElemPtr or NULL - - - + parse an XSLT transformation param declaration, compute its value but doesn't record it. + + + parse an XSLT stylesheet building the associated structures - - + + Load and parse an XSLT stylesheet - - + + - parse an XSLT stylesheet strip-space element and record elements needing stripping. Returns zero on success and something else on failure. - - - + parse an XSLT stylesheet import element + + + - parse an XSLT stylesheet strip-space element and record elements needing stripping. Returns zero on success, something else on failure. - - - + parse an XSLT stylesheet include element + + + parse an XSLT stylesheet output element and record information related to the stylesheet output - - + + parse an XSLT transformation param declaration and record its value. - - + + parse an XSLT stylesheet adding the associated structures - - - + + + parse an XSLT transformation variable declaration and record its value. - - + + parse a template content-model Clean-up the template content from unwanted ignorable blank nodes and process xslt:text - - + + Precomputes an extension module element - - - - + + + + + + + + + + + Display the context of an error. - - - + + + + + + + + + + Process the xslt processing-instruction node on the source node - - - - + + + + Apply the stylesheet to the document and dump the profiling to the given output. - - - - - + + + + + - ctxt: the XSLT transformation context name: a null terminated string giving the name of the parameter value a null terminated string giving the parameter value This is normally called from xsltQuoteUserParams to process a single parameter from a list of parameters. The value is stored in the context's global variable/parameter hash table. - - - - + This is normally called from xsltQuoteUserParams to process a single parameter from a list of parameters. The @value is stored in the context's global variable/parameter hash table. + + + + - ctxt: the XSLT transformation context params: a NULL terminated arry of parameters names/values tuples Similar to xsltEvalUserParams, but the values are treated literally and are * *not* evaluated as XPath expressions. This should be done on parsed stylesheets before starting to apply transformations. - - - + Similar to xsltEvalUserParams, but the values are treated literally and are * *not* evaluated as XPath expressions. This should be done on parsed stylesheets before starting to apply transformations. + + + Registers all default XSLT elements in this context - + Registers the built-in extensions @@ -1417,73 +1497,73 @@ Registers all default XSLT functions in this context - + Registers an extension element - - - - - + + + + + Registers an extension function - - - - - + + + + + Register an XSLT extension module to the library. - - - - + + + + Registers an extension module element. - - - - - + + + + + Register an XSLT extension module to the library. - - - - - - + + + + + + Registers an extension module function. - - - - + + + + Registers an extension module top-level element. - - - - + + + + Registers an extension namespace - - - - + + + + Registers the built-in extensions. This function is deprecated, use xsltRegisterAllExtras instead. - + Registers the test module @@ -1492,316 +1572,319 @@ resolve the references between attribute sets. - + - Apply the stylesheet to the document and generate the output according to outputSAX and IObuf. It's an error to specify both SAX and IObuf. NOTE: This may lead to a non-wellformed output XML wise ! NOTE: This may also result in multiple files being generated NOTE: using IObuf, the result encoding used will be the one used for creating the output buffer, use the following macro to read it from the stylesheet XSLT_GET_IMPORT_PTR(encoding, style, encoding) NOTE: using SAX, any encoding specified in the stylesheet will be lost since the interface uses only UTF8 - - - - - - - + Apply the stylesheet to the document and generate the output according to @output @SAX and @IObuf. It's an error to specify both @SAX and @IObuf. NOTE: This may lead to a non-wellformed output XML wise ! NOTE: This may also result in multiple files being generated NOTE: using IObuf, the result encoding used will be the one used for creating the output buffer, use the following macro to read it from the stylesheet XSLT_GET_IMPORT_PTR(encoding, style, encoding) NOTE: using SAX, any encoding specified in the stylesheet will be lost since the interface uses only UTF8 + + + + + + + - Apply the stylesheet to the document and generate the output according to outputSAX and IObuf. It's an error to specify both SAX and IObuf. NOTE: This may lead to a non-wellformed output XML wise ! NOTE: This may also result in multiple files being generated NOTE: using IObuf, the result encoding used will be the one used for creating the output buffer, use the following macro to read it from the stylesheet XSLT_GET_IMPORT_PTR(encoding, style, encoding) NOTE: using SAX, any encoding specified in the stylesheet will be lost since the interface uses only UTF8 - - - - - - - - - - - - + Apply the stylesheet to the document and generate the output according to @output @SAX and @IObuf. It's an error to specify both @SAX and @IObuf. NOTE: This may lead to a non-wellformed output XML wise ! NOTE: This may also result in multiple files being generated NOTE: using IObuf, the result encoding used will be the one used for creating the output buffer, use the following macro to read it from the stylesheet XSLT_GET_IMPORT_PTR(encoding, style, encoding) NOTE: using SAX, any encoding specified in the stylesheet will be lost since the interface uses only UTF8 + + + + + + + + + + - Save the profiling informations on output + Save the profiling informations on @output - - + + - Save the result result obtained by applying the style stylesheet to an I/O output channel buf - - - - + Save the result @result obtained by applying the @style stylesheet to an I/O output channel @buf + + + + - Save the result result obtained by applying the style stylesheet to an open file descriptor This does not close the descriptor. - - - - + Save the result @result obtained by applying the @style stylesheet to an open file descriptor This does not close the descriptor. + + + + - Save the result result obtained by applying the style stylesheet to an open FILE * I/O. This does not close the FILE file - - - - + Save the result @result obtained by applying the @style stylesheet to an open FILE * I/O. This does not close the FILE @file + + + + - Save the result result obtained by applying the style stylesheet to a file or URL - - - - - + Save the result @result obtained by applying the @style stylesheet to a file or @URL + + + + + - Save the result result obtained by applying the style stylesheet to a file or URL - - - - - + Save the result @result obtained by applying the @style stylesheet to a file or @URL + + + + + Function used to always allow an operation - - - - + + + + User provided function to check the value of a string like a file path or an URL ... - - - - + + + + Function used to always forbid an operation - - - - - - - - + + + + + Set the security preference for a specific transformation - - - + + + + + + Function to set the handler for XSLT sorting for the specified context. If the handler is NULL, then the global sort function will be called + + + - - - + This function allow to plug a debugger into the XSLT library @block points to a block of memory containing the address of @no callback routines. + + + - Get the default security preference application-wide + Set the default security preference application-wide - + - Function to reset the handler and the error context for out of context error messages. This simply means that handler will be called for subsequent error messages while not parsing or validating. And ctx will be passed as first argument to handler One can simply force messages to be emitted to another FILE * than stderr by setting ctx to this file handle and handler to NULL. + Function to reset the handler and the error context for out of context error messages. This simply means that @handler will be called for subsequent error messages while not parsing or validating. And @ctx will be passed as first argument to @handler One can simply force messages to be emitted to another FILE * than stderr by setting @ctx to this file handle and @handler to NULL. - - + + - Function to reset the handler and the error context for out of context error messages. This simply means that handler will be called for subsequent error messages while not parsing nor validating. And ctx will be passed as first argument to handler One can simply force messages to be emitted to another FILE * than stderr by setting ctx to this file handle and handler to NULL. + Function to reset the handler and the error context for out of context error messages. This simply means that @handler will be called for subsequent error messages while not parsing nor validating. And @ctx will be passed as first argument to @handler One can simply force messages to be emitted to another FILE * than stderr by setting @ctx to this file handle and @handler to NULL. - - + + Update the security option to use the new callback checking function - - - - + + + + + + + Function to reset the global handler for XSLT sorting. If the handler is NULL, the default sort function will be used. + + - Function to reset the handler and the error context for out of context error messages specific to a given XSLT transromation. This simply means that handler will be called for subsequent error messages while running the transformation. + Function to reset the handler and the error context for out of context error messages specific to a given XSLT transromation. This simply means that @handler will be called for subsequent error messages while running the transformation. - - - + + + Set whether XInclude should be processed on document being loaded by default - + Shutdown the set of modules loaded - + Shutdown the set of modules loaded - + function attached to xsl:sort nodes, but this should not be called directly - - - - - - - + + + + + + + Signature of the function to use during sorting + + + + + A function called at initialization time of an XSLT extension module. - - - + + + A function called at shutdown time of an XSLT extension module. - - - - + + + + Retrieve the data associated to the extension module in this given stylesheet. - - - + + + - - Precompute an XSLT stylesheet element - - + + - - - Implement the system-property() XSLT function object system-property(string) - - + + - Process the given node and return the new string value. - - - + + + - Test wether the node matches one of the patterns in the list - - - - + + + + Process the xslt text node on the source node - - - - + + + + Used for gathering profiling data - + - - - + + + + - - Display and format an error messages, gives file, line, position and extra parameters, will use the specific transformation context if available - - - - - + + + + + Signature of the function associated to elements part of the stylesheet language like xsl:if or xsl:apply-templates. - - - - - + + + + + - Implement the unparsed-entity-uri() XSLT function string unparsed-entity-uri(string) - - + + Unregister an XSLT extension module from the library. - - + + Unregisters an extension module element - - - + + + Unregisters an extension module function - - - + + + Unregisters an extension module top-level element - - - + + + Process the xslt value-of node on the source node - - - - + + + + Search in the Variable array of the context for the given variable value. - - - - + + + + This is the entry point when a function is needed by the XPath interpretor. - - - - + + + + - Returns the XSLT transformation context from the XPath transformation context. This is useful when an XPath function in the extension module is called by the XPath interpreter and that the XSLT context is needed for example to retrieve the associated data pertaining to this XSLT transformation. - - + Provides the XSLT transformation context from the XPath transformation context. This is useful when an XPath function in the extension module is called by the XPath interpreter and that the XSLT context is needed for example to retrieve the associated data pertaining to this XSLT transformation. + + This is the entry point when a varibale is needed by the XPath interpretor. - - - - + + + + diff --git a/libxslt.spec.in b/libxslt.spec.in index 068754e..db346f0 100644 --- a/libxslt.spec.in +++ b/libxslt.spec.in @@ -102,6 +102,7 @@ rm -fr %{buildroot} %defattr(-, root, root) %doc AUTHORS ChangeLog NEWS README Copyright TODO FEATURES +%doc doc/libxslt-api.xml %doc %{_mandir}/man4/libxslt.4* %doc %{_mandir}/man4/libexslt.4* %{_libdir}/lib*.so diff --git a/libxslt/attributes.c b/libxslt/attributes.c index 368e1b4..6212251 100644 --- a/libxslt/attributes.c +++ b/libxslt/attributes.c @@ -266,10 +266,9 @@ xsltMergeAttrElemList(xsltAttrElemPtr list, xsltAttrElemPtr old) { /** * xsltParseStylesheetAttributeSet: * @style: the XSLT stylesheet - * @template: the "preserve-space" element + * @cur: the "attribute-set" element * - * parse an XSLT stylesheet preserve-space element and record - * elements needing preserving + * parse an XSLT stylesheet attribute-set element */ void diff --git a/libxslt/documents.c b/libxslt/documents.c index e0c817e..0438f30 100644 --- a/libxslt/documents.c +++ b/libxslt/documents.c @@ -45,6 +45,8 @@ * @doc: a parsed XML document * * Register a new document, apply key computations + * + * Returns a handler to the document */ xsltDocumentPtr xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) { @@ -72,6 +74,8 @@ xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) { * @doc: a parsed XML document * * Register a new document, apply key computations + * + * Returns a handler to the document */ xsltDocumentPtr xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) { @@ -267,7 +271,7 @@ xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) { /** * xsltFindDocument: * @ctxt: an XSLT transformation context - * @@doc: a parsed XML document + * @doc: a parsed XML document * * Try to find a document within the XSLT transformation context * diff --git a/libxslt/extensions.c b/libxslt/extensions.c index ce9a00b..b597e57 100644 --- a/libxslt/extensions.c +++ b/libxslt/extensions.c @@ -875,7 +875,7 @@ xsltUnregisterAllExtModules(void) * xsltXPathGetTransformContext: * @ctxt: an XPath transformation context * - * Returns the XSLT transformation context from the XPath transformation + * Provides the XSLT transformation context from the XPath transformation * context. This is useful when an XPath function in the extension module * is called by the XPath interpreter and that the XSLT context is needed * for example to retrieve the associated data pertaining to this XSLT diff --git a/libxslt/imports.c b/libxslt/imports.c index c0d144f..0a5cd50 100644 --- a/libxslt/imports.c +++ b/libxslt/imports.c @@ -56,11 +56,11 @@ /** * xsltParseStylesheetImport: * @style: the XSLT stylesheet - * @template: the "strip-space" element + * @cur: the import element * - * parse an XSLT stylesheet strip-space element and record - * elements needing stripping. Returns zero on success and something else - * on failure. + * parse an XSLT stylesheet import element + * + * Returns 0 in case of success -1 in case of failure. */ int @@ -139,11 +139,11 @@ error: /** * xsltParseStylesheetInclude: * @style: the XSLT stylesheet - * @template: the "strip-space" element + * @cur: the include node + * + * parse an XSLT stylesheet include element * - * parse an XSLT stylesheet strip-space element and record - * elements needing stripping. Returns zero on success, something else - * on failure. + * Returns 0 in case of success -1 in case of failure */ int @@ -230,7 +230,7 @@ xsltNextImport(xsltStylesheetPtr cur) { * xsltNeedElemSpaceHandling: * @ctxt: an XSLT transformation context * - * Returns whether that stylesheet requires white-space stripping + * Checks whether that stylesheet requires white-space stripping * * Returns 1 if space should be stripped, 0 if not */ diff --git a/libxslt/numbers.c b/libxslt/numbers.c index 39641ff..ff537c5 100644 --- a/libxslt/numbers.c +++ b/libxslt/numbers.c @@ -826,6 +826,8 @@ xsltFormatNumberPreSuffix(xsltDecimalFormatPtr self, xmlChar **format, xsltForma * ? multiply by 1000 and show as per mille * X any other characters can be used in the prefix or suffix * ' used to quote special characters in a prefix or suffix. + * + * Returns a possible XPath error */ xmlXPathError xsltFormatNumberConversion(xsltDecimalFormatPtr self, diff --git a/libxslt/numbersInternals.h b/libxslt/numbersInternals.h index b1a583e..57479ec 100644 --- a/libxslt/numbersInternals.h +++ b/libxslt/numbersInternals.h @@ -21,7 +21,10 @@ extern "C" { * * This data structure is just a wrapper to pass xsl:number data in. */ -typedef struct _xsltNumberData { +typedef struct _xsltNumberData xsltNumberData; +typedef xsltNumberData *xsltNumberDataPtr; + +struct _xsltNumberData { xmlChar *level; xmlChar *count; xmlChar *from; @@ -33,14 +36,17 @@ typedef struct _xsltNumberData { int groupingCharacterLen; xmlDocPtr doc; xmlNodePtr node; -} xsltNumberData, *xsltNumberDataPtr; +}; /** * xsltFormatNumberInfo,: * * This data structure lists the various parameters needed to format numbers. */ -typedef struct _xsltFormatNumberInfo { +typedef struct _xsltFormatNumberInfo xsltFormatNumberInfo; +typedef xsltFormatNumberInfo *xsltFormatNumberInfoPtr; + +struct _xsltFormatNumberInfo { int integer_hash; /* Number of '#' in integer part */ int integer_digits; /* Number of '0' in integer part */ int frac_digits; /* Number of '0' in fractional part */ @@ -50,7 +56,7 @@ typedef struct _xsltFormatNumberInfo { char add_decimal; /* Flag for whether decimal point appears in pattern */ char is_multiplier_set; /* Flag to catch multiple occurences of percent/permille */ char is_negative_pattern;/* Flag for processing -ve prefix/suffix */ -} xsltFormatNumberInfo, *xsltFormatNumberInfoPtr; +}; #ifdef __cplusplus } diff --git a/libxslt/pattern.c b/libxslt/pattern.c index 1746bc1..9da3f19 100644 --- a/libxslt/pattern.c +++ b/libxslt/pattern.c @@ -2221,36 +2221,3 @@ xsltFreeTemplateHashes(xsltStylesheetPtr style) { xsltFreeCompMatchList(style->commentMatch); } -#if 0 -/** - * xsltMatchPattern - * @node: a node in the source tree - * @pattern: an XSLT pattern - * @ctxtdoc: context document (for namespaces) - * @ctxtnode: context node (for namespaces) - * - * Determine if a node matches a pattern. - */ -int -xsltMatchPattern(xsltTransformContextPtr context, - xmlNodePtr node, - const xmlChar *pattern, - xmlDocPtr ctxtdoc, - xmlNodePtr ctxtnode) -{ - int match = 0; - xsltCompMatchPtr first, comp; - - if ((context != NULL) && (pattern != NULL)) { - first = xsltCompilePattern(pattern, ctxtdoc, ctxtnode); - for (comp = first; comp != NULL; comp = comp->next) { - match = xsltTestCompMatch(context, comp, node, NULL, NULL); - if (match) - break; /* for */ - } - if (first) - xsltFreeCompMatchList(first); - } - return match; -} -#endif diff --git a/libxslt/preproc.c b/libxslt/preproc.c index eb7f7f3..e5e028d 100644 --- a/libxslt/preproc.c +++ b/libxslt/preproc.c @@ -193,8 +193,11 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) { * xsltDocumentComp: * @style: the XSLT stylesheet * @inst: the instruction in the stylesheet + * @function: unused * * Pre process an XSLT-1.1 document element + * + * Returns a precompiled data structure for the element */ xsltElemPreCompPtr xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst, diff --git a/libxslt/security.c b/libxslt/security.c index 31b4068..baddcca 100644 --- a/libxslt/security.c +++ b/libxslt/security.c @@ -163,7 +163,7 @@ xsltSetDefaultSecurityPrefs(xsltSecurityPrefsPtr sec) { } /** - * xsltSetDefaultSecurityPrefs: + * xsltGetDefaultSecurityPrefs: * * Get the default security preference application-wide * diff --git a/libxslt/templates.c b/libxslt/templates.c index ef24e54..7aa865a 100644 --- a/libxslt/templates.c +++ b/libxslt/templates.c @@ -224,7 +224,6 @@ xsltEvalTemplateString(xsltTransformContextPtr ctxt, xmlNodePtr node, * @ctxt: the XSLT transformation context * @str: the attribute template node value * @node: the node hosting the attribute - * @nsList: the list of in-scope namespaces to use * * Process the given string, allowing to pass a namespace mapping * context and return the new string value. diff --git a/libxslt/transform.c b/libxslt/transform.c index 183746e..07fa5c8 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -77,55 +77,187 @@ int xsltMaxDepth = 5000; #define IS_BLANK_NODE(n) \ (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content))) -/* - * Generic function for accessing stacks in the transform Context +/** + * templPush: + * @ctxt: the transformation context + * @value: the template to push on the stack + * + * Push a template on the stack + * + * Returns the new index in the stack or 0 in case of error + */ +static int +templPush(xsltTransformContextPtr ctxt, xsltTemplatePtr value) +{ + if (ctxt->templMax == 0) { + ctxt->templMax = 4; + ctxt->templTab = + (xsltTemplatePtr *) xmlMalloc(ctxt->templMax * + sizeof(ctxt->templTab[0])); + if (ctxt->templTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "malloc failed !\n"); + return (0); + } + } + if (ctxt->templNr >= ctxt->templMax) { + ctxt->templMax *= 2; + ctxt->templTab = + (xsltTemplatePtr *) xmlRealloc(ctxt->templTab, + ctxt->templMax * + sizeof(ctxt->templTab[0])); + if (ctxt->templTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "realloc failed !\n"); + return (0); + } + } + ctxt->templTab[ctxt->templNr] = value; + ctxt->templ = value; + return (ctxt->templNr++); +} +/** + * varsPop: + * @ctxt: the transformation context + * + * Pop a template value from the stack + * + * Returns the stored template value */ +static xsltTemplatePtr +templPop(xsltTransformContextPtr ctxt) +{ + xsltTemplatePtr ret; -#define PUSH_AND_POP(scope, type, name) \ -scope int name##Push(xsltTransformContextPtr ctxt, type value) { \ - if (ctxt->name##Max == 0) { \ - ctxt->name##Max = 4; \ - ctxt->name##Tab = (type *) xmlMalloc(ctxt->name##Max * \ - sizeof(ctxt->name##Tab[0])); \ - if (ctxt->name##Tab == NULL) { \ - xmlGenericError(xmlGenericErrorContext, \ - "malloc failed !\n"); \ - return(0); \ - } \ - } \ - if (ctxt->name##Nr >= ctxt->name##Max) { \ - ctxt->name##Max *= 2; \ - ctxt->name##Tab = (type *) xmlRealloc(ctxt->name##Tab, \ - ctxt->name##Max * sizeof(ctxt->name##Tab[0])); \ - if (ctxt->name##Tab == NULL) { \ - xmlGenericError(xmlGenericErrorContext, \ - "realloc failed !\n"); \ - return(0); \ - } \ - } \ - ctxt->name##Tab[ctxt->name##Nr] = value; \ - ctxt->name = value; \ - return(ctxt->name##Nr++); \ -} \ -scope type name##Pop(xsltTransformContextPtr ctxt) { \ - type ret; \ - if (ctxt->name##Nr <= 0) return(0); \ - ctxt->name##Nr--; \ - if (ctxt->name##Nr > 0) \ - ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1]; \ - else \ - ctxt->name = (type) 0; \ - ret = ctxt->name##Tab[ctxt->name##Nr]; \ - ctxt->name##Tab[ctxt->name##Nr] = 0; \ - return(ret); \ -} \ + if (ctxt->templNr <= 0) + return (0); + ctxt->templNr--; + if (ctxt->templNr > 0) + ctxt->templ = ctxt->templTab[ctxt->templNr - 1]; + else + ctxt->templ = (xsltTemplatePtr) 0; + ret = ctxt->templTab[ctxt->templNr]; + ctxt->templTab[ctxt->templNr] = 0; + return (ret); +} +/** + * varsPush: + * @ctxt: the transformation context + * @value: the variable to push on the stack + * + * Push a variable on the stack + * + * Returns the new index in the stack or 0 in case of error + */ +static int +varsPush(xsltTransformContextPtr ctxt, xsltStackElemPtr value) +{ + if (ctxt->varsMax == 0) { + ctxt->varsMax = 4; + ctxt->varsTab = + (xsltStackElemPtr *) xmlMalloc(ctxt->varsMax * + sizeof(ctxt->varsTab[0])); + if (ctxt->varsTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "malloc failed !\n"); + return (0); + } + } + if (ctxt->varsNr >= ctxt->varsMax) { + ctxt->varsMax *= 2; + ctxt->varsTab = + (xsltStackElemPtr *) xmlRealloc(ctxt->varsTab, + ctxt->varsMax * + sizeof(ctxt->varsTab[0])); + if (ctxt->varsTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "realloc failed !\n"); + return (0); + } + } + ctxt->varsTab[ctxt->varsNr] = value; + ctxt->vars = value; + return (ctxt->varsNr++); +} +/** + * varsPop: + * @ctxt: the transformation context + * + * Pop a variable value from the stack + * + * Returns the stored variable value + */ +static xsltStackElemPtr +varsPop(xsltTransformContextPtr ctxt) +{ + xsltStackElemPtr ret; -/* - * Those macros actually generate the functions + if (ctxt->varsNr <= 0) + return (0); + ctxt->varsNr--; + if (ctxt->varsNr > 0) + ctxt->vars = ctxt->varsTab[ctxt->varsNr - 1]; + else + ctxt->vars = (xsltStackElemPtr) 0; + ret = ctxt->varsTab[ctxt->varsNr]; + ctxt->varsTab[ctxt->varsNr] = 0; + return (ret); +} +/** + * profPush: + * @ctxt: the transformation context + * @value: the profiling value to push on the stack + * + * Push a profiling value on the stack + * + * Returns the new index in the stack or 0 in case of error */ -PUSH_AND_POP(static, xsltTemplatePtr, templ) -PUSH_AND_POP(static, xsltStackElemPtr, vars) -PUSH_AND_POP(static, long, prof) +static int +profPush(xsltTransformContextPtr ctxt, long value) +{ + if (ctxt->profMax == 0) { + ctxt->profMax = 4; + ctxt->profTab = + (long *) xmlMalloc(ctxt->profMax * sizeof(ctxt->profTab[0])); + if (ctxt->profTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "malloc failed !\n"); + return (0); + } + } + if (ctxt->profNr >= ctxt->profMax) { + ctxt->profMax *= 2; + ctxt->profTab = + (long *) xmlRealloc(ctxt->profTab, + ctxt->profMax * sizeof(ctxt->profTab[0])); + if (ctxt->profTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "realloc failed !\n"); + return (0); + } + } + ctxt->profTab[ctxt->profNr] = value; + ctxt->prof = value; + return (ctxt->profNr++); +} +/** + * profPop: + * @ctxt: the transformation context + * + * Pop a profiling value from the stack + * + * Returns the stored profiling value + */ +static long +profPop(xsltTransformContextPtr ctxt) +{ + long ret; + + if (ctxt->profNr <= 0) + return (0); + ctxt->profNr--; + if (ctxt->profNr > 0) + ctxt->prof = ctxt->profTab[ctxt->profNr - 1]; + else + ctxt->prof = (long) 0; + ret = ctxt->profTab[ctxt->profNr]; + ctxt->profTab[ctxt->profNr] = 0; + return (ret); +} /************************************************************************ * * @@ -149,7 +281,7 @@ xsltSetXIncludeDefault(int xinclude) { /** * xsltGetXIncludeDefault: * - * return the default state for XInclude processing + * Provides the default state for XInclude processing * * Returns 0 if there is no processing 1 otherwise */ @@ -1021,6 +1153,7 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) { * xsltProcessOneNode: * @ctxt: a XSLT process context * @node: the node in the source tree. + * @params: extra parameters passed to the template if any * * Process the source node. */ @@ -3350,7 +3483,7 @@ xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID, /** * xsltApplyStripSpaces: * @ctxt: a XSLT process context - * @root: the root of the XML tree + * @node: the root of the XML tree * * Strip the unwanted ignorable spaces from the input tree */ diff --git a/libxslt/transform.h b/libxslt/transform.h index d32189f..80fb3ef 100644 --- a/libxslt/transform.h +++ b/libxslt/transform.h @@ -43,11 +43,6 @@ xmlDocPtr xsltApplyStylesheetUser (xsltStylesheetPtr style, */ void xsltApplyStripSpaces (xsltTransformContextPtr ctxt, xmlNodePtr node); -xsltTransformFunction - xsltExtElementLookup (xsltTransformContextPtr ctxt, - const xmlChar *name, - const xmlChar *URI); - xmlDocPtr xsltApplyStylesheet (xsltStylesheetPtr style, xmlDocPtr doc, const char **params); diff --git a/libxslt/variables.c b/libxslt/variables.c index 25e6edb..e022763 100644 --- a/libxslt/variables.c +++ b/libxslt/variables.c @@ -949,10 +949,9 @@ xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params) { /** * xsltEvalOneUserParam: - * * @ctxt: the XSLT transformation context * @name: a null terminated string giving the name of the parameter - * @value a null terminated string giving the XPath expression to be evaluated + * @value: a null terminated string giving the XPath expression to be evaluated * * This is normally called from xsltEvalUserParams to process a single * parameter from a list of parameters. The @value is evaluated as an @@ -976,10 +975,9 @@ xsltEvalOneUserParam(xsltTransformContextPtr ctxt, /** * xsltQuoteOneUserParam: - * * @ctxt: the XSLT transformation context * @name: a null terminated string giving the name of the parameter - * @value a null terminated string giving the parameter value + * @value: a null terminated string giving the parameter value * * This is normally called from xsltQuoteUserParams to process a single * parameter from a list of parameters. The @value is stored in the @@ -1167,7 +1165,7 @@ xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, * parse an XSLT transformation param declaration, compute * its value but doesn't record it. * - * It returns the new xsltStackElemPtr or NULL + * Returns the new xsltStackElemPtr or NULL */ xsltStackElemPtr diff --git a/libxslt/xslt.c b/libxslt/xslt.c index 73152e4..49b7bdc 100644 --- a/libxslt/xslt.c +++ b/libxslt/xslt.c @@ -68,53 +68,67 @@ double xmlXPathStringEvalNumber(const xmlChar *str); #define IS_BLANK_NODE(n) \ (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content))) -/* - * Generic function for accessing stacks in the stylesheet +/** + * exclPrefixPush: + * @style: the transformation stylesheet + * @value: the excluded prefix to push on the stack + * + * Push an excluded prefix on the stack + * + * Returns the new index in the stack or 0 in case of error */ - -#define PUSH_AND_POP(scope, type, name) \ -scope int name##Push(xsltStylesheetPtr style, type value) { \ - if (style->name##Max == 0) { \ - style->name##Max = 4; \ - style->name##Tab = (type *) xmlMalloc(style->name##Max * \ - sizeof(style->name##Tab[0])); \ - if (style->name##Tab == NULL) { \ - xmlGenericError(xmlGenericErrorContext, \ - "malloc failed !\n"); \ - return(0); \ - } \ - } \ - if (style->name##Nr >= style->name##Max) { \ - style->name##Max *= 2; \ - style->name##Tab = (type *) xmlRealloc(style->name##Tab, \ - style->name##Max * sizeof(style->name##Tab[0])); \ - if (style->name##Tab == NULL) { \ - xmlGenericError(xmlGenericErrorContext, \ - "realloc failed !\n"); \ - return(0); \ - } \ - } \ - style->name##Tab[style->name##Nr] = value; \ - style->name = value; \ - return(style->name##Nr++); \ -} \ -scope type name##Pop(xsltStylesheetPtr style) { \ - type ret; \ - if (style->name##Nr <= 0) return(0); \ - style->name##Nr--; \ - if (style->name##Nr > 0) \ - style->name = style->name##Tab[style->name##Nr - 1]; \ - else \ - style->name = NULL; \ - ret = style->name##Tab[style->name##Nr]; \ - style->name##Tab[style->name##Nr] = 0; \ - return(ret); \ -} \ - -/* - * Those macros actually generate the functions +static int +exclPrefixPush(xsltStylesheetPtr style, xmlChar * value) +{ + if (style->exclPrefixMax == 0) { + style->exclPrefixMax = 4; + style->exclPrefixTab = + (xmlChar * *)xmlMalloc(style->exclPrefixMax * + sizeof(style->exclPrefixTab[0])); + if (style->exclPrefixTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "malloc failed !\n"); + return (0); + } + } + if (style->exclPrefixNr >= style->exclPrefixMax) { + style->exclPrefixMax *= 2; + style->exclPrefixTab = + (xmlChar * *)xmlRealloc(style->exclPrefixTab, + style->exclPrefixMax * + sizeof(style->exclPrefixTab[0])); + if (style->exclPrefixTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "realloc failed !\n"); + return (0); + } + } + style->exclPrefixTab[style->exclPrefixNr] = value; + style->exclPrefix = value; + return (style->exclPrefixNr++); +} +/** + * exclPrefixPop: + * @style: the transformation stylesheet + * + * Pop an excluded prefix value from the stack + * + * Returns the stored excluded prefix value */ -PUSH_AND_POP(static, xmlChar *, exclPrefix) +static xmlChar * +exclPrefixPop(xsltStylesheetPtr style) +{ + xmlChar *ret; + + if (style->exclPrefixNr <= 0) + return (0); + style->exclPrefixNr--; + if (style->exclPrefixNr > 0) + style->exclPrefix = style->exclPrefixTab[style->exclPrefixNr - 1]; + else + style->exclPrefix = NULL; + ret = style->exclPrefixTab[style->exclPrefixNr]; + style->exclPrefixTab[style->exclPrefixNr] = 0; + return (ret); +} /************************************************************************ * * @@ -240,11 +254,13 @@ xsltFreeDecimalFormatList(xsltStylesheetPtr self) * @name: the decimal-format name to find * * Find decimal-format by name + * + * Returns the xsltDecimalFormatPtr */ xsltDecimalFormatPtr xsltDecimalFormatGetByName(xsltStylesheetPtr sheet, xmlChar *name) { - xsltDecimalFormatPtr result; + xsltDecimalFormatPtr result = NULL; if (name == NULL) return sheet->decimalFormat; diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index fd3f467..e1abbea 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -50,8 +50,29 @@ struct _xsltRuntimeExtra { void *val; /* data not needing deallocation */ }; +/** + * XSLT_RUNTIME_EXTRA_LST: + * @ctxt: the transformation context + * @nr: the index + * + * Macro used to access extra information stored in the context + */ #define XSLT_RUNTIME_EXTRA_LST(ctxt, nr) (ctxt)->extras[(nr)].info +/** + * XSLT_RUNTIME_EXTRA_FREE: + * @ctxt: the transformation context + * @nr: the index + * + * Macro used to free extra information stored in the context + */ #define XSLT_RUNTIME_EXTRA_FREE(ctxt, nr) (ctxt)->extras[(nr)].deallocate +/** + * XSLT_RUNTIME_EXTRA: + * @ctxt: the transformation context + * @nr: the index + * + * Macro used to define extra information stored in the context + */ #define XSLT_RUNTIME_EXTRA(ctxt, nr) (ctxt)->extras[(nr)].val /** diff --git a/libxslt/xsltutils.c b/libxslt/xsltutils.c index 58922a0..f9260cd 100644 --- a/libxslt/xsltutils.c +++ b/libxslt/xsltutils.c @@ -476,6 +476,8 @@ xsltSetTransformErrorFunc(xsltTransformContextPtr ctxt, /** * xsltTransformError: * @ctxt: an XSLT transformation context + * @style: the XSLT stylesheet used + * @node: the current node in the stylesheet * @msg: the message to display/transmit * @...: extra parameters for the message display * @@ -631,10 +633,12 @@ xsltDocumentSortFunction(xmlNodeSetPtr list) { /** * xsltComputeSortResult: * @ctxt: a XSLT process context - * @sorts: array of sort nodes + * @sort: node list * * reorder the current node list accordingly to the set of sorting * requirement provided by the array of nodes. + * + * Returns a ordered XPath nodeset or NULL in case of error. */ xmlXPathObjectPtr * xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) { @@ -1321,7 +1325,6 @@ xsltSaveResultToFd(int fd, xmlDocPtr result, xsltStylesheetPtr style) { * @doc_txt_len: Length of the generated XML text * @result: the result xmlDocPtr * @style: the stylesheet - * @compression: the compression factor (0 - 9 included) * * Save the result @result obtained by applying the @style stylesheet * to a file or @URL @@ -1715,7 +1718,7 @@ static xsltDebuggerCallbacks xsltDebuggerCurrentCallbacks = { int xslDebugStatus; /** - * xslSetDebuggerCallbacks: + * xsltSetDebuggerCallbacks: * @no : number of callbacks * @block : the block of callbacks * @@ -1777,7 +1780,7 @@ xslAddCall(xsltTemplatePtr templ, xmlNodePtr source) } /** - * xslDropCall : + * xslDropCall: * * Drop the topmost item off the call stack */ diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h index b935b41..47448f6 100644 --- a/libxslt/xsltutils.h +++ b/libxslt/xsltutils.h @@ -24,7 +24,7 @@ extern "C" { #endif /** - * TODO: + * XSLT_TODO: * * Macro to flag unimplemented blocks. */ @@ -34,7 +34,7 @@ extern "C" { __FILE__, __LINE__); /** - * STRANGE: + * XSLT_STRANGE: * * Macro to flag that a problem was detected internally. */ @@ -175,6 +175,11 @@ xmlDocPtr xsltGetProfileInformation (xsltTransformContextPtr ctxt); long xsltTimestamp (void); void xsltCalibrateAdjust (long delta); +/** + * XSLT_TIMESTAMP_TICS_PER_SEC: + * + * Sampling precision for profiling + */ #define XSLT_TIMESTAMP_TICS_PER_SEC 100000l /* diff --git a/python/libxsltclass.txt b/python/libxsltclass.txt index 8ec7d17..12b6abc 100644 --- a/python/libxsltclass.txt +++ b/python/libxsltclass.txt @@ -33,6 +33,7 @@ isBlank() loadStylesheetPI() newStylesheet() parseStylesheetDoc() +parseStylesheetFile() # functions from module xsltutils calibrateAdjust() @@ -110,6 +111,8 @@ Class transformCtxt() # functions from module templates attrListTemplateProcess() attrTemplateProcess() + attrTemplateValueProcess() + attrTemplateValueProcessNode() evalAttrValueTemplate() evalTemplateString() @@ -118,6 +121,9 @@ Class transformCtxt() freeTransformContext() registerAllElement() + # functions from module transform.c + copyTree() + # functions from module variables evalGlobalVariables() evalOneUserParam() -- 2.7.4