1#!/usr/bin/env python3 2# 3# SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com> 4# 5# SPDX-License-Identifier: LGPL-2.1-only 6# 7 8""" 9This is a ugly code generate script, which is intended to be used 10against i18nIMProto.c in IMdkit 11it will generate all serialization code against xim protocol frame 12""" 13import fileinput 14import collections 15import sys 16funcs = collections.OrderedDict() 17static_size = dict() 18 19funcname = None 20for line in fileinput.input(sys.argv[1]): 21 if "XimFrameRec" in line: 22 tokens = line.strip().split() 23 token = None 24 for token in tokens: 25 if "[]" in token: 26 break 27 if token is not None: 28 funcname = "xcb_im_" + token[:-2] 29 funcs[funcname] = [] 30 fieldidx = 0 31 elif "FRAME(EOL)" in line: 32 funcname = None 33 elif funcname is not None: 34 line = line.strip() 35 36 try: 37 tp = line[:line.rindex("),")+1] 38 if tp == "_FRAME(POINTER)": 39 continue 40 if line.find("/*") != -1: 41 name = line[line.find("/*")+2:line.find("*/")] 42 name = name.strip().replace(" ", "_").replace(".", "_").replace("-", "_") 43 else: 44 name = "field{0}".format(fieldidx) 45 fieldidx += 1 46 funcs[funcname].append((tp,name)) 47 except Exception as e: 48 pass 49 50def gettypename(attr): 51 if "BIT8" in attr: 52 return ("uint8_t") 53 elif "BIT16" in attr: 54 return ("uint16_t") 55 elif "BIT32" in attr: 56 return ("uint32_t") 57 elif attr == "_FRAME(BARRAY)": 58 return ("xcb_im_bytearray_t") 59 elif "_PTR" in attr: 60 return "xcb_im_" + attr[attr.find("(") + 1:attr.find(")")] 61 else: 62 print(attr) 63 assert(False) 64 65for funcname, attrs in funcs.items(): 66 size = 0 67 for attr, name in attrs: 68 if "BIT8" in attr: 69 size += 1 70 elif "BIT16" in attr: 71 size += 2 72 elif "BIT32" in attr: 73 size += 4 74 elif "PAD" in attr: 75 pad = int(attr[4]) 76 size += 0 if size % pad == 0 else (pad - size % pad) 77 elif "PTR" in attr: 78 if static_size[gettypename(attr)] < 0: 79 size = -1 80 break 81 else: 82 size += static_size[gettypename(attr)] 83 else: 84 size = -1 85 break 86 static_size[funcname] = size 87 88 89 90def getsize(attr, name): 91 if "BIT8" in attr: 92 return "1" 93 elif "BIT16" in attr: 94 return "2" 95 elif "BIT32" in attr: 96 return "4" 97 elif "_PTR" in attr: 98 return "{1}_size(&frame->{0})".format(name, gettypename(attr)) 99 100 101def search_barray_length(attrs, i): 102 for attr, name in reversed(attrs[0:i]): 103 if "length" in name: 104 return (attr, name) 105 106 return attrs[i - 1] 107 108if len(sys.argv) > 2: 109 for funcname, attrs in funcs.items(): 110 print("typedef struct _{0}_t".format(funcname)) 111 print("{") 112 skip = False 113 for i, (attr, name) in enumerate(attrs): 114 if skip: 115 skip = False 116 continue 117 if "_FRAME(B" in attr: 118 print(" {1} {0};".format(name, gettypename(attr))) 119 if "_PTR" in attr: 120 print(" {1}_t {0};".format(name, gettypename(attr))) 121 elif "_PAD" in attr: 122 pass 123 elif "_BYTE_COUNTER" in attr: 124 pass 125 elif attr == "_FRAME(ITER)": 126 (iterattr, itername) = attrs[i + 1] 127 print(" struct {") 128 print(" uint32_t size;") 129 if "_FRAME(B" in iterattr: 130 print(" {0}* items;".format(gettypename(iterattr))) 131 if "_PTR" in iterattr: 132 print(" {0}_t* items;".format(gettypename(iterattr))) 133 print(" }} {0};".format(name)) 134 skip = True 135 136 print("}} {0}_t;".format(funcname)) 137 print("") 138 def print_generic(cat): 139 print("#define frame_{0}_func(FRAME) _Generic((FRAME), \\".format(cat)) 140 first = True 141 for funcname, attrs in funcs.items(): 142 if first: 143 first=False 144 else: 145 print(",\\") 146 if cat == "size": 147 if static_size[funcname] >= 0: 148 print(" {0}_t : {1}".format(funcname, static_size[funcname]), end='') 149 else: 150 print(" {0}_t : {0}_{1}(({0}_t*) &(FRAME))".format(funcname, cat), end='') 151 else: 152 print(" {0}_t : {0}_{1}".format(funcname, cat), end='') 153 print(")") 154 print("") 155 for cat in ["read", "write", "size", "free"]: 156 print_generic(cat) 157 def print_generic_size(): 158 print("#define frame_has_static_size(FRAME) _Generic((FRAME), \\".format(cat)) 159 first = True 160 for funcname, attrs in funcs.items(): 161 if first: 162 first=False 163 else: 164 print(",\\") 165 print(" {0}_t : {1}".format(funcname, "true" if static_size[funcname] >= 0 else "false"), end='') 166 print(")") 167 print("") 168 print_generic_size() 169 170 for funcname, attrs in funcs.items(): 171 usecounter = any("_BYTE_COUNTER" in attr for attr, name in attrs) 172 usecounter8 = any("_BYTE_COUNTER(BIT8" in attr for attr, name in attrs) 173 usecounter16 = any("_BYTE_COUNTER(BIT16" in attr for attr, name in attrs) 174 usecounter32 = any("_BYTE_COUNTER(BIT32" in attr for attr, name in attrs) 175 print(("""void {0}_read({0}_t *frame, uint8_t **data, size_t *len, bool swap);\n""" 176 """uint8_t* {0}_write({0}_t *frame, uint8_t *data, bool swap);\n""" 177 """void {0}_free({0}_t *frame);""").format(funcname)) 178 if static_size[funcname] >= 0: 179 print("""#define {0}_size(ARG...) (((void)(ARG)), ({1}))""".format(funcname, static_size[funcname])) 180 else: 181 print("""size_t {0}_size({0}_t *frame);""".format(funcname)) 182 print("") 183else: 184 print("#include <string.h>") 185 print("#include \"parser.h\"") 186 print("#include \"ximproto.h\"") 187 print("") 188 189 for funcname, attrs in funcs.items(): 190 usecounter = any("_BYTE_COUNTER" in attr for attr, name in attrs) 191 usecounter8 = any("_BYTE_COUNTER(BIT8" in attr for attr, name in attrs) 192 usecounter16 = any("_BYTE_COUNTER(BIT16" in attr for attr, name in attrs) 193 usecounter32 = any("_BYTE_COUNTER(BIT32" in attr for attr, name in attrs) 194 usepad = any("_PAD" in attr for attr, name in attrs) 195 print("void {0}_read({0}_t *frame, uint8_t **data, size_t *len, bool swap)".format(funcname)) 196 print("{") 197 if len(attrs) > 0: 198 print(" memset(frame, 0, sizeof(*frame));") 199 if usepad: 200 print(" uint8_t* start = *data;") 201 if usecounter: 202 if usecounter8: 203 print(" uint8_t counter8 = 0;") 204 if usecounter16: 205 print(" uint16_t counter16 = 0;") 206 if usecounter32: 207 print(" uint32_t counter32 = 0;") 208 print(" size_t counter = 0;") 209 skip = False 210 for i, (attr, name) in enumerate(attrs): 211 if skip: 212 skip = False 213 continue 214 if "_FRAME(BIT" in attr or "_PTR" in attr: 215 print(" {1}_read(&frame->{0}, data, len, swap);".format(name, gettypename(attr))) 216 print(" if (!*data) { return; }") 217 elif "_FRAME(BARRAY" in attr: 218 (lenattr, lenname) = search_barray_length(attrs, i) 219 print(" {1}_read(&frame->{0}, frame->{2}, data, len, swap);".format(name, gettypename(attr), lenname)) 220 print(" if (!*data) { return; }") 221 elif "_PAD" in attr: 222 print(" *data = (uint8_t*) align_to_{0}((uintptr_t) *data, *data - start, len);".format(attr[4])) 223 print(" if (!*data) { return; }") 224 elif "_BYTE_COUNTER" in attr: 225 if "BIT8" in attr: 226 countername = "counter8" 227 elif "BIT16" in attr: 228 countername = "counter16" 229 elif "BIT32" in attr: 230 countername = "counter32" 231 print(" {1}_read(&{0}, data, len, swap);".format(countername, gettypename(attr))) 232 print(" if (!*data) { return; }") 233 if countername != "counter": 234 print(" counter = {0};".format(countername)) 235 elif attr == "_FRAME(ITER)": 236 (iterattr, itername) = attrs[i + 1] 237 print(" if (counter > *len) { *data = NULL; return; } else { *len -= counter; } ") 238 print(" frame->{0}.items = NULL;".format(name, gettypename(iterattr))) 239 print(" frame->{0}.size = 0;".format(name)) 240 print(" while (counter != 0) {") 241 if "_PTR" in iterattr: 242 print(" void* temp = realloc(frame->{0}.items, (frame->{0}.size + 1) * sizeof({1}_t));".format(name, gettypename(iterattr))) 243 else: 244 print(" void* temp = realloc(frame->{0}.items, (frame->{0}.size + 1) * sizeof({1}));".format(name, gettypename(iterattr))) 245 print(" if (!temp) {") 246 print(" *data = NULL;") 247 print(" return;") 248 print(" }") 249 print(" frame->{0}.items = temp;".format(name)) 250 print(" {1}_read(&frame->{0}.items[frame->{0}.size], data, &counter, swap);".format(name, gettypename(iterattr))) 251 print(" if (!*data) { return; }") 252 print(" frame->{0}.size++;".format(name)) 253 print(" }") 254 skip = True 255 256 print("}") 257 print("") 258 print("uint8_t* {0}_write({0}_t *frame, uint8_t *data, bool swap)".format(funcname)) 259 print("{") 260 if usepad: 261 print(" uint8_t* start = data;") 262 if usecounter: 263 if usecounter8: 264 print(" uint8_t counter8 = 0;") 265 if usecounter16: 266 print(" uint16_t counter16 = 0;") 267 if usecounter32: 268 print(" uint32_t counter = 0;") 269 skip = False 270 for i, (attr, name) in enumerate(attrs): 271 if skip: 272 skip = False 273 continue 274 if "_FRAME(BIT" in attr or "_PTR" in attr: 275 print(" data = {1}_write(&frame->{0}, data, swap);".format(name, gettypename(attr))) 276 elif "_FRAME(BARRAY" in attr: 277 (lenattr, lenname) = search_barray_length(attrs, i) 278 print(" data = {1}_write(&frame->{0}, frame->{2}, data, swap);".format(name, gettypename(attr), lenname)) 279 elif "_PAD" in attr: 280 print(" data = (uint8_t*) align_to_{0}((uintptr_t) data, data - start, NULL);".format(attr[4])) 281 elif "_BYTE_COUNTER" in attr: 282 for j, (targetattr, targetname) in enumerate(attrs): 283 if j < i + 1: 284 continue 285 if targetattr == "_FRAME(ITER)": 286 (iterattr, itername) = attrs[j + 1] 287 break 288 if "BIT8" in attr: 289 countername = "counter8" 290 elif "BIT16" in attr: 291 countername = "counter16" 292 elif "BIT32" in attr: 293 countername = "counter" 294 if "_PTR" in iterattr: 295 print(" {0} = 0;".format(countername)); 296 print(" for (uint32_t i = 0; i < frame->{0}.size; i++) {{".format(targetname)) 297 print(" {2} += {1}_size(&frame->{0}.items[i]);".format(targetname, gettypename(iterattr), countername)) 298 print(" }") 299 else: 300 print(" {0} = frame->{1}.size * {2};".format(countername, targetname, getsize(iterattr, itername))) 301 print(" data = {1}_write(&{0}, data, swap);".format(countername, gettypename(attr))) 302 elif attr == "_FRAME(ITER)": 303 (iterattr, itername) = attrs[i + 1] 304 print(" for (uint32_t i = 0; i < frame->{0}.size; i++) {{".format(name)) 305 print(" data = {1}_write(&frame->{0}.items[i], data, swap);".format(name, gettypename(iterattr))) 306 print(" }") 307 skip = True 308 309 print(" return data;"); 310 311 print("}") 312 print("") 313 314 if static_size[funcname] < 0: 315 print("size_t {0}_size({0}_t *frame)".format(funcname)) 316 print("{") 317 print(" size_t size = 0;") 318 skip = False 319 for i, (attr, name) in enumerate(attrs): 320 if skip: 321 skip = False 322 continue 323 if "_FRAME(BIT" in attr or "_BYTE_COUNTER" in attr: 324 print(" size += {0};".format(getsize(attr, name))) 325 elif "_PTR" in attr: 326 print(" size += {1}_size(&frame->{0});".format(name, gettypename(attr))) 327 elif "_FRAME(BARRAY" in attr: 328 (lenattr, lenname) = search_barray_length(attrs, i) 329 print(" size += frame->{0};".format(lenname)) 330 elif "_PAD" in attr: 331 print(" size = align_to_{0}(size, size, NULL);".format(attr[4])) 332 elif attr == "_FRAME(ITER)": 333 (iterattr, itername) = attrs[i + 1] 334 if "_PTR" in iterattr: 335 print(" for (uint32_t i = 0; i < frame->{0}.size; i++) {{".format(name)) 336 print(" size += {1}_size(&frame->{0}.items[i]);".format(name, gettypename(iterattr))) 337 print(" }") 338 339 else: 340 print(" size += frame->{0}.size * {1};".format(name, getsize(iterattr, itername))) 341 skip = True 342 print(" return size;") 343 344 345 print("}") 346 print("") 347 348 print("void {0}_free({0}_t *frame)".format(funcname)) 349 print("{") 350 for i, (attr, name) in enumerate(attrs): 351 if skip: 352 skip = False 353 continue 354 if "_PTR" in attr: 355 print(" {1}_free(&frame->{0});".format(name, gettypename(attr))) 356 elif "_FRAME(BARRAY" in attr: 357 pass 358 elif attr == "_FRAME(ITER)": 359 (iterattr, itername) = attrs[i + 1] 360 if "_PTR" in iterattr: 361 print(" if (frame->{0}.items) {{".format(name)) 362 print(" for (uint32_t i = 0; i < frame->{0}.size; i++) {{".format(name)) 363 print(" {1}_free(&frame->{0}.items[i]);".format(name, gettypename(iterattr))) 364 print(" }") 365 print(" }") 366 print(" free(frame->{0}.items);".format(name)) 367 skip = True 368 369 370 print("}") 371 print("") 372