diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2019-07-31 17:00:20 +0200 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2019-07-31 17:00:20 +0200 | 
| commit | 3759ce55ba79b8d3b9d8ed247a252273ee7dade3 (patch) | |
| tree | d69692a274dd1c7d0672e6bb7155a0fc106f9d49 /backend/scripts | |
| parent | c8bd2513ecba169cff44c09c8058c36987357b18 (diff) | |
| parent | 1687222e1b9e74c89cafbb5910e72d8ec7bfd40f (diff) | |
Update upstream source from tag 'upstream/1.0.28'
Update to upstream version '1.0.28'
with Debian dir ec5bb298266630fc3801ff6dc0c258f6df7ba979
Diffstat (limited to 'backend/scripts')
| -rwxr-xr-x | backend/scripts/pixma_gen_options.py | 389 | 
1 files changed, 389 insertions, 0 deletions
| diff --git a/backend/scripts/pixma_gen_options.py b/backend/scripts/pixma_gen_options.py new file mode 100755 index 0000000..c4c75e0 --- /dev/null +++ b/backend/scripts/pixma_gen_options.py @@ -0,0 +1,389 @@ +#!/usr/bin/env python + +import sys,os,re + +class Error(Exception): +    pass + + +class ParseError(Error): +    def __init__(self, errline): +        Error.__init__(self, errline) + + +class Struct: +    pass + + +def createCNameMap(): +    t = '' +    for i in range(256): +        if ((ord('A') <= i) and (i <= ord('Z'))) or \ +               ((ord('a') <= i) and (i <= ord('z'))) or \ +               ((ord('0') <= i) and (i <= ord('9'))): +            t += chr(i) +        else: +            t += '_' +    return t + + +def seekBegin(f): +    while True: +        line = f.readline() +        if not line: +            return False +        if line.startswith('BEGIN SANE_Option_Descriptor'): +            return True + + +def parseVerbatim(o, line): +    words = line.split(None, 1) +    if (len(words) < 2) or (words[1][0] != '@'): +        return False +    o[words[0]] = words[1] +    return True + + +def parseLine_type(o, line): +    words = line.split(None, 2) +    otype = words[1] +    o['type'] = 'SANE_TYPE_' + otype.upper() +    if otype == 'group': +        g.ngroups += 1 +        oname = '_group_%d' % g.ngroups +        o['size'] = 0 +    else: +        temp = words[2] +        idx = temp.find('[') +        if idx == -1: +            oname = temp +            o['size'] = 1 +        else: +            oname = temp[0:idx] +            o['size'] = int(temp[idx+1:-1]) +    o['name'] = oname + + +def parseLine_title(o, line): +    o['title'] = line.split(None, 1)[1] + + +def parseLine_desc(o, line): +    o['desc'] = line.split(None, 1)[1] + + +def parseLine_unit(o, line): +    o['unit'] = 'SANE_UNIT_' + line.split(None, 1)[1].upper() + + +def parseLine_default(o, line): +    o['default'] = line.split(None, 1)[1] + + +def parseLine_cap(o, line): +    words = line.split() +    o['cap'] = ['SANE_CAP_' + s.upper() for s in words[1:]] + + +def parseLine_constraint(o, line): +    c = line.split(None,1)[1] +    if c[0] == '{': +        o['constraint'] = c[1:-1].split('|') +    elif c[0] == '(': +        o['constraint'] = tuple(c[1:-1].split(',')) +    else: +        sys.stderr.write('Ignored: %s\n' % line) + + +def parseLine_info(o, line): +    words = line.split() +    o['info'] = ['SANE_INFO_' + s.upper() for s in words[1:]] + +def parseLine_rem(o, line): +    pass + +def normalize(o): +    if 'cname' not in o: +        cname = o['name'].translate(cnameMap) +        o['cname'] = cname +    else: +        cname = o['cname'] +    o['cname_opt'] = 'opt_' + cname +    o['cname_con'] = 'constraint_' + cname +    if 'title' not in o: +        o['title'] = 'NO TITLE' +    if 'desc' not in o: +        o['desc'] = '@sod->title' % o +    if 'unit' not in o: +        o['unit'] = 'SANE_UNIT_NONE' +    if 'constraint_type' not in o: +        if 'constraint' not in o: +            ct = 'SANE_CONSTRAINT_NONE' +        elif isinstance(o['constraint'], list): +            if o['type'] == 'SANE_TYPE_STRING': +                ct = 'SANE_CONSTRAINT_STRING_LIST' +            else: +                ct = 'SANE_CONSTRAINT_WORD_LIST' +        elif isinstance(o['constraint'], tuple): +            ct = 'SANE_CONSTRAINT_RANGE' +        elif isinstance(o['constraint'], str): +            oc = o['constraint'] +            if oc.startswith('@range'): +                ct = 'SANE_CONSTRAINT_RANGE' +            elif oc.startswith('@word_list'): +                ct = 'SANE_CONSTRAINT_WORD_LIST' +            elif oc.startswith('@string_list'): +                ct = 'SANE_CONSTRAINT_STRING_LIST' +        o['constraint_type'] = ct +    return o + + +def parseFile(f): +    if not seekBegin(f): +        return None +    options = [ { +        'name' : '', +        'cname' : 'opt_num_opts', +        'title' : '@SANE_TITLE_NUM_OPTIONS', +        'desc' : '@SANE_DESC_NUM_OPTIONS', +        'type' : 'SANE_TYPE_INT', +        'unit' : 'SANE_UNIT_NONE', +        'size' : 1, +        'cap' : ['SANE_CAP_SOFT_DETECT'], +        'constraint_type' : 'SANE_CONSTRAINT_NONE', +        'default' : '@w = ' + opt_prefix + 'last' +        } ] +    o = {} +    while True: +        line = f.readline() +        if not line: +            break +        line = line.strip() +        if not line: +            continue +        token = line.split(None, 1)[0].lower() +        if token == 'end': +            break +        if token == 'type': +            if 'name' in o: +                options.append(o) +            o = {} +        funcName = 'parseLine_' + token +        if funcName in globals(): +            if not parseVerbatim(o, line): +                func = globals()[funcName] +                func(o, line) +        else: +            sys.stderr.write('Skip: %s\n' % line) +    if 'name' in o: +        options.append(o) +    return [normalize(o) for o in options] + + +def genHeader(options): +    print """ +typedef union { +  SANE_Word w; +  SANE_Int  i; +  SANE_Bool b; +  SANE_Fixed f; +  SANE_String s; +  void *ptr; +} option_value_t; +""" +    print 'typedef enum {' +    for o in options: +        print '  %(cname_opt)s,' % o +    print '  ' + opt_prefix + 'last' +    print '} option_t;' +    print """ + +typedef struct { +  SANE_Option_Descriptor sod; +  option_value_t val,def; +  SANE_Word info; +} option_descriptor_t; + + +struct pixma_sane_t; +static int build_option_descriptors(struct pixma_sane_t *ss); +""" + + +def genMinMaxRange(n, t, r): +    if t == 'SANE_TYPE_FIXED': +        r = ['SANE_FIX(%s)' % x for x in r] +    print 'static const SANE_Range ' + n + ' = ' +    print '  { ' + r[0] + ',' + r[1] + ',' + r[2] + ' };' + + +def genList(n, t, l): +    if t == 'SANE_TYPE_INT': +        etype = 'SANE_Word' +        l = [str(len(l))] + l +    elif t == 'SANE_TYPE_FIXED': +        etype = 'SANE_Word' +        l = [str(len(l))] + ['SANE_FIX(%s)' % x for x in l] +    elif t == 'SANE_TYPE_STRING': +        etype = 'SANE_String_Const' +        l = ['SANE_I18N("%s")' % x for x in l] + ['NULL'] +    print 'static const %s %s[%d] = {' % (etype, n, len(l)) +    for x in l[0:-1]: +        print '\t' + x + ',' +    print '\t' + l[-1] + ' };' + + +def genConstraints(options): +    for o in options: +        if 'constraint' not in o: continue +        c = o['constraint'] +        oname = o['cname_con'] +        otype = o['type'] +        if isinstance(c, tuple): +            genMinMaxRange(oname, otype, c) +        elif isinstance(c, list): +            genList(oname, otype, c) +    print + +def buildCodeVerbatim(o): +    for f in ('name', 'title', 'desc', 'type', 'unit', 'size', 'cap', +              'constraint_type', 'constraint', 'default'): +        if (f not in o): continue +        temp = o[f] +        if (not isinstance(temp,str)) or \ +           (len(temp) < 1) or (temp[0] != '@'): +            continue +        o['code_' + f] = temp[1:] + +def ccode(o): +    buildCodeVerbatim(o) +    if 'code_name' not in o: +        o['code_name'] = '"' + o['name'] + '"' +    for f in ('title', 'desc'): +        cf = 'code_' + f +        if cf in o: continue +        o[cf] = 'SANE_I18N("' + o[f] + '")' + +    for f in ('type', 'unit', 'constraint_type'): +        cf = 'code_' + f +        if cf in o: continue +        o[cf] = o[f] + +    if 'code_size' not in o: +        otype = o['type'] +        osize = o['size'] +        if otype == 'SANE_TYPE_STRING': +            code = str(osize + 1) +        elif otype == 'SANE_TYPE_INT' or otype == 'SANE_TYPE_FIXED': +            code = str(osize) + ' * sizeof(SANE_Word)' +        elif otype == 'SANE_TYPE_BUTTON': +            code = '0' +        else: +            code = 'sizeof(SANE_Word)' +        o['code_size'] = code + +    if ('code_cap' not in o) and ('cap' in o): +        o['code_cap'] = reduce(lambda a,b: a+'|'+b, o['cap']) +    else: +        o['code_cap'] = '0' + +    if ('code_info' not in o) and ('info' in o): +        o['code_info'] = reduce(lambda a,b: a+'|'+b, o['info']) +    else: +        o['code_info'] = '0' + +    if ('code_default' not in o) and ('default' in o): +        odefault = o['default'] +        otype = o['type'] +        if odefault == '_MIN': +            rhs = 'w = sod->constraint.range->min' +        elif odefault == '_MAX': +            rhs = 'w = sod->constraint.range->max' +        elif otype in ('SANE_TYPE_INT', 'SANE_TYPE_BOOL'): +            rhs = 'w = %(default)s' +        elif otype == 'SANE_TYPE_FIXED': +            rhs = 'w = SANE_FIX(%(default)s)' +        elif otype == 'SANE_TYPE_STRING': +            rhs = 's = SANE_I18N("%(default)s")' +        o['code_default'] = rhs % o +    if 'code_default' in o: +        code = '  opt->def.%(code_default)s;\n' +        if o['constraint_type'] != 'SANE_CONSTRAINT_STRING_LIST': +            code += '  opt->val.%(code_default)s;\n' +        else: +            code += '  opt->val.w = find_string_in_list' \ +                    '(opt->def.s, sod->constraint.string_list);\n' +        o['full_code_default'] = code % o +    else: +        o['full_code_default'] = '' + +    if ('code_constraint' not in o) and ('constraint' in o): +        ct = o['constraint_type'] +        idx = len('SANE_CONSTRAINT_') +        ctype = ct[idx:].lower() +        if ctype == 'range': +            rhs = '&%(cname_con)s' % o +        else: +            rhs = '%(cname_con)s' % o +        o['code_constraint'] = ctype + ' = ' + rhs +    if 'code_constraint' in o: +        code = '  sod->constraint.%(code_constraint)s;\n' +        o['full_code_constraint'] = code % o +    else: +        o['full_code_constraint'] = '' + +    return o + +def genBuildOptions(options): +  print """ +static +int find_string_in_list(SANE_String_Const str, const SANE_String_Const *list) +{ +  int i; +  for (i = 0; list[i] && strcmp(str, list[i]) != 0; i++) {} +  return i; +} + +static +int build_option_descriptors(struct pixma_sane_t *ss) +{ +  SANE_Option_Descriptor *sod; +  option_descriptor_t *opt; + +  memset(OPT_IN_CTX, 0, sizeof(OPT_IN_CTX));""" + +  for o in options: +      o = ccode(o) +      otype = o['type'] +      code = '\n  opt = &(OPT_IN_CTX[%(cname_opt)s]);\n' \ +             '  sod = &opt->sod;\n' \ +             '  sod->type = %(code_type)s;\n' \ +             '  sod->title = %(code_title)s;\n' \ +             '  sod->desc = %(code_desc)s;\n' +      if otype != 'SANE_TYPE_GROUP': +          code += '  sod->name = %(code_name)s;\n' \ +                  '  sod->unit = %(code_unit)s;\n' \ +                  '  sod->size = %(code_size)s;\n' \ +                  '  sod->cap  = %(code_cap)s;\n' \ +                  '  sod->constraint_type = %(code_constraint_type)s;\n' \ +                  '%(full_code_constraint)s' \ +                  '  OPT_IN_CTX[%(cname_opt)s].info = %(code_info)s;\n' \ +                  '%(full_code_default)s' +      sys.stdout.write(code % o) +  print +  print '  return 0;\n' +  print '}' +  print + +g = Struct() +g.ngroups = 0 +opt_prefix = 'opt_' +con_prefix = 'constraint_' +cnameMap = createCNameMap() +options = parseFile(sys.stdin) +print "/* Automatically generated from pixma_sane.c */" +if (len(sys.argv) == 2) and (sys.argv[1] == 'h'): +    genHeader(options) +else: +    genConstraints(options) +    genBuildOptions(options) | 
