-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Python parser language-independent parts.
- Loading branch information
Eamon Walsh
authored and
Eamon F Walsh
committed
Apr 19, 2008
1 parent
b15d25b
commit 7820273
Showing
10 changed files
with
859 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
SUBDIRS=src | ||
SUBDIRS = src xcbgen | ||
|
||
pkgconfigdir = $(libdir)/pkgconfig | ||
pkgconfig_DATA = xcb-proto.pc | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pkgpythondir = $(pythondir)/xcbgen | ||
|
||
pkgpython_PYTHON = __init__.py error.py expr.py matcher.py state.py types.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
class ResolveException(Exception): | ||
''' | ||
Gets thrown when a type doesn't resolve in the XML. | ||
''' | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
''' | ||
This module contains helper classes for structure fields and length expressions. | ||
''' | ||
class Field(object): | ||
''' | ||
Represents a field of a structure. | ||
type is the datatype object for the field. | ||
field_type is the name of the type (string tuple) | ||
field_name is the name of the structure field. | ||
visible is true iff the field should be in the request API. | ||
wire is true iff the field should be in the request structure. | ||
auto is true iff the field is on the wire but not in the request API (e.g. opcode) | ||
''' | ||
def __init__(self, type, field_type, field_name, visible, wire, auto): | ||
self.type = type | ||
self.field_type = field_type | ||
self.field_name = field_name | ||
self.visible = visible | ||
self.wire = wire | ||
self.auto = auto | ||
|
||
|
||
class Expression(object): | ||
''' | ||
Represents a mathematical expression for a list length or exprfield. | ||
Public fields: | ||
op is the operation (text +,*,/,<<) or None. | ||
lhs and rhs are the sub-Expressions if op is set. | ||
lenfield_name is the name of the length field, or None for request lists. | ||
lenfield is the Field object for the length field, or None. | ||
bitfield is True if the length field is a bitmask instead of a number. | ||
nmemb is the fixed size (value)of the expression, or None | ||
''' | ||
def __init__(self, elt, parent): | ||
self.parent = parent | ||
|
||
self.nmemb = None | ||
|
||
self.lenfield_name = None | ||
self.lenfield_type = None | ||
self.lenfield = None | ||
self.lenwire = False | ||
self.bitfield = False | ||
|
||
self.op = None | ||
self.lhs = None | ||
self.rhs = None | ||
|
||
if elt.tag == 'list': | ||
# List going into a request, which has no length field (inferred by server) | ||
self.lenfield_name = elt.get('name') + '_len' | ||
self.lenfield_type = 'CARD32' | ||
|
||
elif elt.tag == 'fieldref': | ||
# Standard list with a fieldref | ||
self.lenfield_name = elt.text | ||
|
||
elif elt.tag == 'valueparam': | ||
# Value-mask. The length bitmask is described by attributes. | ||
self.lenfield_name = elt.get('value-mask-name') | ||
self.lenfield_type = elt.get('value-mask-type') | ||
self.lenwire = True | ||
self.bitfield = True | ||
|
||
elif elt.tag == 'op': | ||
# Op field. Need to recurse. | ||
self.op = elt.get('op') | ||
self.lhs = Expression(list(elt)[0], parent) | ||
self.rhs = Expression(list(elt)[1], parent) | ||
|
||
# Hopefully we don't have two separate length fields... | ||
self.lenfield_name = self.lhs.lenfield_name | ||
if self.lenfield_name == None: | ||
self.lenfield_name = self.rhs.lenfield_name | ||
|
||
elif elt.tag == 'value': | ||
# Constant expression | ||
self.nmemb = int(elt.text) | ||
|
||
else: | ||
# Notreached | ||
raise Exception('XXX') | ||
|
||
|
||
def fixed_size(self): | ||
return self.nmemb != None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
''' | ||
XML parser. One function for each top-level element in the schema. | ||
Most functions just declare a new object and add it to the module. | ||
For typedefs, eventcopies, xidtypes, and other aliases though, | ||
we do not create a new type object, we just record the existing one under a new name. | ||
''' | ||
|
||
from os.path import join | ||
from xml.etree.cElementTree import parse | ||
|
||
import state | ||
from types import * | ||
|
||
def import_(node, module, namespace): | ||
''' | ||
For imports, we load the file, create a new namespace object, | ||
execute recursively, then record the import (for header files, etc.) | ||
''' | ||
new_file = join(namespace.dir, '%s.xml' % node.text) | ||
new_root = parse(new_file).getroot() | ||
new_namespace = state.Namespace(new_file) | ||
execute(module, new_namespace) | ||
if not module.has_import(node.text): | ||
module.add_import(node.text, new_namespace) | ||
|
||
def typedef(node, module, namespace): | ||
id = node.get('newname') | ||
name = namespace.prefix + (id,) | ||
type = module.get_type(node.get('oldname')) | ||
module.add_type(id, namespace.ns, name, type) | ||
|
||
def xidtype(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
type = module.get_type('CARD32') | ||
module.add_type(id, namespace.ns, name, type) | ||
|
||
def xidunion(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
type = module.get_type('CARD32') | ||
module.add_type(id, namespace.ns, name, type) | ||
|
||
def enum(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
type = Enum(name, node) | ||
module.add_type(id, namespace.ns, name, type) | ||
|
||
def struct(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
type = Struct(name, node) | ||
module.add_type(id, namespace.ns, name, type) | ||
|
||
def union(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
type = Union(name, node) | ||
module.add_type(id, namespace.ns, name, type) | ||
|
||
def request(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
type = Request(name, node) | ||
module.add_request(id, name, type) | ||
|
||
def event(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
event = Event(name, node) | ||
event.add_opcode(node.get('number'), name, True) | ||
module.add_event(id, name, event) | ||
|
||
def eventcopy(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
event = module.get_event(node.get('ref')) | ||
event.add_opcode(node.get('number'), name, False) | ||
module.add_event(id, name, event) | ||
|
||
def error(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
error = Error(name, node) | ||
error.add_opcode(node.get('number'), name, True) | ||
module.add_error(id, name, error) | ||
|
||
def errorcopy(node, module, namespace): | ||
id = node.get('name') | ||
name = namespace.prefix + (id,) | ||
error = module.get_error(node.get('ref')) | ||
error.add_opcode(node.get('number'), name, False) | ||
module.add_error(id, name, error) | ||
|
||
funcs = {'import' : import_, | ||
'typedef' : typedef, | ||
'xidtype' : xidtype, | ||
'xidunion' : xidunion, | ||
'enum' : enum, | ||
'struct' : struct, | ||
'union' : union, | ||
'request' : request, | ||
'event' : event, | ||
'eventcopy' : eventcopy, | ||
'error' : error, | ||
'errorcopy' : errorcopy} | ||
|
||
def execute(module, namespace): | ||
for elt in list(namespace.root): | ||
funcs[elt.tag](elt, module, namespace) |
Oops, something went wrong.