generator: expressions can generate pre-code
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. Note: Patch 2 of this series has been removed during the review process. V2: adapt to changes in previous patches V3: some style and formatting changes according to suggestions from Ran Benita. Signed-off-by: Christian Linhart <chris@DemoRecorder.com> Reviewed-by: Ran Benita <ran234@gmail.com> Message-ID: <54562769.3090405@DemoRecorder.com> Patch-Thread-Subject: [Xcb] [PATCHSET] ListInputDevices revision 2 Patch-Set: ListInputDevices Patch-Number: libxcb 3/9 Patch-Version: V3
This commit is contained in:
parent
265d38882c
commit
fda1fb4ed4
124
src/c_client.py
124
src/c_client.py
|
@ -58,6 +58,107 @@ def _hc(fmt, *args):
|
||||||
_h(fmt, *args)
|
_h(fmt, *args)
|
||||||
_c(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)
|
||||||
|
|
||||||
|
|
||||||
|
class PreCode(object):
|
||||||
|
'''
|
||||||
|
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.
|
||||||
|
|
||||||
|
If redirection is switched on, then all output is collected in
|
||||||
|
self.redirect_code and self.redirect_tempvars instead of
|
||||||
|
being sent to the output via _h und _c.
|
||||||
|
'''
|
||||||
|
def __init__(self):
|
||||||
|
self.nesting_level = 0
|
||||||
|
self.tempvars = []
|
||||||
|
self.codelines = []
|
||||||
|
self.redirect_code = None
|
||||||
|
self.redirect_tempvars = None
|
||||||
|
self.indent_str = ' '
|
||||||
|
self.indent_stack = []
|
||||||
|
self.tempvar_num = 0
|
||||||
|
|
||||||
|
|
||||||
|
# start and end of pre-code blocks
|
||||||
|
def start(self):
|
||||||
|
self.nesting_level += 1
|
||||||
|
|
||||||
|
def end(self):
|
||||||
|
self.nesting_level -= 1
|
||||||
|
if self.nesting_level == 0:
|
||||||
|
# lowest pre-code level is finished -> output to source
|
||||||
|
if self.redirect_tempvars is 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.tempvar_num += 1
|
||||||
|
return "xcb_pre_tmp_%d" % self.tempvar_num
|
||||||
|
|
||||||
|
# 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, redirect_code, redirect_tempvars=None):
|
||||||
|
self.redirect_code = redirect_code
|
||||||
|
self.redirect_tempvars = redirect_tempvars
|
||||||
|
if redirect_tempvars is not None:
|
||||||
|
self.tempvar_num = 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.
|
# XXX See if this level thing is really necessary.
|
||||||
def _h_setlevel(idx):
|
def _h_setlevel(idx):
|
||||||
'''
|
'''
|
||||||
|
@ -1024,6 +1125,8 @@ def _c_serialize_helper_fields(context, self,
|
||||||
need_padding = False
|
need_padding = False
|
||||||
prev_field_was_variable = False
|
prev_field_was_variable = False
|
||||||
|
|
||||||
|
_c_pre.push_indent(space + ' ')
|
||||||
|
|
||||||
for field in self.fields:
|
for field in self.fields:
|
||||||
if not field.visible:
|
if not field.visible:
|
||||||
if not ((field.wire and not field.auto) or 'unserialize' == context):
|
if not ((field.wire and not field.auto) or 'unserialize' == context):
|
||||||
|
@ -1112,6 +1215,8 @@ def _c_serialize_helper_fields(context, self,
|
||||||
if self.c_var_followed_by_fixed_fields:
|
if self.c_var_followed_by_fixed_fields:
|
||||||
need_padding = False
|
need_padding = False
|
||||||
|
|
||||||
|
_c_pre.pop_indent()
|
||||||
|
|
||||||
return count
|
return count
|
||||||
# _c_serialize_helper_fields()
|
# _c_serialize_helper_fields()
|
||||||
|
|
||||||
|
@ -1210,6 +1315,8 @@ def _c_serialize(context, self):
|
||||||
temp_vars = []
|
temp_vars = []
|
||||||
prefix = []
|
prefix = []
|
||||||
|
|
||||||
|
_c_pre.redirect_start(code_lines, temp_vars)
|
||||||
|
|
||||||
if 'serialize' == context:
|
if 'serialize' == context:
|
||||||
if not self.is_switch and not self.c_var_followed_by_fixed_fields:
|
if not self.is_switch and not self.c_var_followed_by_fixed_fields:
|
||||||
_c(' %s *xcb_out = *_buffer;', self.c_type)
|
_c(' %s *xcb_out = *_buffer;', self.c_type)
|
||||||
|
@ -1255,11 +1362,13 @@ def _c_serialize(context, self):
|
||||||
_c(' %s _aux;', self.c_type)
|
_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(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
|
||||||
_c('}')
|
_c('}')
|
||||||
|
_c_pre.redirect_end()
|
||||||
return
|
return
|
||||||
elif self.c_var_followed_by_fixed_fields:
|
elif self.c_var_followed_by_fixed_fields:
|
||||||
# special case: call _unserialize()
|
# special case: call _unserialize()
|
||||||
_c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
|
_c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
|
||||||
_c('}')
|
_c('}')
|
||||||
|
_c_pre.redirect_end()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
_c(' char *xcb_tmp = (char *)_buffer;')
|
_c(' char *xcb_tmp = (char *)_buffer;')
|
||||||
|
@ -1295,6 +1404,8 @@ def _c_serialize(context, self):
|
||||||
_c(' unsigned int xcb_pad = 0;')
|
_c(' unsigned int xcb_pad = 0;')
|
||||||
_c(' unsigned int xcb_align_to = 0;')
|
_c(' unsigned int xcb_align_to = 0;')
|
||||||
|
|
||||||
|
_c_pre.redirect_end()
|
||||||
|
|
||||||
_c('')
|
_c('')
|
||||||
for t in temp_vars:
|
for t in temp_vars:
|
||||||
_c(t)
|
_c(t)
|
||||||
|
@ -1684,12 +1795,11 @@ def _c_accessors_list(self, field):
|
||||||
spacing = ' '*(len(field.c_length_name)+2)
|
spacing = ' '*(len(field.c_length_name)+2)
|
||||||
_h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
|
_h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
|
||||||
_c('%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:
|
else:
|
||||||
_h('%s (const %s *R /**< */);', field.c_length_name, c_type)
|
_h('%s (const %s *R /**< */);', field.c_length_name, c_type)
|
||||||
_c('%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('{')
|
_c('{')
|
||||||
|
length = _c_accessor_get_expr(field.type.expr, fields)
|
||||||
_c(' return %s;', length)
|
_c(' return %s;', length)
|
||||||
_c('}')
|
_c('}')
|
||||||
|
|
||||||
|
@ -1739,10 +1849,15 @@ def _c_accessors_list(self, field):
|
||||||
_c('{')
|
_c('{')
|
||||||
_c(' %s i;', field.c_iterator_type)
|
_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:
|
if switch_obj is not None:
|
||||||
|
_c_pre.end()
|
||||||
_c(' i.data = %s;', fields[field.c_field_name][0])
|
_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:
|
elif field.prev_varsized_field == None:
|
||||||
|
_c_pre.end()
|
||||||
_c(' i.data = (%s *) (R + 1);', field.c_field_type)
|
_c(' i.data = (%s *) (R + 1);', field.c_field_type)
|
||||||
else:
|
else:
|
||||||
(prev_varsized_field, align_pad) = get_align_pad(field)
|
(prev_varsized_field, align_pad) = get_align_pad(field)
|
||||||
|
@ -1753,11 +1868,12 @@ def _c_accessors_list(self, field):
|
||||||
|
|
||||||
_c(' xcb_generic_iterator_t prev = %s;',
|
_c(' xcb_generic_iterator_t prev = %s;',
|
||||||
_c_iterator_get_end(prev_varsized_field, 'R'))
|
_c_iterator_get_end(prev_varsized_field, 'R'))
|
||||||
|
_c_pre.end()
|
||||||
_c(' i.data = (%s *) ((char *) prev.data + %s);',
|
_c(' i.data = (%s *) ((char *) prev.data + %s);',
|
||||||
field.c_field_type, align_pad)
|
field.c_field_type, align_pad)
|
||||||
|
|
||||||
if switch_obj is None:
|
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(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
|
||||||
_c(' return i;')
|
_c(' return i;')
|
||||||
_c('}')
|
_c('}')
|
||||||
|
|
Loading…
Reference in New Issue