Mercurial > cpython-lru_cache-weakref
annotate Tools/scripts/abitype.py @ 70817:dd775b1561ba
Fix markup.
| author | Georg Brandl <georg@python.org> |
|---|---|
| date | Tue, 14 Jun 2011 21:09:55 +0200 |
| parents | 20d82873aa97 |
| children | 65d5ecefd50d |
| rev | line source |
|---|---|
| 66664 | 1 # This script converts a C file to use the PEP 384 type definition API |
| 2 # Usage: abitype.py < old_code > new_code | |
| 3 import re, sys | |
| 4 | |
| 5 ############ Simplistic C scanner ################################## | |
| 6 tokenizer = re.compile( | |
| 7 r"(?P<preproc>#.*\n)" | |
| 8 r"|(?P<comment>/\*.*?\*/)" | |
| 9 r"|(?P<ident>[a-zA-Z_][a-zA-Z0-9_]*)" | |
| 10 r"|(?P<ws>[ \t\n]+)" | |
| 11 r"|(?P<other>.)", | |
| 12 re.MULTILINE) | |
| 13 | |
| 14 tokens = [] | |
| 15 source = sys.stdin.read() | |
| 16 pos = 0 | |
| 17 while pos != len(source): | |
| 18 m = tokenizer.match(source, pos) | |
| 19 tokens.append([m.lastgroup, m.group()]) | |
| 20 pos += len(tokens[-1][1]) | |
| 21 if tokens[-1][0] == 'preproc': | |
| 22 # continuation lines are considered | |
| 23 # only in preprocess statements | |
| 24 while tokens[-1][1].endswith('\\\n'): | |
| 25 nl = source.find('\n', pos) | |
| 26 if nl == -1: | |
| 27 line = source[pos:] | |
| 28 else: | |
| 29 line = source[pos:nl+1] | |
| 30 tokens[-1][1] += line | |
| 31 pos += len(line) | |
| 32 | |
| 33 ###### Replacement of PyTypeObject static instances ############## | |
| 34 | |
| 35 # classify each token, giving it a one-letter code: | |
| 36 # S: static | |
| 37 # T: PyTypeObject | |
| 38 # I: ident | |
| 39 # W: whitespace | |
| 40 # =, {, }, ; : themselves | |
| 41 def classify(): | |
| 42 res = [] | |
| 43 for t,v in tokens: | |
| 44 if t == 'other' and v in "={};": | |
| 45 res.append(v) | |
| 46 elif t == 'ident': | |
| 47 if v == 'PyTypeObject': | |
| 48 res.append('T') | |
| 49 elif v == 'static': | |
| 50 res.append('S') | |
| 51 else: | |
| 52 res.append('I') | |
| 53 elif t == 'ws': | |
| 54 res.append('W') | |
| 55 else: | |
| 56 res.append('.') | |
| 57 return ''.join(res) | |
| 58 | |
| 59 # Obtain a list of fields of a PyTypeObject, in declaration order, | |
| 60 # skipping ob_base | |
| 61 # All comments are dropped from the variable (which are typically | |
| 62 # just the slot names, anyway), and information is discarded whether | |
| 63 # the original type was static. | |
| 64 def get_fields(start, real_end): | |
| 65 pos = start | |
| 66 # static? | |
| 67 if tokens[pos][1] == 'static': | |
| 68 pos += 2 | |
| 69 # PyTypeObject | |
| 70 pos += 2 | |
| 71 # name | |
| 72 name = tokens[pos][1] | |
| 73 pos += 1 | |
| 74 while tokens[pos][1] != '{': | |
| 75 pos += 1 | |
| 76 pos += 1 | |
| 77 # PyVarObject_HEAD_INIT | |
| 78 while tokens[pos][0] in ('ws', 'comment'): | |
| 79 pos += 1 | |
| 80 if tokens[pos][1] != 'PyVarObject_HEAD_INIT': | |
| 81 raise Exception, '%s has no PyVarObject_HEAD_INIT' % name | |
| 82 while tokens[pos][1] != ')': | |
| 83 pos += 1 | |
| 84 pos += 1 | |
| 85 # field definitions: various tokens, comma-separated | |
| 86 fields = [] | |
| 87 while True: | |
| 88 while tokens[pos][0] in ('ws', 'comment'): | |
| 89 pos += 1 | |
| 90 end = pos | |
| 91 while tokens[end][1] not in ',}': | |
| 92 if tokens[end][1] == '(': | |
| 93 nesting = 1 | |
| 94 while nesting: | |
| 95 end += 1 | |
| 96 if tokens[end][1] == '(': nesting+=1 | |
| 97 if tokens[end][1] == ')': nesting-=1 | |
| 98 end += 1 | |
| 99 assert end < real_end | |
| 100 # join field, excluding separator and trailing ws | |
| 101 end1 = end-1 | |
| 102 while tokens[end1][0] in ('ws', 'comment'): | |
| 103 end1 -= 1 | |
| 104 fields.append(''.join(t[1] for t in tokens[pos:end1+1])) | |
| 105 if tokens[end][1] == '}': | |
| 106 break | |
| 107 pos = end+1 | |
| 108 return name, fields | |
| 109 | |
| 110 # List of type slots as of Python 3.2, omitting ob_base | |
| 111 typeslots = [ | |
| 112 'tp_name', | |
| 113 'tp_basicsize', | |
| 114 'tp_itemsize', | |
| 115 'tp_dealloc', | |
| 116 'tp_print', | |
| 117 'tp_getattr', | |
| 118 'tp_setattr', | |
| 119 'tp_reserved', | |
| 120 'tp_repr', | |
| 121 'tp_as_number', | |
| 122 'tp_as_sequence', | |
| 123 'tp_as_mapping', | |
| 124 'tp_hash', | |
| 125 'tp_call', | |
| 126 'tp_str', | |
| 127 'tp_getattro', | |
| 128 'tp_setattro', | |
| 129 'tp_as_buffer', | |
| 130 'tp_flags', | |
| 131 'tp_doc', | |
| 132 'tp_traverse', | |
| 133 'tp_clear', | |
| 134 'tp_richcompare', | |
| 135 'tp_weaklistoffset', | |
| 136 'tp_iter', | |
| 137 'iternextfunc', | |
| 138 'tp_methods', | |
| 139 'tp_members', | |
| 140 'tp_getset', | |
| 141 'tp_base', | |
| 142 'tp_dict', | |
| 143 'tp_descr_get', | |
| 144 'tp_descr_set', | |
| 145 'tp_dictoffset', | |
| 146 'tp_init', | |
| 147 'tp_alloc', | |
| 148 'tp_new', | |
| 149 'tp_free', | |
| 150 'tp_is_gc', | |
| 151 'tp_bases', | |
| 152 'tp_mro', | |
| 153 'tp_cache', | |
| 154 'tp_subclasses', | |
| 155 'tp_weaklist', | |
| 156 'tp_del' | |
| 157 'tp_version_tag' | |
| 158 ] | |
| 159 | |
| 160 # Generate a PyType_Spec definition | |
| 161 def make_slots(name, fields): | |
| 162 res = [] | |
| 163 res.append('static PyType_Slot %s_slots[] = {' % name) | |
| 164 # defaults for spec | |
|
67924
20d82873aa97
Issue #11135: Remove redundant doc field from PyType_Spec.
Martin v. Löwis <martin@v.loewis.de>
parents:
66664
diff
changeset
|
165 spec = { 'tp_itemsize':'0' } |
| 66664 | 166 for i, val in enumerate(fields): |
| 167 if val.endswith('0'): | |
| 168 continue | |
| 169 if typeslots[i] in ('tp_name', 'tp_doc', 'tp_basicsize', | |
| 170 'tp_itemsize', 'tp_flags'): | |
| 171 spec[typeslots[i]] = val | |
| 172 continue | |
| 173 res.append(' {Py_%s, %s},' % (typeslots[i], val)) | |
| 174 res.append('};') | |
| 175 res.append('static PyType_Spec %s_spec = {' % name) | |
| 176 res.append(' %s,' % spec['tp_name']) | |
| 177 res.append(' %s,' % spec['tp_basicsize']) | |
| 178 res.append(' %s,' % spec['tp_itemsize']) | |
| 179 res.append(' %s,' % spec['tp_flags']) | |
| 180 res.append(' %s_slots,' % name) | |
| 181 res.append('};\n') | |
| 182 return '\n'.join(res) | |
| 183 | |
| 184 | |
| 185 # Main loop: replace all static PyTypeObjects until | |
| 186 # there are none left. | |
| 187 while 1: | |
| 188 c = classify() | |
| 189 m = re.search('(SW)?TWIW?=W?{.*?};', c) | |
| 190 if not m: | |
| 191 break | |
| 192 start = m.start() | |
| 193 end = m.end() | |
| 194 name, fields = get_fields(start, m) | |
| 195 tokens[start:end] = [('',make_slots(name, fields))] | |
| 196 | |
| 197 # Output result to stdout | |
| 198 for t, v in tokens: | |
| 199 sys.stdout.write(v) |
