source: proto/charsetcompiler/charset_compiler.py @ 3928

Last change on this file since 3928 was 3928, checked in by daled, 5 years ago

Implements the new algorithm to reduce the number of character class equations.

File size: 27.7 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    if len(chardef.items) > 1:
407        combine = True
408        #If all of the charset items are single codepoints
409        #such that X0 == Y0, X1 == Y1 etc.
410        for i in range(1, len(chardef.items)):
411            if len(chardef.items[i]) == 3:
412                combine = False
413                break
414        if combine == True:
415            #If charset items are all of the form X1 = X0 + 2.
416            for i in range(1 , len(chardef.items) - 1):
417                curr_item = chardef.items[i]
418                next_item = chardef.items[i+1]
419                if ord(curr_item) != ord(next_item) - 2:
420                    combine = False
421                    break
422        if combine == True:
423            first_item = ord(chardef.items[0])
424            last_item = ord(chardef.items[len(chardef.items)-1])
425            utf_temp = UTF_encoding.Encoding.mask - 1
426            first_item &= utf_temp
427            last_item |= (UTF_encoding.Encoding.mask ^ utf_temp)
428            return char_or_range_expr(chr(first_item) + '-' + chr(last_item))
429    e1 = char_or_range_expr(chardef.items[0])
430    for i in range(1, len(chardef.items)):   
431        e1 = make_or(e1, char_or_range_expr(chardef.items[i]))
432    if chardef.complemented: return make_not(e1)
433    else: return e1
434
435#
436#
437#  Code Generation
438#
439class CodeGenObject:
440    def __init__(self, predeclared, typedecl='BitBlock '):
441        self.gensym_template = options.gensym_pattern
442        self.gensym_counter = 0
443        self.generated_code = []
444        self.common_expression_map = {}
445        for sym in predeclared: self.common_expression_map[sym] = sym             
446        self.typedecl = typedecl
447    def add_assignment(self, varname, expr):
448        self.common_expression_map[expr] = varname
449        #self.generated_code.append('%s%s = %s;\n' % (self.typedecl, varname, expr))
450        self.generated_code.append('\t%s%s = %s\n' % (self.typedecl, varname, expr))
451    def expr_string_to_variable(self, expr_string):
452        if self.common_expression_map.has_key(expr_string):
453            return self.common_expression_map[expr_string]
454        else:
455            self.gensym_counter += 1                           
456            sym = self.gensym_template % self.gensym_counter 
457            self.add_assignment(sym, expr_string) 
458            return sym
459
460    def showcode(self):
461        s = ''
462        for stmt in self.generated_code: s += stmt
463        return s
464
465def expr2simd(genobj, expr):
466    """Translate a Boolean expression into three-address Altivec code
467       using code generator object genobj.
468    """
469    if isinstance(expr, TrueLiteral): return 'simd_const_1(1)'
470    elif isinstance(expr, FalseLiteral): return 'simd_const_1(0)'
471    elif isinstance(expr, Var): return expr.varname
472    elif isinstance(expr, Not):
473       e = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand))
474       return 'simd_andc(simd_const_1(1), %s)' % (e)
475    elif isinstance(expr, Or):
476       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
477       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
478       return 'simd_or(%s, %s)' % (e1, e2)
479    elif isinstance(expr, Xor):
480       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
481       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
482       return 'simd_xor(%s, %s)' % (e1, e2)
483    elif isinstance(expr, And):
484       if isinstance(expr.operand1, Not):
485           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1.operand))
486           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
487           return 'simd_andc(%s, %s)' % (e2, e1)
488       elif isinstance(expr.operand2, Not):
489           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
490           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2.operand))
491           return 'simd_andc(%s, %s)' % (e1, e2)
492       else:
493           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
494           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
495           return 'simd_and(%s, %s)' % (e1, e2)
496    elif isinstance(expr, Sel):
497       sel = genobj.expr_string_to_variable(expr2simd(genobj, expr.sel))
498       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.true_branch))
499       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.false_branch))
500       return 'simd_if(%s, %s, %s)' %(sel, e1, e2)
501
502def chardef2simd(genobj, chardef):
503    genobj.add_assignment(chardef.name, expr2simd(genobj, charset_expr(chardef)))
504
505def chardeflist2simd(chardeflist):
506    cgo = CodeGenObject([bit_var(i) for i in range(0, UTF_encoding.Encoding.bits)])
507    for d in chardeflist:
508        chardef2simd(cgo, d)
509    return cgo.showcode()
510
511def expr2py(genobj, expr):
512    """Translate a Boolean expression into three-address python code
513       using code generator object genobj.
514    """
515    if isinstance(expr, TrueLiteral): return '-1'
516    elif isinstance(expr, FalseLiteral): return '0'
517    elif isinstance(expr, Var): return expr.varname
518    elif isinstance(expr, Not):
519       e = genobj.expr_string_to_variable(expr2py(genobj, expr.operand))
520       return '(~%s)' % (e)
521    elif isinstance(expr, Or):
522       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
523       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
524       return '(%s | %s)' % (e1, e2)
525    elif isinstance(expr, Xor):
526       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
527       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
528       return '(%s ^ %s)' % (e1, e2)
529    elif isinstance(expr, And):
530       if isinstance(expr.operand1, Not):
531           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1.operand))
532           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
533           return '(%s &~ %s)' % (e2, e1)
534       elif isinstance(expr.operand2, Not):
535           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
536           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2.operand))
537           return '(%s &~ %s)' % (e1, e2)
538       else:
539           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
540           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
541           return '(%s & %s)' % (e1, e2)
542    elif isinstance(expr, Sel):
543       sel = genobj.expr_string_to_variable(expr2py(genobj, expr.sel))
544       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.true_branch))
545       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.false_branch))
546       return '((%s & %s)|(~(%s) & %s))' %(sel, e1, sel, e2)
547
548def chardef2py(genobj, chardef):
549    genobj.add_assignment(chardef.name, expr2py(genobj, charset_expr(chardef)))
550   
551def py_chardefmap(chardeflist):
552    defs = ["'%s' : %s" % (d.name,d.name) for d in chardeflist]
553    return  '{%s}' % string.join(defs, ',\n\t')
554
555def chardeflist2py(chardeflist):
556    cgo = CodeGenObject([bit_var(i) for i in range(0, UTF_encoding.Encoding.bits)],'') 
557    for d in chardeflist:
558        chardef2py(cgo, d) 
559    return cgo.showcode()# + "  return "+ py_chardefmap(chardeflist) + "\n"
560
561def main():   
562
563    global options
564    # Option definition
565    option_parser = optparse.OptionParser(usage='python %prog [options] <input file>', version='0.8')
566 
567    option_parser.add_option('-u', '--character_encoding',
568                             dest='character_encoding',
569                             type='string',
570                             default='Default',
571                             help='character encoding; default: UTF-8',
572                             ) 
573    option_parser.add_option('-b', '--basis_pattern', 
574                             dest='basis_pattern',
575                             type='string',
576                             default='basis_bits.bit_%i',
577                             help='pattern for basis bit streams; default: basis_bits.bit_%i',
578                             )
579    option_parser.add_option('-l', '--little_endian',
580                             dest='little_endian',
581                             action='store_true',
582                             default=False,
583                             help='sets bit numbering of the output to little-endian',
584                             )
585    option_parser.add_option('-g', '--gensym_pattern', 
586                             dest='gensym_pattern',
587                             type='string',
588                             default='temp%i',
589                             help='pattern for generated temporaries; default: temp%i',
590                             )
591    option_parser.add_option('-E', '--EBCDIC', 
592                             dest='use_EBCDIC',
593                             action='store_true', 
594                             default=False,
595                             help='generate definitions for EBCDIC input',
596                             )
597    option_parser.add_option('-p', '--pablo', 
598                             dest='Pablo_skeleton',
599                             action='store_true', 
600                             default=False,
601                             help='generate pablo skeleton',
602                             )
603    option_parser.add_option('-t', '--test', 
604                             dest='test_skeleton',
605                             action='store_true', 
606                             default=False,
607                             help='generate pablo test skeleton',
608                             )
609    options, args = option_parser.parse_args(sys.argv[1:])
610
611    # Set the encoding.
612       
613    #If the user has entered the encoding type as a command-line argument
614    #then the encoding type that is to be used is locked.
615    if options.character_encoding == UTF_encoding.UTF32.name:
616        UTF_encoding.Encoding = Encoding_Type(options.character_encoding, 
617        UTF_encoding.UTF32.bits, UTF_encoding.UTF32.mask, False, True)
618    elif options.character_encoding == UTF_encoding.UTF16.name:
619        UTF_encoding.Encoding = Encoding_Type(options.character_encoding, 
620        UTF_encoding.UTF16.bits, UTF_encoding.UTF16.mask, False, True)
621    elif options.character_encoding == UTF_encoding.UTF8.name: 
622        UTF_encoding.Encoding = Encoding_Type(options.character_encoding,
623        UTF_encoding.UTF8.bits, UTF_encoding.UTF8.mask, False, True)
624    elif options.character_encoding == 'Default': 
625        UTF_encoding.Encoding = Encoding_Type(UTF_encoding.UTF8.name, 
626        UTF_encoding.UTF8.bits, UTF_encoding.UTF8.mask, True, False)
627    else:
628        print "ERROR: Invalid encoding format."
629        return
630
631    # If we have a valid encoding format then set the basis pattern.
632    UTF_encoding.Encoding.basis_pattern = string.split(options.basis_pattern, ",")
633    if len(UTF_encoding.Encoding.basis_pattern) == 1:
634        # If we have the default basis pattern string then adjust it
635        # for UTF-16 or UTF-32.  If the encoding is UTF-8 then we will
636        # leave it as is.
637        if "basis_bits.bit_%i" in UTF_encoding.Encoding.basis_pattern[0]:
638            if UTF_encoding.UTF16.name in UTF_encoding.Encoding.name:
639                UTF_encoding.Encoding.basis_pattern[0] = "u16_bit%i"
640            elif UTF_encoding.UTF32.name in UTF_encoding.Encoding.name:
641                UTF_encoding.Encoding.basis_pattern[0] = "u32_bit%i"
642    elif len(UTF_encoding.Encoding.basis_pattern) == 2:
643        if UTF_encoding.UTF16.name not in UTF_encoding.Encoding.name:
644            print "ERROR: Invalid encoding for the basis pattern variables."
645            return
646    elif len(UTF_encoding.Encoding.basis_pattern) == 3:
647        if UTF_encoding.UTF32.name not in UTF_encoding.Encoding.name:
648            print "ERROR: Invalid encoding for the basis pattern variables."
649            return
650    else:
651        print "ERROR: Invalid number of basis pattern variables."
652        return
653               
654           
655    # Positional arguments
656    if (len(args) == 1):
657        # if the specified argument is not in the DefinitionSet, then assume that it's a filename
658        if args[0] not in DefinitionSet:
659            #define the characters in the list
660            defs = charset_input_parser.input_chardef(args[0])
661            if UTF_encoding.Encoding.encoding_error == True:
662               if UTF_encoding.Encoding.default:
663                  print "ERROR: The input file contains characters with mixed encodings."
664               else:
665                  print ''.join(["ERROR: The input file contains encodings that are not ",
666                                  UTF_encoding.Encoding.name, "."])
667               return
668        else: defs = DefinitionSet[args[1]]
669        if options.use_EBCDIC:
670            defs = EBCDIC.ascii2ebcdic_chardeflist(defs)
671        stmts = chardeflist2py(defs)
672        if options.Pablo_skeleton or options.test_skeleton:
673          b = string.split(options.basis_pattern, ".")
674          if len(b) == 2: 
675            basis_struct = string.upper(b[0][0]) + b[0][1:]
676            basis_struct_var = b[0]
677            bit_pattern = b[1]
678          else: 
679            basis_struct = 'Bits'
680            basis_stuct_var = 'bits'
681            bit_pattern = bit[0]
682          struct_defs = "class %s():\n" % basis_struct
683          for i in range(8): struct_defs += "\t" + bit_pattern % i + " = 0\n"
684          struct_sets = {}
685          for d in defs:
686            n = string.split(d.name, ".")
687            if len(n) == 2:
688              if not n[0] in struct_sets.keys(): struct_sets[n[0]] = []
689              struct_sets[n[0]].append(n[1])
690          for k in struct_sets.keys():
691            struct_defs += "\nclass %s():\n" % (string.upper(k[0])+k[1:])
692            for f in struct_sets[k]: struct_defs += "\t" + f + " = 0\n"
693          print struct_defs
694          params = ", ".join([basis_struct_var] + struct_sets.keys())
695          print "\ndef Do_defs(%s):\n" % params
696          print stmts
697          if options.test_skeleton:
698            for d in defs:
699              print '\tprint_register<BitBlock>("%s",%s);\n' % (d.name, d.name)
700          print "\ndef main():\n\tDo_defs(%s)\n" % params
701        else: 
702           print stmts
703           #fo = open("icgrep_dev/Z_equations.txt", "wb")
704           #fo.write(stmts);
705
706           # Close opend file
707           #fo.close()
708    else:
709        option_parser.print_usage()
710       
711
712if __name__ == "__main__": main()
713
Note: See TracBrowser for help on using the repository browser.