[Xcb] [PATCH libxcb 3/6] generator: expressions can generate pre-code
Christian Linhart
chris at demorecorder.com
Wed Sep 3 04:22:38 PDT 2014
This patch provides a mechanism for generating
preparatory code for expressions.
This is e.g. necessary when an expression needs computations
which cannot be done in a C-Expression, like for-loops.
This will be used for sumof expressions but may be useful
elsewhere.
---
src/c_client.py | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 115 insertions(+), 4 deletions(-)
diff --git a/src/c_client.py b/src/c_client.py
index 35c975f..193e050 100644
--- a/src/c_client.py
+++ b/src/c_client.py
@@ -54,14 +54,110 @@ def _c(fmt, *args):
def _hc(fmt, *args):
'''
Writes the given line to both the header and source files.
'''
_h(fmt, *args)
_c(fmt, *args)
+def _c_wr_stringlist( indent, strlist ):
+ '''
+ Writes the given list of strings to the source file.
+ Each line is prepended by the indent string
+ '''
+ for str in strlist:
+ _c("%s%s", indent, str)
+
+
+#For pre-code generated by expression generation
+#(for example, the for-loop of a sumof)
+#This has to account for recursiveness of the expression
+#generation, i.e., there may be pre-code for pre-code.
+#Therefore this is implemented as a stack of lists of lines.
+#
+class PreCode:
+ def __init__(self):
+ self.nestingLevel = 0
+ self.tempvars = []
+ self.codelines = []
+ self.redirect_code = None
+ self.redirect_tempvars = None
+ self.indent_str = ' '
+ self.indent_stack = []
+ self.tempvarNum = 0
+
+
+ #start and end of pre-code blocks
+ def start(self):
+ self.nestingLevel += 1
+
+ def end(self):
+ self.nestingLevel -= 1
+ if ( self.nestingLevel == 0 ):
+ #lowest pre-code level is finished -> output to source
+ if self.redirect_tempvars == None:
+ _c_wr_stringlist('', self.tempvars )
+ self.tempvars = []
+ else:
+ self.redirect_tempvars.extend( self.tempvars )
+ self.tempvars = []
+ if self.redirect_code == None:
+ _c_wr_stringlist('', self.codelines )
+ self.codelines = []
+ else:
+ self.redirect_code.extend( self.codelines )
+ self.codelines = []
+
+
+ def output_tempvars(self):
+ if self.redirect_code == None:
+ _c_wr_stringlist('', self.tempvars )
+ self.tempvars = []
+
+ #output to precode
+ def code( self, fmt, *args):
+ self.codelines.append( self.indent_str + fmt % args )
+
+ def tempvar( self, fmt, *args):
+ self.tempvars.append(' ' + ( fmt % args ) )
+
+ #get a unique name for a temporary variable
+ def get_tempvarname(self):
+ self.tempvarNum += 1
+ return "xcb_pre_tmp_%d" % self.tempvarNum
+
+ #indentation
+
+ def push_indent(self, indentstr):
+ self.indent_stack.append( self.indent_str )
+ self.indent_str = indentstr
+
+ def push_addindent(self, indent_add_str):
+ self.push_indent( self.indent_str + indent_add_str )
+
+ def indent(self):
+ self.push_addindent(' ')
+
+ def pop_indent(self):
+ self.indent_str = self.indent_stack.pop()
+
+ #redirection to lists
+ def redirect_start( self, redirectCode, redirectTempvars = None):
+ self.redirect_code = redirectCode
+ self.redirect_tempvars = redirectTempvars
+ if redirectTempvars != None:
+ self.tempvarNum = 0
+
+ def redirect_end(self):
+ self.redirect_code = None
+ self.redirect_tempvars = None
+
+#global PreCode handler
+_c_pre = PreCode()
+
+
# XXX See if this level thing is really necessary.
def _h_setlevel(idx):
'''
Changes the array that header lines are written to.
Supports writing different sections of the header file.
'''
global _hlevel
@@ -1006,14 +1102,16 @@ def _c_serialize_helper_fields_variable_size(context, self, field,
def _c_serialize_helper_fields(context, self,
code_lines, temp_vars,
space, prefix, is_case_or_bitcase):
count = 0
need_padding = False
prev_field_was_variable = False
+ _c_pre.push_indent( space + ' ' )
+
for field in self.fields:
if not field.visible:
if not ((field.wire and not field.auto) or 'unserialize' == context):
continue
# switch/bitcase: fixed size fields must be considered explicitly
if field.type.fixed_size():
@@ -1092,14 +1190,16 @@ def _c_serialize_helper_fields(context, self,
if field.c_field_type == 'void' or field.type.is_switch
else field.c_field_type))
need_padding = True
if self.c_var_followed_by_fixed_fields:
need_padding = False
+ _c_pre.pop_indent()
+
return count
# _c_serialize_helper_fields()
def _c_serialize_helper(context, complex_type,
code_lines, temp_vars,
space='', prefix=[]):
# count tracks the number of fields to serialize
@@ -1191,14 +1291,16 @@ def _c_serialize(context, self):
_c("%s)" % param_str[-1].rstrip(','))
_c('{')
code_lines = []
temp_vars = []
prefix = []
+ _c_pre.redirect_start( code_lines, temp_vars )
+
if 'serialize' == context:
if not self.is_switch and not self.c_var_followed_by_fixed_fields:
_c(' %s *xcb_out = *_buffer;', self.c_type)
_c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
_c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
_c(' unsigned int xcb_align_to = 0;')
else:
@@ -1240,19 +1342,21 @@ def _c_serialize(context, self):
elif 'sizeof' == context:
param_names = [p[2] for p in params]
if self.is_switch:
# switch: call _unpack()
_c(' %s _aux;', self.c_type)
_c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
_c('}')
+ _c_pre.redirect_end()
return
elif self.c_var_followed_by_fixed_fields:
# special case: call _unserialize()
_c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
_c('}')
+ _c_pre.redirect_end()
return
else:
_c(' char *xcb_tmp = (char *)_buffer;')
prefix = [('_aux', '->', self)]
_c(' unsigned int xcb_padding_offset = 0;')
count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
@@ -1279,14 +1383,16 @@ def _c_serialize(context, self):
_c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
_c(' unsigned int xcb_buffer_len = 0;')
_c(' unsigned int xcb_block_len = 0;')
_c(' unsigned int xcb_pad = 0;')
_c(' unsigned int xcb_align_to = 0;')
+ _c_pre.redirect_end()
+
_c('')
for t in temp_vars:
_c(t)
_c('')
for l in code_lines:
_c(l)
@@ -1668,20 +1774,19 @@ def _c_accessors_list(self, field):
_hc('')
_hc('int')
if switch_obj is not None:
_hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
spacing = ' '*(len(field.c_length_name)+2)
_h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
_c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
- length = _c_accessor_get_expr(field.type.expr, fields)
else:
_h('%s (const %s *R /**< */);', field.c_length_name, c_type)
_c('%s (const %s *R /**< */)', field.c_length_name, c_type)
- length = _c_accessor_get_expr(field.type.expr, fields)
_c('{')
+ length = _c_accessor_get_expr(field.type.expr, fields)
_c(' return %s;', length)
_c('}')
if field.type.member.is_simple:
_hc('')
_hc('xcb_generic_iterator_t')
if switch_obj is not None:
@@ -1723,33 +1828,39 @@ def _c_accessors_list(self, field):
_c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
else:
_h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
_c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
_c('{')
_c(' %s i;', field.c_iterator_type)
+ _c_pre.start()
+ length_expr_str = _c_accessor_get_expr(field.type.expr, fields)
+
if switch_obj is not None:
+ _c_pre.end()
_c(' i.data = %s;', fields[field.c_field_name][0])
- _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
+ _c(' i.rem = %s;', length_expr_str)
elif field.prev_varsized_field == None:
+ _c_pre.end()
_c(' i.data = (%s *) (R + 1);', field.c_field_type)
else:
(prev_varsized_field, align_pad) = get_align_pad(field)
if align_pad is None:
align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
type_pad_type(field.c_field_type))
_c(' xcb_generic_iterator_t prev = %s;',
_c_iterator_get_end(prev_varsized_field, 'R'))
+ _c_pre.end()
_c(' i.data = (%s *) ((char *) prev.data + %s);',
field.c_field_type, align_pad)
if switch_obj is None:
- _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
+ _c(' i.rem = %s;', length_expr_str )
_c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
_c(' return i;')
_c('}')
def _c_accessors(self, name, base):
'''
Declares the accessor functions for the fields of a structure.
--
2.0.1
More information about the Xcb
mailing list