- DOM parser replaced by SAX parser

git-svn-id: https://svn.code.sf.net/p/libusbjava/code/trunk@117 94ad28fe-ef68-46b1-9651-e7ae4fcf1c4c
This commit is contained in:
schlaepfer
2006-03-16 15:33:19 +00:00
parent dbe7b547f7
commit e39c8308f0
2 changed files with 157 additions and 199 deletions

View File

@@ -6,66 +6,48 @@ import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.LinkedList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Representation of a register dictionary. All registers are read from an
* xml-file specified by <code>registerDictionary.dtd</code>. Note that the
* type values are implementation specific. Therefore each <i>Register</i> has
* its own <i>registerDictionary.dtd</i> definition. For an example see
* <code>MPC555Register</code> and the corresponding
* <code>resources/targets/mpc555/registerDictionary.dtd</code> file.
*
* @author schlaepfer
*/
public abstract class RegisterDict {
private LinkedList registers;
private Class<? extends Register> regClass;
private Method regClassGetTypesMethod;
private static final String GetTypes_METHOD_NAME = "getTypes";
private String[] types;
public abstract class RegisterDict extends DefaultHandler {
private static final long serialVersionUID = -582382284126896830L;
private static final String REGISTER_DEFINITIONS = "registerDefinitions";
private Class<? extends Register> regClass;
private Method regClassGetTypesMethod;
private static final String GetTypes_METHOD_NAME = "getTypes";
private static final String REGISTER_GROUP = "registerGroup";
private LinkedList registers;
private static final String REG_GROUP_ATTR_BASEADDR = "baseAddress";
private String[] types;
private static final String REGISTER = "register";
private static final String ELEMENT_REGISTER = "register";
private static final String ELEMENT_DESCRIPTION = "description";
private static final String DESCRIPTION = "description";
private static final String ATTR_MNEMONIC = "mnemonic";
private static final String ATTR_ALTMNEMONIC = "altmnemonic";
private static final String ATTR_TYPE = "type";
private static final String ATTR_VALUE = "value";
private static final String ATTR_SIZE = "size";
private static final String ATTR_ACCESSMODE = "accessmode";
private static final String ATTR_ACCESSATTR = "accessattr";
private static final String REG_ATTR_MNEMONIC = "mnemonic";
private static final String REG_ATTR_TYPE = "type";
private static final String REG_ATTR_VALUE = "value";
private static final String REG_ATTR_SIZE = "size";
private Register reg;
private StringBuffer cdata;
/**
* Default constructor which takes the Class object from a
* <code>Register</code> subclass as argument. The registerDict will be of
* this Register-type.<br>
* An example:<br>
* MPC555Register extends Register -> use MPC555Register.class as parameter.
* MPC555Register extends Register -> use <code>MPC555Register.class</code>
* as parameter.
*
* @param registerClass
* subclass of Register
@@ -85,44 +67,13 @@ public abstract class RegisterDict {
this.registers = new LinkedList();
}
/**
* Add a new register to the registerDict.
*
* @param name
* name of the register. Registers are identified by this value.
* @param type
* register specific type
* @param value
* address or a register specific value (e.g. BDI-identifier)
* @param size
* size in bytes
* @param description
* a string description of the register
*/
@SuppressWarnings("unchecked")
public void add(String name, int type, int value, int size,
String description) {
// remove before add for updates
for (Iterator i = registers.iterator(); i.hasNext();) {
Register r = (Register) i.next();
if (r.getMnemonic().equals(name) || r.getAltmnemonic().equals(name)) {
i.remove();
private int convertType(String typeStr) throws SAXException {
for (int index = 0; index < types.length; index++) {
if (typeStr.equals(types[index])) {
return index;
}
}
Register reg = null;
try {
reg = (Register) regClass.newInstance();
reg.setMnemonic(name);
reg.setType(type);
reg.setValue(value);
reg.setSize(size);
reg.setDescription(description);
} catch (Exception e) {
e.printStackTrace();
// TODO exception handling
System.exit(1);
}
registers.add(reg);
throw new SAXException("invalid register definition: " + typeStr);
}
private int parseInt(String s) {
@@ -146,20 +97,37 @@ public abstract class RegisterDict {
}
/**
* Get a register by its name.
* Adds the registers from the specified xml-file to the register
* dictionary. <br>
* The xml-file must be structured according to
* <code>registerDictionary.dtd</code>. The dtd-file must be adapted to
* the type values specific to this register. Include
* <code><!DOCTYPE registerDefinitions SYSTEM "registerDictionary.dtd"></code>
* in your xml file.
*
* @param name
* the register name
* @return register on null if no register is found
* @param xmlPathname
* path to the xml file
* @throws IOException
* throws an IOException if the file is not found
* @throws SAXException
* @throws ParserConfigurationException
* @throws ParserConfigurationException
* throws an ParserConfigurationException if the SAX parser
* can't be configured
* @throws SAXException
* throws an SAXException if the file could not be successfully
* parsed
*/
public Register getRegister(String name) {
for (Iterator i = registers.iterator(); i.hasNext();) {
Register r = (Register) i.next();
if (r.getMnemonic().equals(name) || r.getAltmnemonic().equals(name)) {
return r;
}
}
return null;
public void addRegistersFromFile(String xmlPathname) throws IOException,
ParserConfigurationException, SAXException {
// reset temporary register variable
reg = null;
// Use the default (non-validating) parser
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);
// Parse the input
SAXParser saxParser = factory.newSAXParser();
saxParser.parse(new File(xmlPathname), this);
}
/**
@@ -181,122 +149,112 @@ public abstract class RegisterDict {
}
/**
* Adds the registers from the specified xml-file to the register
* dictionary. <br>
* The xml-file must be structured according to
* <code>registerDictionary.dtd</code>. The dtd-file must be adapted to
* the type values specific to this register. Include
* <code><!DOCTYPE registerDefinitions SYSTEM "registerDictionary.dtd"></code>
* in your xml file.
* Get a register by its name.
*
* @param xmlPathname
* path to the xml file
* @throws IOException
* throws an IOException if the file is not found
* @throws ParserConfigurationException
* throws an ParserConfigurationException if the SAX parser
* can't be configured
* @throws SAXException
* throws an SAXException if the file could not be successfully
* parsed
* @param name
* the register name
* @return register on null if no register is found
*/
public void addRegistersFromFile(String xmlPathname) throws IOException,
ParserConfigurationException, SAXException {
Document document;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setErrorHandler(new ErrorHandler() {
// ignore fatal errors (an exception is guaranteed)
public void fatalError(SAXParseException exception)
throws SAXException {
public Register getRegister(String name) {
for (Iterator i = registers.iterator(); i.hasNext();) {
Register r = (Register) i.next();
if (r.getMnemonic().equals(name) || r.getAltmnemonic().equals(name)) {
return r;
}
}
return null;
}
// treat validation errors as fatal error
public void error(SAXParseException e) throws SAXParseException {
throw e;
}
// ===========================================================
// SAX DocumentHandler methods
// ===========================================================
// treat warnings as fatal error
public void warning(SAXParseException e) throws SAXParseException {
throw e;
}
});
document = builder.parse(new File(xmlPathname));
NodeList list = document.getElementsByTagName(REGISTER_DEFINITIONS);
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i).getNodeName().equals(REGISTER_DEFINITIONS)) {
list = list.item(i).getChildNodes();
}
for (int j = 0; j < list.getLength(); j++) {
if (list.item(j).getNodeName().equals(REGISTER_GROUP)) {
NamedNodeMap attributes = list.item(j).getAttributes();
for (int k = 0; k < attributes.getLength(); k++) {
if (attributes.item(k).getNodeName().equals(
REG_GROUP_ATTR_BASEADDR)) {
int baseAddr = parseInt(attributes.item(k)
.getNodeValue());
parseRegisterGroup(list.item(j), baseAddr);
}
}
} else if (list.item(j).getNodeName().equals(REGISTER)) {
NamedNodeMap attributes = list.item(j).getAttributes();
// attributes: name, type, offset, size
Node n = attributes.getNamedItem(REG_ATTR_MNEMONIC);
String name = n.getNodeValue();
n = attributes.getNamedItem(REG_ATTR_TYPE);
String typeStr = n.getNodeValue();
int type = convertType(typeStr);
n = attributes.getNamedItem(REG_ATTR_VALUE);
int value = parseInt(n.getNodeValue());
n = attributes.getNamedItem(REG_ATTR_SIZE);
int size = parseInt(n.getNodeValue());
parseRegister(list.item(j), name, type, value, size);
public void startDocument() throws SAXException {
}
public void endDocument() throws SAXException {
}
public void startElement(String namespaceURI, String lName, // local name
String qName, // qualified name
Attributes attrs) throws SAXException {
if (qName.equals(ELEMENT_REGISTER)) {
if (attrs != null) {
// instantiate new register
try {
reg = (Register) regClass.newInstance();
} catch (Exception e) {
throw new SAXException(e.getMessage());
}
for (int i = 0; i < attrs.getLength(); i++) {
String attr_qName = attrs.getQName(i);
String attr_value = attrs.getValue(i);
if (attr_qName.equals(ATTR_MNEMONIC)) {
reg.setMnemonic(attr_value);
} else if (attr_qName.equals(ATTR_ALTMNEMONIC)) {
reg.setAltmnemonic(attr_value);
} else if (attr_qName.equals(ATTR_TYPE)) {
reg.setType(convertType(attr_value));
} else if (attr_qName.equals(ATTR_SIZE)) {
reg.setSize(parseInt(attr_value));
} else if (attr_qName.equals(ATTR_VALUE)) {
reg.setValue(parseInt(attr_value));
} else if (attr_qName.equals(ATTR_ACCESSMODE)) {
reg.setAccessmode(Register.Accessmode
.valueOf(attr_value));
} else if (attr_qName.equals(ATTR_ACCESSATTR)) {
reg.setAccessattr(Register.Accessattr
.valueOf(attr_value));
}
}
} else {
throw new SAXException("attributes expected");
}
} else if (qName.equals(ELEMENT_DESCRIPTION)) {
// reset the cdata for descriptions
cdata = new StringBuffer();
}
}
protected int convertType(String typeStr) throws SAXException {
for (int index = 0; index < types.length; index++) {
if (typeStr.equals(types[index])) {
return index;
}
@SuppressWarnings("unchecked")
public void endElement(String namespaceURI, String sName, // simple
// name
String qName // qualified name
) throws SAXException {
if (qName.equals(ELEMENT_DESCRIPTION)) {
reg.setDescription(cdata.toString().trim());
}
throw new SAXException("invalid register definition: " + typeStr);
}
private void parseRegisterGroup(Node registerGroup, int baseAddr)
throws SAXException {
NodeList list = registerGroup.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i).getNodeName().equals(REGISTER)) {
NamedNodeMap attributes = list.item(i).getAttributes();
// attributes: name, type, offset, size
Node n = attributes.getNamedItem(REG_ATTR_MNEMONIC);
String name = n.getNodeValue();
n = attributes.getNamedItem(REG_ATTR_TYPE);
String typeStr = n.getNodeValue();
int type = convertType(typeStr);
n = attributes.getNamedItem(REG_ATTR_VALUE);
int offset = parseInt(n.getNodeValue());
n = attributes.getNamedItem(REG_ATTR_SIZE);
int size = parseInt(n.getNodeValue());
parseRegister(list.item(i), name, type, baseAddr + offset, size);
}
if (reg != null) {
registers.add(reg);
reg = null;
}
}
private void parseRegister(Node register, String name, int type, int addr,
int size) throws SAXException {
NodeList list = register.getChildNodes();
String description = "";
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i).getNodeName().equals(DESCRIPTION)) {
description = list.item(i).getTextContent();
}
public void characters(char buf[], int offset, int len) throws SAXException {
int startOffset = offset;
while ((offset < startOffset + len) && (buf[offset] <= ' ')) {
offset++;
}
add(name, type, addr, size, description);
len -= offset - startOffset;
while ((len > 0) && (buf[offset + len - 1] <= ' ')) {
len--;
}
cdata.append(buf, offset, len);
}
// ===========================================================
// SAX ErrorHandler methods
// ===========================================================
// treat validation errors as fatal
public void error(SAXParseException e) throws SAXParseException {
throw e;
}
// dump warnings too
public void warning(SAXParseException err) throws SAXParseException {
System.out.println("** Warning" + ", line " + err.getLineNumber()
+ ", uri " + err.getSystemId());
System.out.println(" " + err.getMessage());
}
}

View File

@@ -32,15 +32,15 @@ public class IMCBTargetBoard {
logger.info("writeRegister: " + name + ", value: 0x"
+ Integer.toHexString(value));
MC68332Register r = (MC68332Register) regDict.getRegister(name);
switch (r.type) {
switch (r.getType()) {
case MC68332Register.CtrlReg:
bdi.writeMem(r.value, value, r.size);
bdi.writeMem(r.getValue(), value, r.getSize());
break;
case MC68332Register.SysReg:
bdi.writeSysReg(r.value, value);
bdi.writeSysReg(r.getValue(), value);
break;
case MC68332Register.UserReg:
bdi.writeUserReg(r.value, value);
bdi.writeUserReg(r.getValue(), value);
break;
}
}
@@ -49,13 +49,13 @@ public class IMCBTargetBoard {
DispatchException, BDIException {
logger.info("readRegister: " + name);
MC68332Register r = (MC68332Register) regDict.getRegister(name);
switch (r.type) {
switch (r.getType()) {
case MC68332Register.CtrlReg:
return bdi.readMem(r.value, r.size);
return bdi.readMem(r.getValue(), r.getSize());
case MC68332Register.SysReg:
return bdi.readSysReg(r.value);
return bdi.readSysReg(r.getValue());
case MC68332Register.UserReg:
return bdi.readUserReg(r.value);
return bdi.readUserReg(r.getValue());
}
return -1;
}