diff options
Diffstat (limited to 'src/pkg/xgb/go_client.py')
-rw-r--r-- | src/pkg/xgb/go_client.py | 704 |
1 files changed, 0 insertions, 704 deletions
diff --git a/src/pkg/xgb/go_client.py b/src/pkg/xgb/go_client.py deleted file mode 100644 index f26548000..000000000 --- a/src/pkg/xgb/go_client.py +++ /dev/null @@ -1,704 +0,0 @@ -#!/usr/bin/env python -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -from xml.etree.cElementTree import * -from os.path import basename, exists -import getopt -import sys -import re -import math - -_ns = None - -outfile = None -golines = [] -def go(fmt, *args): - golines.append(fmt % args) - -namere = re.compile('([A-Z0-9][a-z]+|[A-Z0-9]+(?![a-z])|[a-z]+)') -allcaps = re.compile('^[A-Z0-9]+$') - -sizeoftab = { - "byte": 1, - "int8": 1, - "uint8": 1, - "int16": 2, - "uint16": 2, - "int32": 4, - "uint32": 4, - "float32": 4, - "float64": 8, - "Id": 4, - "Keysym": 4, - "Timestamp": 4, -} - -def sizeof(t): - if t in sizeoftab: - return sizeoftab[t] - return 4 - -symbols = [] - -def readsymbols(filename): - symbols.append("XXX Dummy XXX") - if exists(filename): - for line in open(filename, 'r').readlines(): - symbols.append(line.strip()) - -# -# Name munging crap for names, enums and types. -# - -mangletab = { - "int8_t": "int8", - "uint8_t": "byte", - "uint16_t": "uint16", - "uint32_t": "uint32", - "int16_t": "int16", - "int32_t": "int32", - "float": "float32", - "double": "float64", - "char": "byte", - "void": "byte", - 'VISUALTYPE': 'VisualInfo', - 'DEPTH': 'DepthInfo', - 'SCREEN': 'ScreenInfo', - 'Setup': 'SetupInfo', - 'WINDOW': 'Id', -} - -def mangle(str): - if str in mangletab: - return mangletab[str] - return str - -def camel(str): - return str[0].upper() + str[1:] -def uncamel(str): - return str[0].lower() + str[1:] - -def nitem(str): - split = namere.finditer(str) - return ''.join([camel(match.group(0)) for match in split]) - -def titem(str): - str = mangle(str) - if str in sizeoftab: - return str - if allcaps.match(str): - return str.capitalize() - return nitem(str) - -def n(list): - "Mangle name (JoinedCamelCase) and chop off 'xcb' prefix." - if len(list) == 1: - parts = [nitem(list[0])] - else: - parts = [nitem(x) for x in list[1:]] - return ''.join(parts) - -def t(list): - "Mangle name (JoinedCamelCase) and chop off 'xcb' prefix. Preserve primitive type names." - if len(list) == 1: - return titem(list[0]) - else: - parts = [titem(x) for x in list[1:]] - return ''.join(parts) - -# -# Various helper functions -# - -def go_type_setup(self, name, postfix): - ''' - Sets up all the Go-related state by adding additional data fields to - all Field and Type objects. Here is where we figure out most of our - variable and function names. - - Recurses into child fields and list member types. - ''' - # Do all the various names in advance - self.c_type = t(name + postfix) - self.c_request_name = n(name) - self.c_reply_name = n(name + ('Reply',)) - self.c_reply_type = t(name + ('Reply',)) - - if not self.is_container: - return - - offset = 0 - for field in self.fields: - go_type_setup(field.type, field.field_type, ()) - if field.type.is_list: - go_type_setup(field.type.member, field.field_type, ()) - field.c_field_type = t(field.field_type) - field.c_field_name = n((field.field_name,)) - field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else '' - field.c_pointer = ' ' if field.type.nmemb == 1 else '[]' - field.c_offset = offset - if field.type.fixed_size(): - offset += field.type.size * field.type.nmemb - -def go_accessor_length(expr, prefix, iswriting): - ''' - Figures out what C code is needed to get a length field. - For fields that follow a variable-length field, use the accessor. - Otherwise, just reference the structure field directly. - ''' - prefarrow = '' if prefix == '' else prefix + '.' - if expr.lenfield_name != None: - lenstr = prefarrow + n((expr.lenfield_name,)) - if iswriting and lenstr.endswith("Len"): - # chop off ...Len and refer to len(array) instead - return "len(" + lenstr[:-3] + ")" - return "int(" + lenstr + ")" - else: - return str(expr.nmemb) - -def go_accessor_expr(expr, prefix, iswriting): - ''' - Figures out what C code is needed to get the length of a list field. - Recurses for math operations. - Returns bitcount for value-mask fields. - Otherwise, uses the value of the length field. - ''' - lenexp = go_accessor_length(expr, prefix, iswriting) - if expr.op != None: - return '(' + go_accessor_expr(expr.lhs, prefix, iswriting) + ' ' + expr.op + ' ' + go_accessor_expr(expr.rhs, prefix, iswriting) + ')' - elif expr.bitfield: - return 'popCount(' + lenexp + ')' - else: - return lenexp - -def go_complex(self, fieldlist=None): - ''' - Helper function for handling all structure types. - Called for all structs, requests, replies, events, errors. - ''' - if self.is_union: - go('type %s struct /*union */ {', self.c_type) - else: - go('type %s struct {', self.c_type) - if not fieldlist: - fieldlist = self.fields - for field in fieldlist: - if field.type.is_pad: - continue - if field.wire and field.type.fixed_size(): - go(' %s %s%s', field.c_field_name, field.c_subscript, field.c_field_type) - if field.wire and not field.type.fixed_size(): - go(' %s []%s', field.c_field_name, field.c_field_type) - go('}') - go('') - -def go_get(dst, ofs, typename, typesize): - dst = "v." + dst - if typesize == 1: - if typename == 'byte': - go('%s = b[%s]', dst, ofs) - else: - go('%s = %s(b[%s])', dst, typename, ofs) - elif typesize == 2: - if typename == 'uint16': - go('%s = get16(b[%s:])', dst, ofs) - else: - go('%s = %s(get16(b[%s:]))', dst, typename, ofs) - elif typesize == 4: - if typename == 'uint32': - go('%s = get32(b[%s:])', dst, ofs) - else: - go('%s = %s(get32(b[%s:]))', dst, typename, ofs) - else: - go('get%s(b[%s:], &%s)', typename, ofs, dst) - -def go_get_list(dst, ofs, typename, typesize, count): - if typesize == 1 and typename == 'byte': - go('copy(v.%s[0:%s], b[%s:])', dst, count, ofs) - else: - go('for i := 0; i < %s; i++ {', count) - go_get(dst + "[i]", ofs + "+i*" + str(typesize), typename, typesize) - go('}') - - -def go_complex_reader_help(self, fieldlist): - firstvar = 1 - total = 0 - for field in fieldlist: - fieldname = field.c_field_name - fieldtype = field.c_field_type - if field.wire and field.type.fixed_size(): - total = field.c_offset + field.type.size * field.type.nmemb - if field.type.is_pad: - continue - if field.type.nmemb == 1: - go_get(fieldname, field.c_offset, fieldtype, field.type.size) - else: - go_get_list(fieldname, field.c_offset, fieldtype, field.type.size, field.type.nmemb) - if field.wire and not field.type.fixed_size(): - lenstr = go_accessor_expr(field.type.expr, 'v', False) - if firstvar: - firstvar = 0 - go('offset := %d', field.c_offset) - else: - go('offset = pad(offset)') - go('v.%s = make([]%s, %s)', fieldname, fieldtype, lenstr) - if fieldtype in sizeoftab: - go_get_list(fieldname, "offset", fieldtype, sizeoftab[fieldtype], "len(v."+fieldname+")") - go('offset += len(v.%s) * %d', fieldname, sizeoftab[fieldtype]) - else: - go('for i := 0; i < %s; i++ {', lenstr) - go(' offset += get%s(b[offset:], &v.%s[i])', fieldtype, fieldname) - go('}') - if not firstvar: - return 'offset' - return str(total) - -def go_complex_reader(self): - go('func get%s(b []byte, v *%s) int {', self.c_type, self.c_type) - go(' return %s', go_complex_reader_help(self, self.fields)) - go('}') - go('') - -def structsize(fieldlist): - fixedtotal = 0 - for field in fieldlist: - if field.wire and field.type.fixed_size(): - fixedtotal += field.type.size * field.type.nmemb - return fixedtotal - -def go_put(src, ofs, typename, typesize): - if typesize == 1: - if typename == 'byte': - go('b[%s] = %s', ofs, src) - else: - go('b[%s] = byte(%s)', ofs, src) - elif typesize == 2: - if typename == 'uint16': - go('put16(b[%s:], %s)', ofs, src) - else: - go('put16(b[%s:], uint16(%s))', ofs, src) - elif typesize == 4: - if typename == 'uint32': - go('put32(b[%s:], %s)', ofs, src) - else: - go('put32(b[%s:], uint32(%s))', ofs, src) - else: - go('put%s(b[%s:], %s)', typename, ofs, src) - - -def go_complex_writer_help(fieldlist, prefix=''): - prefarrow = '' if prefix == '' else prefix + '.' - for field in fieldlist: - fieldname = prefarrow + field.c_field_name - fieldtype = field.c_field_type - if fieldname.endswith("Len"): - fieldname = "len(%s)" % fieldname[:-3] - fieldtype = "(exp)" - if not field.type.fixed_size(): - continue - if field.type.is_expr: - expstr = go_accessor_expr(field.type.expr, prefix, True) - go_put(expstr, field.c_offset, "(exp)", field.type.size) - elif not field.type.is_pad: - if field.type.nmemb == 1: - go_put(fieldname, field.c_offset, fieldtype, field.type.size) - else: - go(' copy(b[%d:%d], %s)', field.c_offset, field.c_offset + field.type.nmemb, fieldname) - -def go_complex_writer_arguments(param_fields, endstr): - out = [] - for field in param_fields: - namestr = field.c_field_name - typestr = field.c_pointer + t(field.field_type) - if typestr == '[]byte' and namestr == 'Name': - typestr = 'string' - out.append(namestr + ' ' + typestr) - go(' ' + ', '.join(out) + ')' + endstr) - -def go_complex_writer_arguments_names(param_fields): - out = [] - for field in param_fields: - out.append(field.c_field_name) - return ', '.join(out) - -def go_complex_writer(self, name, void): - func_name = self.c_request_name - - param_fields = [] - wire_fields = [] - for field in self.fields: - if field.visible: - # _len is taken from the list directly - if not field.field_name.endswith("_len"): - # The field should appear as a call parameter - param_fields.append(field) - if field.wire and not field.auto: - # We need to set the field up in the structure - wire_fields.append(field) - - if void: - go('func (c *Conn) %s(', func_name) - go_complex_writer_arguments(param_fields, "{") - else: - go('func (c *Conn) %sRequest(', func_name) - go_complex_writer_arguments(param_fields, "Cookie {") - - fixedlength = math.ceil(float(structsize(self.fields)) / float(4)) - fixedsize = fixedlength * 4 - - if fixedsize <= 32: - go(' b := c.scratch[0:%d]', fixedsize) - else: - go(' b := make([]byte, %d)', fixedsize) - firstvar = 0 - for field in wire_fields: - if not field.type.fixed_size(): - if not firstvar: - firstvar = 1 - go(' n := %d', fixedsize) - go(' n += pad(%s * %d)', go_accessor_expr(field.type.expr, '', True), field.type.size) - if not firstvar: - go(' put16(b[2:], %d)', fixedlength) - else: - go(' put16(b[2:], uint16(n / 4))') - go(' b[0] = %s', self.opcode) - go_complex_writer_help(wire_fields) - if not void: - if firstvar: - go(' cookie := c.sendRequest(b)') - else: - go(' return c.sendRequest(b)') - else: - go(' c.sendRequest(b)') - - # send extra data - for field in param_fields: - if not field.type.fixed_size(): - if field.type.is_list: - fieldname = field.c_field_name - lenstr = go_accessor_expr(field.type.expr, '', True) - if t(field.field_type) == 'byte': - if fieldname == 'Name': - go(' c.sendString(%s)', fieldname) - else: - go(' c.sendBytes(%s[0:%s])', fieldname, lenstr) - elif t(field.field_type) == 'uint32': - go(' c.sendUInt32List(%s[0:%s])', fieldname, lenstr) - else: - go(' c.send%sList(%s, %s)', t(field.field_type), fieldname, lenstr) - - if not void and firstvar: - go(' return cookie') - go('}') - go('') - - if not void: - args = go_complex_writer_arguments_names(param_fields) - go('func (c *Conn) %s(', func_name) - go_complex_writer_arguments(param_fields, '(*%s, os.Error) {' % self.c_reply_type) - go(' return c.%sReply(c.%sRequest(%s))', func_name, func_name, args) - go('}') - go('') - -# -# Struct definitions, readers and writers -# - -def go_struct(self, name): - go_type_setup(self, name, ()) - if symbols and t(name) not in symbols: - go('// excluding struct %s\n', t(name)) - return - - if self.c_type == 'SetupRequest': return - if self.c_type == 'SetupFailed': return - if self.c_type == 'SetupAuthenticate': return - - go_complex(self) - go_complex_reader(self) - - if self.c_type == 'Format': return - if self.c_type == 'VisualInfo': return - if self.c_type == 'DepthInfo': return - if self.c_type == 'SetupInfo': return - if self.c_type == 'ScreenInfo': return - - # omit variable length struct writers, they're never used - if not self.fixed_size(): - go('// omitting variable length send%s', self.c_type) - go('') - return - - go('func (c *Conn) send%sList(list []%s, count int) {', self.c_type, self.c_type) - go(' b0 := make([]byte, %d * count)', structsize(self.fields)) - go(' for k := 0; k < count; k++ {') - go(' b := b0[k * %d:]', structsize(self.fields)) - go_complex_writer_help(self.fields, 'list[k]') - go(' }') - go(' c.sendBytes(b0)') - go('}') - go('') - -def go_union(self, name): - pass - -# -# Request writers with reply structs and readers where needed -# - -def replyfields(self): - l = [] - for field in self.fields: - if field.type.is_pad or not field.wire: continue - if field.field_name == 'response_type': continue - if field.field_name == 'sequence': continue - if field.field_name == 'length': - if self.c_reply_name != 'GetImageReply' and self.c_reply_name != 'GetKeyboardMappingReply': - continue - l.append(field) - return l - -def go_reply(self, name): - ''' - Declares the function that returns the reply structure. - ''' - fields = replyfields(self.reply) - go_complex(self.reply, fields) - go('func (c *Conn) %s(cookie Cookie) (*%s, os.Error) {', self.c_reply_name, self.c_reply_type) - go(' b, error := c.waitForReply(cookie)') - go(' if error != nil { return nil, error }') - go(' v := new(%s)', self.c_reply_type) - go_complex_reader_help(self.reply, fields) - go(' return v, nil') - go('}') - go('') - -def go_request(self, name): - ''' - Exported function that handles request declarations. - ''' - go_type_setup(self, name, ('Request',)) - if symbols and n(name) not in symbols: - go('// excluding request %s\n', n(name)) - return - - if self.reply: - go_complex_writer(self, name, False) - go_type_setup(self.reply, name, ('Reply',)) - go_reply(self, name) - else: - go_complex_writer(self, name, True) - -# -# Event structs and readers -# - -def eventfields(self): - l = [] - for field in self.fields: - if field.type.is_pad or not field.wire: continue - if field.field_name == 'response_type': continue - if field.field_name == 'sequence': continue - l.append(field) - return l - -eventlist = [] - -def dumpeventlist(): - go('func parseEvent(buf []byte) (Event, os.Error) {') - go(' switch buf[0] {') - for event in eventlist: - go(' case %s: return get%sEvent(buf), nil', event, event) - go(' }') - go(' return nil, os.NewError("unknown event type")') - go('}') - -def go_event(self, name): - ''' - Exported function that handles event declarations. - ''' - go_type_setup(self, name, ('Event',)) - if symbols and t(name) not in symbols: - go('// excluding event %s\n', t(name)) - return - - eventlist.append(n(name)) - - go('const %s = %s', t(name), self.opcodes[name]) - go('') - fields = eventfields(self) - if self.name == name: - # Structure definition - go_complex(self, fields) - go('func get%s(b []byte) %s {', self.c_type, self.c_type) - go(' var v %s', self.c_type) - go_complex_reader_help(self, fields) - go(' return v') - go('}') - go('') - else: - # maybe skip this depending on how it interacts with type switching on interfaces - go('type %s %s', n(name + ('Event',)), n(self.name + ('Event',))) - go('') - go('func get%s(b []byte) %s {', self.c_type, self.c_type) - go(' return (%s)(get%s(b))', n(name + ('Event',)), n(self.name + ('Event',))) - go('}') - go('') - -# -# Map simple types to primitive types -# - -def go_simple(self, name): - ''' - Exported function that handles cardinal type declarations. - These are types which are typedef'd to one of the CARDx's, char, float, etc. - We stick them into the mangletab. Lop off xcb prefix. - ''' - go_type_setup(self, name, ()) - if self.name != name: - if _ns.is_ext: - name = name[2] - else: - name = name[1] - if name == "KEYSYM": - mangletab[name] = "Keysym" - elif name == "TIMESTAMP": - mangletab[name] = "Timestamp" - elif self.size == 4: - mangletab[name] = "Id" - else: - mangletab[name] = t(self.name) - -# -# Dump enums as consts, calculate implicit values instead -# of using iota. -# - -def go_enum(self, name): - if symbols and t(name) not in symbols: - go('// excluding enum %s\n', t(name)) - return - go('const (') - iota = 0 - for (enam, eval) in self.values: - if str(eval) == '': - iota = iota + 1 - eval = iota - else: - iota = int(eval) - if name[1] == 'Atom': - s = name[1] + "".join([x.capitalize() for x in enam.split("_")]) - else: - s = n(name + (enam,)) - go(' %s = %s', s, eval) - go(')') - go('') - -errorlist = [] - -def dumperrorlist(): - go('var errorNames = map[byte]string{') - for error in errorlist: - go(' Bad%s: "%s",', error, error) - go('}') - go('') - -def go_error(self, name): - ''' - Exported function that handles error declarations. - ''' - errorlist.append(n(name)) - go('const Bad%s = %s', n(name), self.opcodes[name]) - go('') - -# -# Create the go file -# - -def go_open(self): - ''' - Exported function that handles module open. - Opens the files and writes out the auto-generated code. - ''' - global _ns - _ns = self.namespace - - go('// This file was generated automatically from %s.', _ns.file) - go('') - go('package xgb') - go('') - go('import "os"') - go('') - - if _ns.is_ext: - go('const %s_MAJOR_VERSION = %s', _ns.ext_name.upper(), _ns.major_version) - go('const %s_MINOR_VERSION = %s', _ns.ext_name.upper(), _ns.minor_version) - go('') - -def go_close(self): - ''' - Exported function that handles module close. - ''' - global outfile - if len(eventlist) > 0: - dumpeventlist() - if len(errorlist) > 0: - dumperrorlist() - if not outfile: - outfile = '%s.go' % _ns.header - gofile = open(outfile, 'w') - for line in golines: - gofile.write(line) - gofile.write('\n') - gofile.close() - -# Main routine starts here - -# Must create an "output" dictionary before any xcbgen imports. -output = {'open' : go_open, - 'close' : go_close, - 'simple' : go_simple, - 'enum' : go_enum, - 'struct' : go_struct, - 'union' : go_union, - 'request' : go_request, - 'event' : go_event, - 'error' : go_error - } - -# Boilerplate below this point - -# Check for the argument that specifies path to the xcbgen python package. -try: - opts, args = getopt.getopt(sys.argv[1:], 'p:s:o:') -except getopt.GetoptError, err: - print str(err) - print 'Usage: go_client.py [-p path] [-s symbol_list_file] [-o output.go] file.xml' - sys.exit(1) - -for (opt, arg) in opts: - if opt == '-p': - sys.path.append(arg) - if opt == '-s': - readsymbols(arg) - if opt == '-o': - outfile = arg - -# Import the module class -try: - from xcbgen.state import Module -except ImportError: - print 'Failed to load the xcbgen Python package!' - print 'Make sure that xcb/proto installed it on your Python path,' - print 'or pass the path with -p.' - print '' - raise - -module = Module(args[0], output) -module.register() -module.resolve() -module.generate() |