source: proto/charsetcompiler/charset_compiler.py @ 3349

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

Add UTF-16 and UTF-32 modes for charsetcompiler.py

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