source: proto/RE/demo/pablo.py @ 3740

Last change on this file since 3740 was 3428, checked in by ksherdy, 6 years ago

Fixed line counting.

File size: 7.6 KB
Line 
1#
2# pablo.py
3#
4# Bitstream Utilities
5#
6# These are quick-and-dirty Python implementations of utilities
7# for demo purposes only.
8#
9# Dan Lin, Robert D. Cameron
10# March 24, 2012
11#
12#----------------------------------------------------------------------------
13#
14# We use python's unlimited precision integers for unbounded bit streams.
15# This permits simple logical operations on the entire stream.
16# Assumption: bitstreams are little-endian (e.g., as on x86).
17#
18#----------------------------------------------------------------------------
19#
20import sys
21import codecs
22# Utility functions for demo purposes.
23
24EOF_mask = 0
25data = ''
26
27def writefile(filename, s, charcode='utf-8',):
28        f = codecs.open(filename, 'w', encoding=charcode)
29        f.write(s) # writes encoded bytes to file
30        f.close()
31
32def readfile(filename):
33        f = open(filename, 'r')
34        contents = f.read() 
35        f.close()
36        return contents
37
38def transpose_streams(s, b):
39        mask = 128
40        index = 0
41        global data
42        while index < 8:
43                current = 0
44                cursor = 1
45                for byte in s:
46                        if  (ord(byte) & mask != 0):
47                                current += cursor
48                        cursor <<= 1
49                       
50                index+=1
51                mask>>=1
52                if index == 1:
53                        b.bit_0 = current
54                elif index == 2:
55                        b.bit_1 = current
56                elif index == 3:
57                        b.bit_2 = current
58                elif index == 4:
59                        b.bit_3 = current
60                elif index == 5:
61                        b.bit_4 = current
62                elif index == 6:
63                        b.bit_5 = current
64                elif index == 7:
65                        b.bit_6 = current
66                elif index == 8:
67                        b.bit_7 = current
68        data  = s
69        return cursor-1  # basis streams and EOF mask
70
71def match(s,marker):
72        pos = count_leading_zeroes(marker)
73        i = 0
74        for byte in s:
75                if byte != data[pos+i]:
76                        return 0
77                i +=1
78        return marker
79
80def inFile(lex_error):
81        return EOF_mask & lex_error
82
83def atEOF(strm):
84        if strm > EOF_mask or strm < 0:
85                return EOF_mask + 1
86        else:
87                return 0
88
89def count_leading_zeroes(strm):
90        zeroes = 0
91        while (strm & 0xFFFFFFFF) == 0: 
92                zeroes += 32
93                strm >>= 32
94        while (strm & 1) == 0:
95                zeroes += 1
96                strm >>= 1
97        return zeroes
98#
99#
100#  Are there any bits in a stream
101def any(strm):
102        return strm != 0
103#
104#  ScanThru is the core operation for parallel scanning.
105#  Given a bitstream Cursors marking current cursor positions,
106#  advance each cursor through occurrences of a character
107#  class identified by ScanStream.
108
109def ScanThru(Cursors, ScanStream):
110        return (Cursors + ScanStream) & ~ScanStream
111       
112def ScanTo(Cursors, ToStream): 
113        ScanStream = ~ToStream & EOF_mask
114        return (Cursors + ScanStream ) &~ ScanStream
115
116def ScanToFirst(ScanStream):
117        return ScanTo(1, ScanStream)
118#
119# Advance all cursors by one position.
120def Advance(stream):
121        return stream + stream
122       
123def AdvancebyPos(stream, pos):
124        return stream << pos
125
126
127#
128# Advance-and-Scan
129#
130# These are common and useful operations, with a slight
131# optimization to avoid a separate Advance.   
132#
133# Warning:  they each require a "separation" property
134# between markers and scanclass streams.   This property
135# normally seems to hold in our applications, but we should
136# work out methods for formally establishing it.
137#
138# AdvanceThenScanThru(marker, scanclass)
139# optimizes: ScanThru(Advance(marker), scanclass)
140# requires: scanclass-marker separation: no occurrence of
141# a marker immediately after a scanclass run.  That is,
142# any(Advance(scanclass) & marker) == False
143# (this is a sufficient precondition, but maybe not weakest.)
144#
145def AdvanceThenScanThru(marker, scanclass):     
146        return ScanThru(marker, marker | scanclass)
147#
148# AdvanceThenScanTo(marker, scanclass)
149# optimizes: ScanTo(Advance(marker), scanclass)
150# requires: scanclass existence between markers
151
152def AdvanceThenScanTo(marker, scanclass):
153        #return ScanTo(Advance(marker), scanclass)
154        charclass = ~scanclass & EOF_mask
155        return (marker + (charclass | marker)) &~ charclass
156
157#
158# Span operations
159# These operations define spans of positions from
160# starting to ending positions.
161# Requirement:  start and end positions are properly
162# matched: popcount(ends)==popcount(starts) and
163# nth-one(starts, n) < nth-one(ends, n), if n < popcount(starts)
164# nth-one(ends, n) < nth-one(starts, n+1) if n < popcount(starts)
165
166#def First():
167#       return Advance(~0) ^ ~0
168
169def First():
170        return ~Advance(~0)
171
172def PopCount(stream):
173        count = 0
174        while(stream > 0):
175                if stream & 1 == 1: count += 1
176                stream >>= 1
177        return count
178
179def MatchStar(marker, scanclass):
180  return (((marker & scanclass) + scanclass) ^ scanclass) | marker
181
182def SpanUpTo(starts, ends):
183        return (ends - starts)
184
185def InclusiveSpan(starts, ends): 
186        return (ends - starts) | ends
187
188def ExclusiveSpan(starts, ends): 
189        return (ends - starts) &~ starts
190
191#Functions copied from bitutil.py
192def writefile(filename, s, charcode='utf-8',):
193        f = codecs.open(filename, 'w', encoding=charcode)
194        f.write(s) # writes encoded bytes to file
195        f.close()
196
197def EOF_mask(strm_lgth):
198        mask = 1
199        mask <<= (strm_lgth)
200        mask -= 1
201        return mask
202
203def extract_bit(strm, pos):
204        bit = (strm >> pos) & 1
205        return bit
206
207def inverse_transpose(bitset, len):
208        bytestream=""
209        cursor = 1
210        for i in range(0, len):
211                byteval = 0
212                for j in range(0,8):
213                        if bitset[j] & cursor != 0:
214                                byteval += 128 >> j
215                bytestream += chr(byteval)
216                cursor += cursor
217        return bytestream
218                       
219def filter_bits(bitstream, delmask):
220        newstream = 0
221        cursor = 1
222        while delmask > 0:
223                if delmask & 1 == 0:
224                        if bitstream & 1 == 1:
225                                newstream += cursor
226                        cursor += cursor
227                delmask >>= 1
228                bitstream >>= 1
229        while bitstream > 0:
230                if bitstream & 1 == 1:
231                        newstream += cursor
232                cursor += cursor
233                bitstream >>= 1         
234        return newstream
235                       
236def filter_bytes(bytestream, delmask):
237        newstream=""
238        cursor = 1
239        for c in bytestream:
240                if delmask & cursor == 0:
241                        newstream += c
242                cursor += cursor
243        return newstream
244                       
245def merge_bytes(stream1, stream2):
246        s = ""
247        for i in range(len(stream1)):
248                s += stream1[i]
249                s += stream2[i]
250        return s
251
252def bitstream2string(stream, lgth):
253        str = ""
254        for i in range(lgth):
255                if stream & 1 == 1: str += '1'
256                else: str += '_'
257                stream >>= 1
258        return str
259
260def bitstream2stringLE(stream, lgth):
261        str = ""
262        for i in range(lgth):
263                if stream & 1 == 1: str = '1' + str
264                else: str = '_' + str
265                stream >>= 1
266        return str
267
268def print_aligned_streams(stream_list):
269        """Print out a set of aligned streams."""
270        label_max = max([len(p[0]) for p in stream_list])
271        for p in stream_list:
272                print (p[0] + " "*(label_max - len(p[0]))) + ": " + p[1] 
273
274def latex_streams(stream_list):
275        """Return a latex table for streams."""
276        table = "\\begin{tabular}{cr}"
277        for p in stream_list:
278                table += "\\\\\n" + p[0] +" & \\verb`" + p[1] +"`"
279        return table + "\n\\end{tabular}\n"
280
281def print_aligned_u8_byte_streams(u8_byte_stream):
282        """Print out a set of 'encoding' aligned streams."""
283
284        # Set the system info to print utf-8
285        info = codecs.lookup('utf-8')
286        sys.stdout = info.streamwriter(sys.stdout) 
287
288        label_max = max([len(p[0]) for p in u8_byte_stream])
289        for p in u8_byte_stream:
290                sys.stdout.write(p[0] + " "*(label_max - len(p[0])) + ": ")
291               
292                for c in (p[1].decode('utf-8')):                        # for each unicode character
293                        u8_seq_len = len(c.encode('utf-8'))     # encode the unicode character as utf-8 and get the utf-8 sequence length
294                        if u8_seq_len == 1:
295                                sys.stdout.write(c)
296                        elif u8_seq_len == 2:
297                                sys.stdout.write('2_')                          # align 2 byte sequences with a trailing _
298                        elif u8_seq_len == 3:
299                                sys.stdout.write('3__')                         # align 3 byte sequences with 2 trailing _
300                        elif u8_seq_len == 4:
301                                sys.stdout.write('4___')                        # align 2 byte sequences with 3 trailing _               
302                        else:
303                                sys.stdout.write('Error: Invalid UTF-8 character sequence of length: ' + str(u8_seq_len) + '.')                 
304                sys.stdout.write('\n')   
305
306def high_nybble_stream(bytes):
307        str=""
308        for b in bytes:
309                h = hex(ord(b))[-2]
310                if h == 'x': str += '0'
311                else: str += h
312        return str
313
314def low_nybble_stream(bytes):
315        str=""
316        for b in bytes:
317                str += hex(ord(b))[-1]
318        return str
319
320
Note: See TracBrowser for help on using the repository browser.