7 def __init__(self
, args
, name
):
10 self
.line
= line_count
11 def emit_declaration(self
):
12 return ["\tint %s;" % self
.name
]
14 return "#line %d" % self
.line
15 def emit_secure(self
, parent
):
17 def emit_unpack(self
):
18 return ["msg.%s = msg_unpack_int();" % self
.name
]
19 def emit_unpack_check(self
):
22 return ["\t\tmsg_pack_int(%s);" % self
.name
]
24 class var_any(variable
):
25 def __init__(self
, args
, name
):
26 variable
.__init
__(self
, args
, name
)
28 class var_range(variable
):
29 def __init__(self
, args
, name
):
30 variable
.__init
__(self
, args
, name
)
33 def emit_unpack_check(self
):
34 return ["if(msg.%s < %s || msg.%s > %s) { msg_failed_on = \"%s\"; return 0; }" % (self
.name
, self
.min, self
.name
, self
.max, self
.name
)]
35 def emit_secure(self
, parent
):
36 return [self
.linedef(), "obj->%s = netobj_clamp_int(\"%s.%s\", obj->%s, %s, %s);" % (self
.name
, parent
.name
, self
.name
, self
.name
, self
.min, self
.max)]
38 class var_string(variable
):
39 def __init__(self
, args
, name
):
40 variable
.__init
__(self
, args
, name
)
42 class var_string(variable
):
43 def __init__(self
, args
, name
):
44 variable
.__init
__(self
, args
, name
)
45 def emit_declaration(self
):
46 return ["\tconst char *%s;" % self
.name
]
47 def emit_unpack(self
):
48 return ["msg.%s = msg_unpack_string();" % self
.name
]
50 return ["\t\tmsg_pack_string(%s, -1);" % self
.name
]
53 def __init__(self
, line
):
57 if len(fields
) == 4 and fields
[2] == "extends":
58 self
.extends
= fields
[3]
59 self
.enum_name
= "NETOBJTYPE_%s" % self
.name
.upper()
60 self
.struct_name
= "NETOBJ_%s" % self
.name
.upper()
63 def parse(self
, lines
):
65 for index
in xrange(0, len(lines
)):
72 return lines
[index
+1:]
75 fields
= line
.split(")", 1)
77 names
= [line
.strip() for line
in fields
[1].split(",")]
78 l
= fields
[0].split("(", 1)
80 args
= [line
.strip() for line
in l
[1].split(",")]
82 l
= fields
[0].split(None, 1)
85 names
= [line
.strip() for line
in l
[1].split(",")]
88 create_string
= 'var_%s(%s, "%s")' % (type, args
, name
)
89 new_member
= eval(create_string
)
90 self
.members
+= [new_member
]
92 raise BaseException("Parse error")
94 def emit_declaration(self
):
97 lines
+= ["struct %s : public NETOBJ_%s\n {" % (self
.struct_name
, self
.extends
.upper())]
99 lines
+= ["struct %s\n {" % self
.struct_name
]
100 for m
in self
.members
:
101 lines
+= m
.emit_declaration()
105 def emit_secure(self
):
107 for m
in self
.members
:
108 lines
+= m
.emit_secure(self
)
112 def __init__(self
, line
):
113 fields
= line
.split()
114 self
.name
= fields
[1]
115 self
.enum_name
= "NETMSGTYPE_%s" % self
.name
.upper()
116 self
.struct_name
= "NETMSG_%s" % self
.name
.upper()
119 def parse(self
, lines
):
121 for index
in xrange(0, len(lines
)):
128 return lines
[index
+1:]
131 fields
= line
.split(")", 1)
133 names
= [line
.strip() for line
in fields
[1].split(",")]
134 l
= fields
[0].split("(", 1)
136 args
= [line
.strip() for line
in l
[1].split(",")]
138 l
= fields
[0].split(None, 1)
141 names
= [line
.strip() for line
in l
[1].split(",")]
144 create_string
= 'var_%s(%s, "%s")' % (type, args
, name
)
145 new_member
= eval(create_string
)
146 self
.members
+= [new_member
]
148 raise BaseException("Parse error")
150 def emit_declaration(self
):
152 lines
+= ["struct %s\n {" % self
.struct_name
]
153 for m
in self
.members
:
154 lines
+= m
.emit_declaration()
155 lines
+= ["\tvoid pack(int flags)"]
157 lines
+= ["\t\tmsg_pack_start(%s, flags);" % self
.enum_name
]
158 for m
in self
.members
:
159 lines
+= m
.emit_pack()
160 lines
+= ["\t\tmsg_pack_end();"]
165 def emit_unpack(self
):
167 for m
in self
.members
:
168 lines
+= m
.emit_unpack()
169 for m
in self
.members
:
170 lines
+= m
.emit_unpack_check()
175 for m
in self
.members
:
176 lines
+= m
.emit_pack()
181 def __init__(self
, line
):
182 object.__init
__(self
, line
)
183 self
.enum_name
= "NETEVENTTYPE_%s" % self
.name
.upper()
184 self
.struct_name
= "NETEVENT_%s" % self
.name
.upper()
189 def parse(self
, lines
):
191 for index
in xrange(0, len(lines
)):
198 return lines
[index
+1:]
200 self
.raw_lines
+= [line
]
202 raise BaseException("Parse error")
215 lines
= [line
.split("//", 2)[0].strip() for line
in file(filename
).readlines()]
227 fields
= line
.split(None, 1)
231 if fields
[0] == "object":
232 new_obj
= object(line
)
233 lines
= new_obj
.parse(lines
)
234 p
.objects
+= [new_obj
]
235 elif fields
[0] == "message":
236 new_msg
= message(line
)
237 lines
= new_msg
.parse(lines
)
238 p
.messages
+= [new_msg
]
239 elif fields
[0] == "event":
240 new_obj
= event(line
)
241 lines
= new_obj
.parse(lines
)
242 p
.objects
+= [new_obj
]
243 elif fields
[0] == "raw_source":
245 lines
= raw
.parse(lines
)
246 p
.source_raw
+= raw
.raw_lines
247 elif fields
[0] == "raw_header":
249 lines
= raw
.parse(lines
)
250 p
.header_raw
+= raw
.raw_lines
252 print "error, strange line:", line
256 def emit_header_file(f
, p
):
257 for l
in p
.header_raw
:
260 if 1: # emit the enum table for objects
262 print >>f
, "\tNETOBJTYPE_INVALID=0,"
263 for obj
in p
.objects
:
264 print >>f
, "\t%s," % obj
.enum_name
265 print >>f
, "\tNUM_NETOBJTYPES"
269 if 1: # emit the enum table for messages
271 print >>f
, "\tNETMSGTYPE_INVALID=0,"
272 for msg
in p
.messages
:
273 print >>f
, "\t%s," % msg
.enum_name
274 print >>f
, "\tNUM_NETMSGTYPES"
278 print >>f
, "int netobj_secure(int type, void *data, int size);"
279 print >>f
, "const char *netobj_get_name(int type);"
280 print >>f
, "int netobj_num_corrections();"
281 print >>f
, "const char *netobj_corrected_on();"
283 print >>f
, "void *netmsg_secure_unpack(int type);"
284 print >>f
, "const char *netmsg_get_name(int type);"
285 print >>f
, "const char *netmsg_failed_on();"
288 for obj
in p
.objects
:
289 for l
in obj
.emit_declaration():
293 for msg
in p
.messages
:
294 for l
in msg
.emit_declaration():
298 def emit_source_file(f
, p
, protofilename
):
299 print >>f
, "#line 1 \"%s\"" % os
.path
.abspath(protofilename
).replace("\\", "\\\\")
301 for l
in p
.source_raw
:
304 print >>f
, "const char *msg_failed_on = \"\";"
305 print >>f
, "const char *obj_corrected_on = \"\";"
306 print >>f
, "static int num_corrections = 0;"
307 print >>f
, "int netobj_num_corrections() { return num_corrections; }"
308 print >>f
, "const char *netobj_corrected_on() { return obj_corrected_on; }"
309 print >>f
, "const char *netmsg_failed_on() { return msg_failed_on; }"
311 print >>f
, "static int netobj_clamp_int(const char *error_msg, int v, int min, int max)"
313 print >>f
, "\tif(v<min) { obj_corrected_on = error_msg; num_corrections++; return min; }"
314 print >>f
, "\tif(v>max) { obj_corrected_on = error_msg; num_corrections++; return max; }"
315 print >>f
, "\treturn v;"
320 print >>f
, "static const char *object_names[] = {"
321 print >>f
, "\t" + '"invalid",'
322 for obj
in p
.objects
:
323 print >>f
, '\t"%s",' % obj
.name
328 if 1: # secure functions
329 print >>f
, "static int secure_object_invalid(void *data, int size) { return 0; }"
330 for obj
in p
.objects
:
331 print >>f
, "static int secure_%s(void *data, int size)" % obj
.name
333 print >>f
, "\t%s *obj = (%s *)data;" % (obj
.struct_name
, obj
.struct_name
)
334 print >>f
, "\t(void)obj;" # to get rid of "unused variable" warning
335 print >>f
, "\tif(size != sizeof(%s)) return -1;" % obj
.struct_name
337 print >>f
, "\tif(secure_%s(data, sizeof(NETOBJ_%s)) != 0) return -1;" % (obj
.extends
, obj
.extends
.upper())
339 for l
in obj
.emit_secure():
341 print >>f
, "\treturn 0;";
345 if 1: # secure function table
346 print >>f
, "typedef int(*SECUREFUNC)(void *data, int size);"
347 print >>f
, "static SECUREFUNC secure_funcs[] = {"
348 print >>f
, "\t" + 'secure_object_invalid,'
349 for obj
in p
.objects
:
350 print >>f
, "\tsecure_%s," % obj
.name
351 print >>f
, "\t" + '0x0'
356 print >>f
, "int netobj_secure(int type, void *data, int size)"
358 print >>f
, "\tif(type < 0 || type >= NUM_NETOBJTYPES) return -1;"
359 print >>f
, "\treturn secure_funcs[type](data, size);"
364 print >>f
, "const char *netobj_get_name(int type)"
366 print >>f
, "\tif(type < 0 || type >= NUM_NETOBJTYPES) return \"(invalid)\";"
367 print >>f
, "\treturn object_names[type];"
372 print >>f
, "static const char *message_names[] = {"
373 print >>f
, "\t" + '"invalid",'
374 for msg
in p
.messages
:
375 print >>f
, '\t"%s",' % msg
.name
380 if 1: # secure functions
381 print >>f
, "static void *secure_unpack_invalid() { return 0; }"
382 for msg
in p
.messages
:
383 print >>f
, "static void *secure_unpack_%s()" % msg
.name
385 print >>f
, "\tstatic %s msg;" % msg
.struct_name
386 for l
in msg
.emit_unpack():
388 print >>f
, "\treturn &msg;";
392 if 1: # secure function table
393 print >>f
, "typedef void *(*SECUREUNPACKFUNC)();"
394 print >>f
, "static SECUREUNPACKFUNC secure_unpack_funcs[] = {"
395 print >>f
, "\t" + 'secure_unpack_invalid,'
396 for msg
in p
.messages
:
397 print >>f
, "\tsecure_unpack_%s," % msg
.name
398 print >>f
, "\t" + '0x0'
403 print >>f
, "void *netmsg_secure_unpack(int type)"
405 print >>f
, "\tvoid *msg;"
406 print >>f
, "\tmsg_failed_on = \"\";"
407 print >>f
, "\tif(type < 0 || type >= NUM_NETMSGTYPES) return 0;"
408 print >>f
, "\tmsg = secure_unpack_funcs[type]();"
409 print >>f
, "\tif(msg_unpack_error()) return 0;"
410 print >>f
, "\treturn msg;"
415 print >>f
, "const char *netmsg_get_name(int type)"
417 print >>f
, "\tif(type < 0 || type >= NUM_NETMSGTYPES) return \"(invalid)\";"
418 print >>f
, "\treturn message_names[type];"
422 if sys
.argv
[1] == "header":
423 p
= load(sys
.argv
[2])
424 emit_header_file(file(sys
.argv
[3], "w"), p
)
425 elif sys
.argv
[1] == "source":
426 p
= load(sys
.argv
[2])
427 emit_source_file(file(sys
.argv
[3], "w"), p
, sys
.argv
[2])
429 print "invalid command"