source: proto/charsetcompiler/charset_compiler.py @ 3547

Last change on this file since 3547 was 3413, checked in by cameron, 6 years ago

Autodetect encoding type

File size: 26.6 KB
Line 
1#
2#  Character Class Compiler
3#
4#  Version 0.9 - June 24, 2013
5#
6#  Copyright (c) 2007-13, Robert D. Cameron
7#  Licensed to the public under Open Software License 3.0
8#
9#  Initial UTF-16 and UTF-32 support added by Dale Denis, June 2013.
10#
11#  TO DO
12#    - add autosensing of 16/32 bit characters from input files
13#    - optimization of range logic for 16-bit char sets.
14#
15#--------------------------------------------------------------------------
16#
17#  Data types
18#  1. Character Set Definitions
19#  2. Boolean Expressions
20#  3. Code Generator Objects
21#
22import sys, optparse
23import re, binascii, string
24import EBCDIC
25
26import charset_def
27CharDef = charset_def.CharDef
28CharSetDef = charset_def.CharSetDef
29
30import charsets
31DefinitionSet = charsets.DefinitionSet
32
33import charset_input_parser
34
35import UTF_encoding
36Encoding_Type = UTF_encoding.UTF_Encoding_Type
37
38#
39# Symbolic Representations of Boolean Expressions
40#
41
42class BoolExpr:
43   """The BoolExpr class and its subclasses provide a symbolic
44      representation of Boolean expressions.
45   """
46   pass
47
48class Var(BoolExpr):
49    def __init__(self, varname):
50        self.varname = varname
51    def show(self): return 'Var("' + self.varname + '")'
52    def __str__(self): return 'Var("' + self.varname + '")'
53
54class TrueLiteral(BoolExpr):
55    def __init__(self):
56        self.value = True
57    def show(self): return 'T'
58    def __str__(self): return 'T'
59
60class FalseLiteral(BoolExpr):
61    def __init__(self):
62        self.value = False
63    def show(self): return 'F'
64
65class Not(BoolExpr):
66    def __init__(self, expr):
67        self.operand = expr
68    def show(self): return 'Not(%s)' % (self.operand.show())
69    def __str__(self): return 'Not(%s)' % (self.operand.show())
70
71class And(BoolExpr):
72    def __init__(self, expr1, expr2):
73        self.operand1 = expr1
74        self.operand2 = expr2
75    def show(self): return 'And(%s, %s)' % (self.operand1.show(), self.operand2.show())
76    def __str__(self): return 'And(%s, %s)' % (self.operand1.show(), self.operand2.show())
77
78class Or(BoolExpr):
79    def __init__(self, expr1, expr2):
80        self.operand1 = expr1
81        self.operand2 = expr2
82    def show(self): return 'Or(%s, %s)' % (self.operand1.show(), self.operand2.show())
83
84class Xor(BoolExpr):
85    def __init__(self, expr1, expr2):
86        self.operand1 = expr1
87        self.operand2 = expr2
88    def show(self): return 'Xor(%s, %s)' % (self.operand1.show(), self.operand2.show())
89
90class Sel(BoolExpr):
91    def __init__(self, expr1, expr2, expr3):
92        self.sel = expr1
93        self.true_branch = expr2
94        self.false_branch = expr3
95    def show(self): return 'Sel(%s, %s, %s)' % (self.sel.show(), self.true_branch.show(), self.false_branch.show())
96    def __str__(self): return 'Sel(%s, %s, %s)' % (self.sel.show(), self.true_branch.show(), self.false_branch.show())
97
98
99#
100# Optimizing Constructors for Boolean Expressions
101# - Maintaining Assembler Instruction Form:
102#   - All boolean algebraic rules involving true/false applied.
103#   - Negations restricted:
104#       - no negations within or (DeMorgan's to nand)
105#       - at most one negation within and
106#
107
108def make_not(expr):
109    if isinstance(expr, TrueLiteral):
110        return FalseLiteral()
111    elif isinstance(expr, FalseLiteral):
112        return TrueLiteral()
113    elif isinstance(expr, Not):
114        return expr.operand
115    else: return Not(expr)
116
117def make_and(expr1, expr2):
118    if isinstance(expr1, TrueLiteral):
119        return expr2
120    elif isinstance(expr2, TrueLiteral):
121        return expr1
122    elif isinstance(expr1, FalseLiteral):
123        return FalseLiteral()
124    elif isinstance(expr2, FalseLiteral):
125        return FalseLiteral()
126    elif equal_exprs(expr1, expr2): return expr1
127    elif isinstance(expr1, Not):
128        if isinstance(expr2, Not):
129            return make_not(make_or(expr1.operand, expr2.operand))
130        elif equal_exprs(expr1.operand, expr2): return FalseLiteral()
131        else: return And(expr1, expr2)
132    elif isinstance(expr2, Not):
133        if equal_exprs(expr1, expr2.operand): return FalseLiteral()
134        else: return And(expr1, expr2)
135    else: return And(expr1, expr2)
136
137def make_or(expr1, expr2):
138    if isinstance(expr1, FalseLiteral):
139        return expr2
140    elif isinstance(expr2, FalseLiteral):
141        return expr1
142    elif isinstance(expr1, TrueLiteral):
143        return TrueLiteral()
144    elif isinstance(expr2, TrueLiteral):
145        return TrueLiteral()
146    elif isinstance(expr1, Not):
147        return make_not(make_and(expr1.operand, make_not(expr2)))
148    elif isinstance(expr2, Not):
149        return make_not(make_and(make_not(expr1), expr2.operand))
150    elif equal_exprs(expr1, expr2): return expr1
151    elif isinstance(expr1, And) and isinstance(expr2, And):
152        # These optimizations factor out common components that
153        # can occur when sets are formed by union (e.g., union of
154        # [a-z] and [A-Z].
155        if equal_exprs(expr1.operand1, expr2.operand1):
156            return make_and(expr1.operand1, make_or(expr1.operand2, expr2.operand2))
157        elif equal_exprs(expr1.operand2, expr2.operand2):
158            return make_and(expr1.operand2, make_or(expr1.operand1, expr2.operand1))
159        elif equal_exprs(expr1.operand1, expr2.operand2):
160            return make_and(expr1.operand1, make_or(expr1.operand2, expr2.operand1))
161        elif equal_exprs(expr1.operand2, expr2.operand1):
162            return make_and(expr1.operand2, make_or(expr1.operand1, expr2.operand2))
163        else: return Or(expr1, expr2)
164    else: return Or(expr1, expr2)
165
166def make_sel(if_expr, T_expr, F_expr):
167    if isinstance(if_expr, TrueLiteral):
168        return T_expr
169    elif isinstance(if_expr, FalseLiteral):
170        return F_expr
171    elif isinstance(T_expr, TrueLiteral):
172        # if x then T else y = x or y
173        return make_or(if_expr, F_expr) 
174    elif isinstance(T_expr, FalseLiteral):
175        # if x then F else y = not(x) and y
176        return make_and(make_not(if_expr), F_expr) 
177    elif isinstance(F_expr, FalseLiteral):
178        # if x then y else F = x and y
179        return make_and(if_expr, T_expr) 
180    elif isinstance(F_expr, TrueLiteral):
181        # if x then y else T = not(x) or y
182        return make_or(make_not(if_expr), T_expr)
183    elif equal_exprs(T_expr, F_expr):
184        return T_expr
185    else: return Sel(if_expr, T_expr, F_expr)
186
187
188def make_xor(expr1, expr2):
189    if isinstance(expr1, FalseLiteral):
190        return expr2
191    elif isinstance(expr2, FalseLiteral):
192        return expr1
193    elif isinstance(expr1, TrueLiteral):
194        return make_not(expr2)
195    elif isinstance(expr2, TrueLiteral):
196        return make_not(expr1)
197    elif isinstance(expr1, Not) and isinstance(expr2, Not):
198        return make_xor(expr1.operand, expr2.operand)
199    else: return Xor(expr1, expr2)
200
201# Return True if e1 and e2 can be proven equivalent according
202# to some rules, False otherwise.   Note that False may
203# be returned in some cases when the exprs are equivalent.
204def equal_exprs(e1, e2):
205    if isinstance(e1, FalseLiteral): return isinstance(e2, FalseLiteral)
206    elif isinstance(e1, TrueLiteral): return isinstance(e2, TrueLiteral)
207    elif isinstance(e1, Var) and isinstance(e2, Var):
208        return e1.varname == e2.varname
209    elif isinstance(e1, Not) and isinstance(e2, Not):
210        return equal_exprs(e1.operand, e2.operand)
211    elif isinstance(e1, And) and isinstance(e2, And):
212        if equal_exprs(e1.operand1, e2.operand1):
213            return equal_exprs(e1.operand2, e2.operand2)
214        elif equal_exprs(e1.operand1, e2.operand2):
215            return equal_exprs(e1.operand2, e2.operand1)
216        else: return False
217    elif isinstance(e1, Or) and isinstance(e2, Or):
218        if equal_exprs(e1.operand1, e2.operand1):
219            return equal_exprs(e1.operand2, e2.operand2)
220        elif equal_exprs(e1.operand1, e2.operand2):
221            return equal_exprs(e1.operand2, e2.operand1)
222        else: return False
223    elif isinstance(e1, Xor) and isinstance(e2, Xor):
224        if equal_exprs(e1.operand1, e2.operand1):
225            return equal_exprs(e1.operand2, e2.operand2)
226        elif equal_exprs(e1.operand1, e2.operand2):
227            return equal_exprs(e1.operand2, e2.operand1)
228        else: return False
229    elif isinstance(e1, Sel) and isinstance(e2, Sel):
230        if equal_exprs(e1.sel, e2.sel):
231             if equal_exprs(e1.true_branch, e2.true_branch):
232                 return equal_exprs(e1.false_branch, e2.false_branch)
233             else: return False
234        else: return False
235
236#
237#
238#  Boolean Expressions for Character Class Definitions
239#
240
241def bit_var(n):
242
243#    return 'bit[%i]' % n
244
245    global options
246    global Encoding
247
248    if len(UTF_encoding.Encoding.basis_pattern) == 1:
249        return UTF_encoding.Encoding.basis_pattern[0] % n
250   
251    if UTF_encoding.Encoding.name == UTF_encoding.UTF16.name:
252        if options.little_endian == True:
253            if n >= 8:
254                return UTF_encoding.Encoding.basis_pattern[0] % (n - 8)
255            else:
256                return UTF_encoding.Encoding.basis_pattern[1] % n
257        else:
258            if n <= 7:
259                return UTF_encoding.Encoding.basis_pattern[0] % n
260            else:
261                return UTF_encoding.Encoding.basis_pattern[1] % (n - 8)
262
263    if UTF_encoding.Encoding.name == UTF_encoding.UTF32.name:
264        if options.little_endian == True:
265            if n >= 21:
266                return "unused_bit%i" % (n - 21)
267            elif n < 21 and n >= 16:
268                return UTF_encoding.Encoding.basis_pattern[0] % (n - 16)
269            elif n < 16 and n >= 8:
270                return UTF_encoding.Encoding.basis_pattern[1] % (n - 8)
271            elif n < 8:
272                return UTF_encoding.Encoding.basis_pattern[2] % n
273        else:
274            if n <= 10:
275                return "unused_bit%i" % n
276            elif n > 10 and n <= 15:
277                return UTF_encoding.Encoding.basis_pattern[0] % (n - 8)
278            elif n > 15 and n <= 23:
279                return UTF_encoding.Encoding.basis_pattern[1] % (n - 16)
280            elif n > 23:
281                return UTF_encoding.Encoding.basis_pattern[2] % (n - 24)
282
283
284def make_bitv(n):
285       
286    global options
287
288    if options.little_endian == True:
289        return Var(bit_var(n))
290    else:
291        return Var(bit_var((UTF_encoding.Encoding.bits - 1) -n)) 
292       
293def make_bit_test(pattern, bit_count):
294    if bit_count == 0: return TrueLiteral()
295    bit_terms = []
296    test_bit = 2**(bit_count - 1)
297    for i in range(0, bit_count):
298        if (pattern & test_bit) == 0:
299            bit_terms.append(make_not(make_bitv((UTF_encoding.Encoding.bits - 1)-i)))   
300        else: bit_terms.append(make_bitv((UTF_encoding.Encoding.bits - 1)-i))           
301        test_bit >>= 1
302    while len(bit_terms) > 1:
303        new_terms = []
304        for i in range(0, len(bit_terms)/ 2):
305            new_terms.append(make_and(bit_terms[2*i], bit_terms[2*i+1]))
306        if len(bit_terms) % 2 == 1:
307            new_terms.append(bit_terms[-1])
308        bit_terms = new_terms
309    return bit_terms[0]
310
311def bit_pattern_expr(pattern, selected_bits):
312    if selected_bits == 0: return TrueLiteral()
313    bit_terms = []
314    bit_no = 0
315    while selected_bits:
316      test_bit = 1 << bit_no
317      if selected_bits & test_bit:
318        if (pattern & test_bit) == 0:
319            bit_terms = [make_not(make_bitv(bit_no))] + bit_terms
320        else: bit_terms = [make_bitv(bit_no)] + bit_terms
321      else: bit_terms = [TrueLiteral()] + bit_terms
322      # Appending TrueLiteral() for nonselected bits is intended
323      # to keep consistent grouping of variables in the next loop.
324      selected_bits &= ~test_bit
325      bit_no += 1
326     
327    while len(bit_terms) > 1:
328        new_terms = []
329        for i in range(0, len(bit_terms)/ 2):
330            new_terms.append(make_and(bit_terms[2*i], bit_terms[2*i+1]))
331        if len(bit_terms) % 2 == 1:
332            new_terms.append(bit_terms[-1])
333        bit_terms = new_terms
334   
335    return bit_terms[0]
336   
337
338def char_test_expr(ch):
339    #return make_bit_test(ord(ch), 8)
340    return bit_pattern_expr(ord(ch), UTF_encoding.Encoding.mask) 
341
342def GE_Range(N, n):
343
344    if N == 0: return TrueLiteral()
345    elif N % 2 == 0 and (n >> (N - 2)) == 0:
346        return make_or(make_or(make_bitv(N-1), make_bitv(N-2)),
347                        GE_Range(N - 2, n))
348    elif N % 2 == 0 and (n >> (N - 2)) == 3:   # >= 11xxxx
349        return make_and(make_and(make_bitv(N-1), make_bitv(N-2)),
350                        GE_Range(N - 2, n - (3 << (N-2))))
351    elif N >= 1:
352        hi_bit = n & (1 << (N-1))
353        lo_bits = n - hi_bit
354        lo_range = GE_Range(N-1, lo_bits)
355        if hi_bit == 0:
356            # If the hi_bit of n is not set, then whenever the corresponding bit
357            # is set in the target, the target will certainly be >=.  Otherwise,
358            # the value of GE_range(N-1, lo_bits) is required.
359            return make_or(make_bitv(N-1), lo_range)
360        else: 
361            # If the hi_bit of n is set, then the corresponding bit must be set
362            # in the target for >= and GE_range(N-1, lo_bits) must also be true.
363            return make_and(make_bitv(N-1), lo_range)
364
365def LE_Range(N, n):
366    # If an N-bit pattern is all ones, then it is always
367    # true that any n-bit value is LE this pattern.
368    # Handling this as a special case avoids an overflow
369    # issue with n+1 requiring more than N bits.
370    if n+1 == 2 ** N:
371        return TrueLiteral()
372    else:
373        return make_not(GE_Range(N, n+1))
374
375BadRange = Exception()
376
377def Make_Range(n1, n2):  # require n2 >= n1
378    diff_bits = n1 ^ n2
379    diff_count = 0
380    while diff_bits > 0:
381        diff_count += 1
382        diff_bits >>= 1
383    if n2 < n1 or diff_count > UTF_encoding.Encoding.bits: raise BadRange() 
384    mask = 2**(diff_count) - 1
385    #common = make_bit_test(n1 >> diff_count, 8 - diff_count)
386    common = bit_pattern_expr(n1 & ~mask, UTF_encoding.Encoding.mask^mask)   
387    if diff_count == 0: return common
388    mask = 2**(diff_count-1) - 1
389    lo_test = GE_Range(diff_count-1, n1 & mask)
390    hi_test = LE_Range(diff_count-1, n2 & mask)
391
392    return make_and(common, make_sel(make_bitv(diff_count-1), hi_test, lo_test))
393
394BadCharSetItem = Exception()
395
396def char_or_range_expr(charset_item):
397    if len(charset_item) == 1:
398        return char_test_expr(charset_item[0])
399    elif len(charset_item) == 3:
400        if charset_item[1] == '-' and ord(charset_item[0]) <= ord(charset_item[2]):
401             return Make_Range(ord(charset_item[0]), ord(charset_item[2]))
402    raise BadCharSetItem
403
404def charset_expr(chardef):
405    if chardef.items == []: return FalseLiteral()
406    e1 = char_or_range_expr(chardef.items[0])
407    for i in range(1, len(chardef.items)):   
408        e1 = make_or(e1, char_or_range_expr(chardef.items[i]))
409    if chardef.complemented: return make_not(e1)
410    else: return e1
411
412#
413#
414#  Code Generation
415#
416class CodeGenObject:
417    def __init__(self, predeclared, typedecl='BitBlock '):
418        self.gensym_template = options.gensym_pattern
419        self.gensym_counter = 0
420        self.generated_code = []
421        self.common_expression_map = {}
422        for sym in predeclared: self.common_expression_map[sym] = sym             
423        self.typedecl = typedecl
424    def add_assignment(self, varname, expr):
425        self.common_expression_map[expr] = varname
426        #self.generated_code.append('%s%s = %s;\n' % (self.typedecl, varname, expr))
427        self.generated_code.append('\t%s%s = %s\n' % (self.typedecl, varname, expr))
428    def expr_string_to_variable(self, expr_string):
429        if self.common_expression_map.has_key(expr_string):
430            return self.common_expression_map[expr_string]
431        else:
432            self.gensym_counter += 1                           
433            sym = self.gensym_template % self.gensym_counter 
434            self.add_assignment(sym, expr_string) 
435            return sym
436
437    def showcode(self):
438        s = ''
439        for stmt in self.generated_code: s += stmt
440        return s
441
442def expr2simd(genobj, expr):
443    """Translate a Boolean expression into three-address Altivec code
444       using code generator object genobj.
445    """
446    if isinstance(expr, TrueLiteral): return 'simd_const_1(1)'
447    elif isinstance(expr, FalseLiteral): return 'simd_const_1(0)'
448    elif isinstance(expr, Var): return expr.varname
449    elif isinstance(expr, Not):
450       e = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand))
451       return 'simd_andc(simd_const_1(1), %s)' % (e)
452    elif isinstance(expr, Or):
453       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
454       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
455       return 'simd_or(%s, %s)' % (e1, e2)
456    elif isinstance(expr, Xor):
457       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
458       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
459       return 'simd_xor(%s, %s)' % (e1, e2)
460    elif isinstance(expr, And):
461       if isinstance(expr.operand1, Not):
462           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1.operand))
463           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
464           return 'simd_andc(%s, %s)' % (e2, e1)
465       elif isinstance(expr.operand2, Not):
466           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
467           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2.operand))
468           return 'simd_andc(%s, %s)' % (e1, e2)
469       else:
470           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
471           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
472           return 'simd_and(%s, %s)' % (e1, e2)
473    elif isinstance(expr, Sel):
474       sel = genobj.expr_string_to_variable(expr2simd(genobj, expr.sel))
475       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.true_branch))
476       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.false_branch))
477       return 'simd_if(%s, %s, %s)' %(sel, e1, e2)
478
479def chardef2simd(genobj, chardef):
480    genobj.add_assignment(chardef.name, expr2simd(genobj, charset_expr(chardef)))
481
482def chardeflist2simd(chardeflist):
483    cgo = CodeGenObject([bit_var(i) for i in range(0, UTF_encoding.Encoding.bits)])
484    for d in chardeflist:
485        chardef2simd(cgo, d)
486    return cgo.showcode()
487
488def expr2py(genobj, expr):
489    """Translate a Boolean expression into three-address python code
490       using code generator object genobj.
491    """
492    if isinstance(expr, TrueLiteral): return '-1'
493    elif isinstance(expr, FalseLiteral): return '0'
494    elif isinstance(expr, Var): return expr.varname
495    elif isinstance(expr, Not):
496       e = genobj.expr_string_to_variable(expr2py(genobj, expr.operand))
497       return '(~%s)' % (e)
498    elif isinstance(expr, Or):
499       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
500       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
501       return '(%s | %s)' % (e1, e2)
502    elif isinstance(expr, Xor):
503       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
504       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
505       return '(%s ^ %s)' % (e1, e2)
506    elif isinstance(expr, And):
507       if isinstance(expr.operand1, Not):
508           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1.operand))
509           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
510           return '(%s &~ %s)' % (e2, e1)
511       elif isinstance(expr.operand2, Not):
512           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
513           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2.operand))
514           return '(%s &~ %s)' % (e1, e2)
515       else:
516           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
517           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
518           return '(%s & %s)' % (e1, e2)
519    elif isinstance(expr, Sel):
520       sel = genobj.expr_string_to_variable(expr2py(genobj, expr.sel))
521       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.true_branch))
522       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.false_branch))
523       return '((%s & %s)|(~(%s) & %s))' %(sel, e1, sel, e2)
524
525def chardef2py(genobj, chardef):
526    genobj.add_assignment(chardef.name, expr2py(genobj, charset_expr(chardef)))
527   
528def py_chardefmap(chardeflist):
529    defs = ["'%s' : %s" % (d.name,d.name) for d in chardeflist]
530    return  '{%s}' % string.join(defs, ',\n\t')
531
532def chardeflist2py(chardeflist):
533    cgo = CodeGenObject([bit_var(i) for i in range(0, UTF_encoding.Encoding.bits)],'') 
534    for d in chardeflist:
535        chardef2py(cgo, d) 
536    return cgo.showcode()# + "  return "+ py_chardefmap(chardeflist) + "\n"
537
538def main():   
539
540    global options
541    # Option definition
542    option_parser = optparse.OptionParser(usage='python %prog [options] <input file>', version='0.8')
543 
544    option_parser.add_option('-u', '--character_encoding',
545                             dest='character_encoding',
546                             type='string',
547                             default='Default',
548                             help='character encoding; default: UTF-8',
549                             ) 
550    option_parser.add_option('-b', '--basis_pattern', 
551                             dest='basis_pattern',
552                             type='string',
553                             default='basis_bits.bit_%i',
554                             help='pattern for basis bit streams; default: basis_bits.bit_%i',
555                             )
556    option_parser.add_option('-l', '--little_endian',
557                             dest='little_endian',
558                             action='store_true',
559                             default=False,
560                             help='sets bit numbering of the output to little-endian',
561                             )
562    option_parser.add_option('-g', '--gensym_pattern', 
563                             dest='gensym_pattern',
564                             type='string',
565                             default='temp%i',
566                             help='pattern for generated temporaries; default: temp%i',
567                             )
568    option_parser.add_option('-E', '--EBCDIC', 
569                             dest='use_EBCDIC',
570                             action='store_true', 
571                             default=False,
572                             help='generate definitions for EBCDIC input',
573                             )
574    option_parser.add_option('-p', '--pablo', 
575                             dest='Pablo_skeleton',
576                             action='store_true', 
577                             default=False,
578                             help='generate pablo skeleton',
579                             )
580    option_parser.add_option('-t', '--test', 
581                             dest='test_skeleton',
582                             action='store_true', 
583                             default=False,
584                             help='generate pablo test skeleton',
585                             )
586    options, args = option_parser.parse_args(sys.argv[1:])
587
588    # Set the encoding.
589       
590    #If the user has entered the encoding type as a command-line argument
591    #then the encoding type that is to be used is locked.
592    if options.character_encoding == UTF_encoding.UTF32.name:
593        UTF_encoding.Encoding = Encoding_Type(options.character_encoding, 
594        UTF_encoding.UTF32.bits, UTF_encoding.UTF32.mask, False, True)
595    elif options.character_encoding == UTF_encoding.UTF16.name:
596        UTF_encoding.Encoding = Encoding_Type(options.character_encoding, 
597        UTF_encoding.UTF16.bits, UTF_encoding.UTF16.mask, False, True)
598    elif options.character_encoding == UTF_encoding.UTF8.name: 
599        UTF_encoding.Encoding = Encoding_Type(options.character_encoding,
600        UTF_encoding.UTF8.bits, UTF_encoding.UTF8.mask, False, True)
601    elif options.character_encoding == 'Default': 
602        UTF_encoding.Encoding = Encoding_Type(UTF_encoding.UTF8.name, 
603        UTF_encoding.UTF8.bits, UTF_encoding.UTF8.mask, True, False)
604    else:
605        print "ERROR: Invalid encoding format."
606        return
607
608    # If we have a valid encoding format then set the basis pattern.
609    UTF_encoding.Encoding.basis_pattern = string.split(options.basis_pattern, ",")
610    if len(UTF_encoding.Encoding.basis_pattern) == 1:
611        # If we have the default basis pattern string then adjust it
612        # for UTF-16 or UTF-32.  If the encoding is UTF-8 then we will
613        # leave it as is.
614        if "basis_bits.bit_%i" in UTF_encoding.Encoding.basis_pattern[0]:
615            if UTF_encoding.UTF16.name in UTF_encoding.Encoding.name:
616                UTF_encoding.Encoding.basis_pattern[0] = "u16_bit%i"
617            elif UTF_encoding.UTF32.name in UTF_encoding.Encoding.name:
618                UTF_encoding.Encoding.basis_pattern[0] = "u32_bit%i"
619    elif len(UTF_encoding.Encoding.basis_pattern) == 2:
620        if UTF_encoding.UTF16.name not in UTF_encoding.Encoding.name:
621            print "ERROR: Invalid encoding for the basis pattern variables."
622            return
623    elif len(UTF_encoding.Encoding.basis_pattern) == 3:
624        if UTF_encoding.UTF32.name not in UTF_encoding.Encoding.name:
625            print "ERROR: Invalid encoding for the basis pattern variables."
626            return
627    else:
628        print "ERROR: Invalid number of basis pattern variables."
629        return
630               
631           
632    # Positional arguments
633    if (len(args) == 1):
634        # if the specified argument is not in the DefinitionSet, then assume that it's a filename
635        if args[0] not in DefinitionSet:
636            #define the characters in the list
637            defs = charset_input_parser.input_chardef(args[0])
638            if UTF_encoding.Encoding.encoding_error == True:
639               if UTF_encoding.Encoding.default:
640                  print "ERROR: The input file contains characters with mixed encodings."
641               else:
642                  print ''.join(["ERROR: The input file contains encodings that are not ",
643                                  UTF_encoding.Encoding.name, "."])
644               return
645        else: defs = DefinitionSet[args[1]]
646        if options.use_EBCDIC:
647            defs = EBCDIC.ascii2ebcdic_chardeflist(defs)
648        stmts = chardeflist2py(defs)
649        if options.Pablo_skeleton or options.test_skeleton:
650          b = string.split(options.basis_pattern, ".")
651          if len(b) == 2: 
652            basis_struct = string.upper(b[0][0]) + b[0][1:]
653            basis_struct_var = b[0]
654            bit_pattern = b[1]
655          else: 
656            basis_struct = 'Bits'
657            basis_stuct_var = 'bits'
658            bit_pattern = bit[0]
659          struct_defs = "class %s():\n" % basis_struct
660          for i in range(8): struct_defs += "\t" + bit_pattern % i + " = 0\n"
661          struct_sets = {}
662          for d in defs:
663            n = string.split(d.name, ".")
664            if len(n) == 2:
665              if not n[0] in struct_sets.keys(): struct_sets[n[0]] = []
666              struct_sets[n[0]].append(n[1])
667          for k in struct_sets.keys():
668            struct_defs += "\nclass %s():\n" % (string.upper(k[0])+k[1:])
669            for f in struct_sets[k]: struct_defs += "\t" + f + " = 0\n"
670          print struct_defs
671          params = ", ".join([basis_struct_var] + struct_sets.keys())
672          print "\ndef Do_defs(%s):\n" % params
673          print stmts
674          if options.test_skeleton:
675            for d in defs:
676              print '\tprint_register<BitBlock>("%s",%s);\n' % (d.name, d.name)
677          print "\ndef main():\n\tDo_defs(%s)\n" % params
678        else: print stmts 
679    else:
680        option_parser.print_usage()
681       
682
683if __name__ == "__main__": main()
684
Note: See TracBrowser for help on using the repository browser.