[Xcb] [PATCH libxcb 3/6 V2] generator: expressions can generate pre-code

Ran Benita ran234 at gmail.com
Sat Nov 1 03:42:18 PDT 2014


Another small request, see below.

On Wed, Sep 10, 2014 at 12:57:34PM +0200, Christian Linhart wrote:
> 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.
> 
> V2: adapt to changes in previous patches
> ---
>  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):

Would you mind changing to `get_tempvar_name`?

Ran

> +        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
> @@ -1011,14 +1107,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():
> @@ -1099,14 +1197,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
> @@ -1197,14 +1297,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:
> @@ -1242,20 +1344,22 @@ 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)]
>              if self.is_switch:
>                  _c('    unsigned int xcb_padding_offset = 0;')
>  
>      count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
> @@ -1282,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)
>  
> @@ -1671,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:
> @@ -1726,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 _______________________________________________ Xcb mailing list Xcb at lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/xcb
> 
> 
> _______________________________________________
> Xcb mailing list
> Xcb at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/xcb


More information about the Xcb mailing list