PageRenderTime 41ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 0ms

/ipc/chromium/src/third_party/libevent/event_rpcgen.py

https://bitbucket.org/marfey/releases-mozilla-central
Python | 1410 lines | 1345 code | 46 blank | 19 comment | 38 complexity | 5d92e4feddd880b3c8afcf1360bc9652 MD5 | raw file
Possible License(s): AGPL-1.0, MIT, LGPL-3.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD, LGPL-2.1
  1. #!/usr/bin/env python
  2. #
  3. # Copyright (c) 2005 Niels Provos <provos@citi.umich.edu>
  4. # All rights reserved.
  5. #
  6. # Generates marshaling code based on libevent.
  7. import sys
  8. import re
  9. #
  10. _NAME = "event_rpcgen.py"
  11. _VERSION = "0.1"
  12. _STRUCT_RE = '[a-z][a-z_0-9]*'
  13. # Globals
  14. line_count = 0
  15. white = re.compile(r'^\s+')
  16. cppcomment = re.compile(r'\/\/.*$')
  17. headerdirect = []
  18. cppdirect = []
  19. # Holds everything that makes a struct
  20. class Struct:
  21. def __init__(self, name):
  22. self._name = name
  23. self._entries = []
  24. self._tags = {}
  25. print >>sys.stderr, ' Created struct: %s' % name
  26. def AddEntry(self, entry):
  27. if self._tags.has_key(entry.Tag()):
  28. print >>sys.stderr, ( 'Entry "%s" duplicates tag number '
  29. '%d from "%s" around line %d' ) % (
  30. entry.Name(), entry.Tag(),
  31. self._tags[entry.Tag()], line_count)
  32. sys.exit(1)
  33. self._entries.append(entry)
  34. self._tags[entry.Tag()] = entry.Name()
  35. print >>sys.stderr, ' Added entry: %s' % entry.Name()
  36. def Name(self):
  37. return self._name
  38. def EntryTagName(self, entry):
  39. """Creates the name inside an enumeration for distinguishing data
  40. types."""
  41. name = "%s_%s" % (self._name, entry.Name())
  42. return name.upper()
  43. def PrintIdented(self, file, ident, code):
  44. """Takes an array, add indentation to each entry and prints it."""
  45. for entry in code:
  46. print >>file, '%s%s' % (ident, entry)
  47. def PrintTags(self, file):
  48. """Prints the tag definitions for a structure."""
  49. print >>file, '/* Tag definition for %s */' % self._name
  50. print >>file, 'enum %s_ {' % self._name.lower()
  51. for entry in self._entries:
  52. print >>file, ' %s=%d,' % (self.EntryTagName(entry),
  53. entry.Tag())
  54. print >>file, ' %s_MAX_TAGS' % (self._name.upper())
  55. print >>file, '};\n'
  56. def PrintForwardDeclaration(self, file):
  57. print >>file, 'struct %s;' % self._name
  58. def PrintDeclaration(self, file):
  59. print >>file, '/* Structure declaration for %s */' % self._name
  60. print >>file, 'struct %s_access_ {' % self._name
  61. for entry in self._entries:
  62. dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name())
  63. dcl.extend(
  64. entry.GetDeclaration('(*%s_get)' % entry.Name()))
  65. if entry.Array():
  66. dcl.extend(
  67. entry.AddDeclaration('(*%s_add)' % entry.Name()))
  68. self.PrintIdented(file, ' ', dcl)
  69. print >>file, '};\n'
  70. print >>file, 'struct %s {' % self._name
  71. print >>file, ' struct %s_access_ *base;\n' % self._name
  72. for entry in self._entries:
  73. dcl = entry.Declaration()
  74. self.PrintIdented(file, ' ', dcl)
  75. print >>file, ''
  76. for entry in self._entries:
  77. print >>file, ' uint8_t %s_set;' % entry.Name()
  78. print >>file, '};\n'
  79. print >>file, \
  80. """struct %(name)s *%(name)s_new(void);
  81. void %(name)s_free(struct %(name)s *);
  82. void %(name)s_clear(struct %(name)s *);
  83. void %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
  84. int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *);
  85. int %(name)s_complete(struct %(name)s *);
  86. void evtag_marshal_%(name)s(struct evbuffer *, uint32_t,
  87. const struct %(name)s *);
  88. int evtag_unmarshal_%(name)s(struct evbuffer *, uint32_t,
  89. struct %(name)s *);""" % { 'name' : self._name }
  90. # Write a setting function of every variable
  91. for entry in self._entries:
  92. self.PrintIdented(file, '', entry.AssignDeclaration(
  93. entry.AssignFuncName()))
  94. self.PrintIdented(file, '', entry.GetDeclaration(
  95. entry.GetFuncName()))
  96. if entry.Array():
  97. self.PrintIdented(file, '', entry.AddDeclaration(
  98. entry.AddFuncName()))
  99. print >>file, '/* --- %s done --- */\n' % self._name
  100. def PrintCode(self, file):
  101. print >>file, ('/*\n'
  102. ' * Implementation of %s\n'
  103. ' */\n') % self._name
  104. print >>file, \
  105. 'static struct %(name)s_access_ __%(name)s_base = {' % \
  106. { 'name' : self._name }
  107. for entry in self._entries:
  108. self.PrintIdented(file, ' ', entry.CodeBase())
  109. print >>file, '};\n'
  110. # Creation
  111. print >>file, (
  112. 'struct %(name)s *\n'
  113. '%(name)s_new(void)\n'
  114. '{\n'
  115. ' struct %(name)s *tmp;\n'
  116. ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n'
  117. ' event_warn("%%s: malloc", __func__);\n'
  118. ' return (NULL);\n'
  119. ' }\n'
  120. ' tmp->base = &__%(name)s_base;\n') % { 'name' : self._name }
  121. for entry in self._entries:
  122. self.PrintIdented(file, ' ', entry.CodeNew('tmp'))
  123. print >>file, ' tmp->%s_set = 0;\n' % entry.Name()
  124. print >>file, (
  125. ' return (tmp);\n'
  126. '}\n')
  127. # Adding
  128. for entry in self._entries:
  129. if entry.Array():
  130. self.PrintIdented(file, '', entry.CodeAdd())
  131. print >>file, ''
  132. # Assigning
  133. for entry in self._entries:
  134. self.PrintIdented(file, '', entry.CodeAssign())
  135. print >>file, ''
  136. # Getting
  137. for entry in self._entries:
  138. self.PrintIdented(file, '', entry.CodeGet())
  139. print >>file, ''
  140. # Clearing
  141. print >>file, ( 'void\n'
  142. '%(name)s_clear(struct %(name)s *tmp)\n'
  143. '{'
  144. ) % { 'name' : self._name }
  145. for entry in self._entries:
  146. self.PrintIdented(file, ' ', entry.CodeClear('tmp'))
  147. print >>file, '}\n'
  148. # Freeing
  149. print >>file, ( 'void\n'
  150. '%(name)s_free(struct %(name)s *tmp)\n'
  151. '{'
  152. ) % { 'name' : self._name }
  153. for entry in self._entries:
  154. self.PrintIdented(file, ' ', entry.CodeFree('tmp'))
  155. print >>file, (' free(tmp);\n'
  156. '}\n')
  157. # Marshaling
  158. print >>file, ('void\n'
  159. '%(name)s_marshal(struct evbuffer *evbuf, '
  160. 'const struct %(name)s *tmp)'
  161. '{') % { 'name' : self._name }
  162. for entry in self._entries:
  163. indent = ' '
  164. # Optional entries do not have to be set
  165. if entry.Optional():
  166. indent += ' '
  167. print >>file, ' if (tmp->%s_set) {' % entry.Name()
  168. self.PrintIdented(
  169. file, indent,
  170. entry.CodeMarshal('evbuf', self.EntryTagName(entry), 'tmp'))
  171. if entry.Optional():
  172. print >>file, ' }'
  173. print >>file, '}\n'
  174. # Unmarshaling
  175. print >>file, ('int\n'
  176. '%(name)s_unmarshal(struct %(name)s *tmp, '
  177. ' struct evbuffer *evbuf)\n'
  178. '{\n'
  179. ' uint32_t tag;\n'
  180. ' while (EVBUFFER_LENGTH(evbuf) > 0) {\n'
  181. ' if (evtag_peek(evbuf, &tag) == -1)\n'
  182. ' return (-1);\n'
  183. ' switch (tag) {\n'
  184. ) % { 'name' : self._name }
  185. for entry in self._entries:
  186. print >>file, ' case %s:\n' % self.EntryTagName(entry)
  187. if not entry.Array():
  188. print >>file, (
  189. ' if (tmp->%s_set)\n'
  190. ' return (-1);'
  191. ) % (entry.Name())
  192. self.PrintIdented(
  193. file, ' ',
  194. entry.CodeUnmarshal('evbuf',
  195. self.EntryTagName(entry), 'tmp'))
  196. print >>file, ( ' tmp->%s_set = 1;\n' % entry.Name() +
  197. ' break;\n' )
  198. print >>file, ( ' default:\n'
  199. ' return -1;\n'
  200. ' }\n'
  201. ' }\n' )
  202. # Check if it was decoded completely
  203. print >>file, ( ' if (%(name)s_complete(tmp) == -1)\n'
  204. ' return (-1);'
  205. ) % { 'name' : self._name }
  206. # Successfully decoded
  207. print >>file, ( ' return (0);\n'
  208. '}\n')
  209. # Checking if a structure has all the required data
  210. print >>file, (
  211. 'int\n'
  212. '%(name)s_complete(struct %(name)s *msg)\n'
  213. '{' ) % { 'name' : self._name }
  214. for entry in self._entries:
  215. self.PrintIdented(
  216. file, ' ',
  217. entry.CodeComplete('msg'))
  218. print >>file, (
  219. ' return (0);\n'
  220. '}\n' )
  221. # Complete message unmarshaling
  222. print >>file, (
  223. 'int\n'
  224. 'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, '
  225. 'uint32_t need_tag, struct %(name)s *msg)\n'
  226. '{\n'
  227. ' uint32_t tag;\n'
  228. ' int res = -1;\n'
  229. '\n'
  230. ' struct evbuffer *tmp = evbuffer_new();\n'
  231. '\n'
  232. ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1'
  233. ' || tag != need_tag)\n'
  234. ' goto error;\n'
  235. '\n'
  236. ' if (%(name)s_unmarshal(msg, tmp) == -1)\n'
  237. ' goto error;\n'
  238. '\n'
  239. ' res = 0;\n'
  240. '\n'
  241. ' error:\n'
  242. ' evbuffer_free(tmp);\n'
  243. ' return (res);\n'
  244. '}\n' ) % { 'name' : self._name }
  245. # Complete message marshaling
  246. print >>file, (
  247. 'void\n'
  248. 'evtag_marshal_%(name)s(struct evbuffer *evbuf, uint32_t tag, '
  249. 'const struct %(name)s *msg)\n'
  250. '{\n'
  251. ' struct evbuffer *_buf = evbuffer_new();\n'
  252. ' assert(_buf != NULL);\n'
  253. ' evbuffer_drain(_buf, -1);\n'
  254. ' %(name)s_marshal(_buf, msg);\n'
  255. ' evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), '
  256. 'EVBUFFER_LENGTH(_buf));\n'
  257. ' evbuffer_free(_buf);\n'
  258. '}\n' ) % { 'name' : self._name }
  259. class Entry:
  260. def __init__(self, type, name, tag):
  261. self._type = type
  262. self._name = name
  263. self._tag = int(tag)
  264. self._ctype = type
  265. self._optional = 0
  266. self._can_be_array = 0
  267. self._array = 0
  268. self._line_count = -1
  269. self._struct = None
  270. self._refname = None
  271. def GetTranslation(self):
  272. return { "parent_name" : self._struct.Name(),
  273. "name" : self._name,
  274. "ctype" : self._ctype,
  275. "refname" : self._refname
  276. }
  277. def SetStruct(self, struct):
  278. self._struct = struct
  279. def LineCount(self):
  280. assert self._line_count != -1
  281. return self._line_count
  282. def SetLineCount(self, number):
  283. self._line_count = number
  284. def Array(self):
  285. return self._array
  286. def Optional(self):
  287. return self._optional
  288. def Tag(self):
  289. return self._tag
  290. def Name(self):
  291. return self._name
  292. def Type(self):
  293. return self._type
  294. def MakeArray(self, yes=1):
  295. self._array = yes
  296. def MakeOptional(self):
  297. self._optional = 1
  298. def GetFuncName(self):
  299. return '%s_%s_get' % (self._struct.Name(), self._name)
  300. def GetDeclaration(self, funcname):
  301. code = [ 'int %s(struct %s *, %s *);' % (
  302. funcname, self._struct.Name(), self._ctype ) ]
  303. return code
  304. def CodeGet(self):
  305. code = (
  306. 'int',
  307. '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, '
  308. '%(ctype)s *value)',
  309. '{',
  310. ' if (msg->%(name)s_set != 1)',
  311. ' return (-1);',
  312. ' *value = msg->%(name)s_data;',
  313. ' return (0);',
  314. '}' )
  315. code = '\n'.join(code)
  316. code = code % self.GetTranslation()
  317. return code.split('\n')
  318. def AssignFuncName(self):
  319. return '%s_%s_assign' % (self._struct.Name(), self._name)
  320. def AddFuncName(self):
  321. return '%s_%s_add' % (self._struct.Name(), self._name)
  322. def AssignDeclaration(self, funcname):
  323. code = [ 'int %s(struct %s *, const %s);' % (
  324. funcname, self._struct.Name(), self._ctype ) ]
  325. return code
  326. def CodeAssign(self):
  327. code = [ 'int',
  328. '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,'
  329. ' const %(ctype)s value)',
  330. '{',
  331. ' msg->%(name)s_set = 1;',
  332. ' msg->%(name)s_data = value;',
  333. ' return (0);',
  334. '}' ]
  335. code = '\n'.join(code)
  336. code = code % self.GetTranslation()
  337. return code.split('\n')
  338. def CodeClear(self, structname):
  339. code = [ '%s->%s_set = 0;' % (structname, self.Name()) ]
  340. return code
  341. def CodeComplete(self, structname):
  342. if self.Optional():
  343. return []
  344. code = [ 'if (!%s->%s_set)' % (structname, self.Name()),
  345. ' return (-1);' ]
  346. return code
  347. def CodeFree(self, name):
  348. return []
  349. def CodeBase(self):
  350. code = [
  351. '%(parent_name)s_%(name)s_assign,',
  352. '%(parent_name)s_%(name)s_get,'
  353. ]
  354. if self.Array():
  355. code.append('%(parent_name)s_%(name)s_add,')
  356. code = '\n'.join(code)
  357. code = code % self.GetTranslation()
  358. return code.split('\n')
  359. def Verify(self):
  360. if self.Array() and not self._can_be_array:
  361. print >>sys.stderr, (
  362. 'Entry "%s" cannot be created as an array '
  363. 'around line %d' ) % (self._name, self.LineCount())
  364. sys.exit(1)
  365. if not self._struct:
  366. print >>sys.stderr, (
  367. 'Entry "%s" does not know which struct it belongs to '
  368. 'around line %d' ) % (self._name, self.LineCount())
  369. sys.exit(1)
  370. if self._optional and self._array:
  371. print >>sys.stderr, ( 'Entry "%s" has illegal combination of '
  372. 'optional and array around line %d' ) % (
  373. self._name, self.LineCount() )
  374. sys.exit(1)
  375. class EntryBytes(Entry):
  376. def __init__(self, type, name, tag, length):
  377. # Init base class
  378. Entry.__init__(self, type, name, tag)
  379. self._length = length
  380. self._ctype = 'uint8_t'
  381. def GetDeclaration(self, funcname):
  382. code = [ 'int %s(struct %s *, %s **);' % (
  383. funcname, self._struct.Name(), self._ctype ) ]
  384. return code
  385. def AssignDeclaration(self, funcname):
  386. code = [ 'int %s(struct %s *, const %s *);' % (
  387. funcname, self._struct.Name(), self._ctype ) ]
  388. return code
  389. def Declaration(self):
  390. dcl = ['uint8_t %s_data[%s];' % (self._name, self._length)]
  391. return dcl
  392. def CodeGet(self):
  393. name = self._name
  394. code = [ 'int',
  395. '%s_%s_get(struct %s *msg, %s **value)' % (
  396. self._struct.Name(), name,
  397. self._struct.Name(), self._ctype),
  398. '{',
  399. ' if (msg->%s_set != 1)' % name,
  400. ' return (-1);',
  401. ' *value = msg->%s_data;' % name,
  402. ' return (0);',
  403. '}' ]
  404. return code
  405. def CodeAssign(self):
  406. name = self._name
  407. code = [ 'int',
  408. '%s_%s_assign(struct %s *msg, const %s *value)' % (
  409. self._struct.Name(), name,
  410. self._struct.Name(), self._ctype),
  411. '{',
  412. ' msg->%s_set = 1;' % name,
  413. ' memcpy(msg->%s_data, value, %s);' % (
  414. name, self._length),
  415. ' return (0);',
  416. '}' ]
  417. return code
  418. def CodeUnmarshal(self, buf, tag_name, var_name):
  419. code = [ 'if (evtag_unmarshal_fixed(%s, %s, ' % (buf, tag_name) +
  420. '%s->%s_data, ' % (var_name, self._name) +
  421. 'sizeof(%s->%s_data)) == -1) {' % (
  422. var_name, self._name),
  423. ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
  424. self._name ),
  425. ' return (-1);',
  426. '}'
  427. ]
  428. return code
  429. def CodeMarshal(self, buf, tag_name, var_name):
  430. code = ['evtag_marshal(%s, %s, %s->%s_data, sizeof(%s->%s_data));' % (
  431. buf, tag_name, var_name, self._name, var_name, self._name )]
  432. return code
  433. def CodeClear(self, structname):
  434. code = [ '%s->%s_set = 0;' % (structname, self.Name()),
  435. 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
  436. structname, self._name, structname, self._name)]
  437. return code
  438. def CodeNew(self, name):
  439. code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
  440. name, self._name, name, self._name)]
  441. return code
  442. def Verify(self):
  443. if not self._length:
  444. print >>sys.stderr, 'Entry "%s" needs a length around line %d' % (
  445. self._name, self.LineCount() )
  446. sys.exit(1)
  447. Entry.Verify(self)
  448. class EntryInt(Entry):
  449. def __init__(self, type, name, tag):
  450. # Init base class
  451. Entry.__init__(self, type, name, tag)
  452. self._ctype = 'uint32_t'
  453. def CodeUnmarshal(self, buf, tag_name, var_name):
  454. code = ['if (evtag_unmarshal_int(%s, %s, &%s->%s_data) == -1) {' % (
  455. buf, tag_name, var_name, self._name),
  456. ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
  457. self._name ),
  458. ' return (-1);',
  459. '}' ]
  460. return code
  461. def CodeMarshal(self, buf, tag_name, var_name):
  462. code = ['evtag_marshal_int(%s, %s, %s->%s_data);' % (
  463. buf, tag_name, var_name, self._name)]
  464. return code
  465. def Declaration(self):
  466. dcl = ['uint32_t %s_data;' % self._name]
  467. return dcl
  468. def CodeNew(self, name):
  469. code = ['%s->%s_data = 0;' % (name, self._name)]
  470. return code
  471. class EntryString(Entry):
  472. def __init__(self, type, name, tag):
  473. # Init base class
  474. Entry.__init__(self, type, name, tag)
  475. self._ctype = 'char *'
  476. def CodeAssign(self):
  477. name = self._name
  478. code = """int
  479. %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
  480. const %(ctype)s value)
  481. {
  482. if (msg->%(name)s_data != NULL)
  483. free(msg->%(name)s_data);
  484. if ((msg->%(name)s_data = strdup(value)) == NULL)
  485. return (-1);
  486. msg->%(name)s_set = 1;
  487. return (0);
  488. }""" % self.GetTranslation()
  489. return code.split('\n')
  490. def CodeUnmarshal(self, buf, tag_name, var_name):
  491. code = ['if (evtag_unmarshal_string(%s, %s, &%s->%s_data) == -1) {' % (
  492. buf, tag_name, var_name, self._name),
  493. ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
  494. self._name ),
  495. ' return (-1);',
  496. '}'
  497. ]
  498. return code
  499. def CodeMarshal(self, buf, tag_name, var_name):
  500. code = ['evtag_marshal_string(%s, %s, %s->%s_data);' % (
  501. buf, tag_name, var_name, self._name)]
  502. return code
  503. def CodeClear(self, structname):
  504. code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
  505. ' free (%s->%s_data);' % (structname, self.Name()),
  506. ' %s->%s_data = NULL;' % (structname, self.Name()),
  507. ' %s->%s_set = 0;' % (structname, self.Name()),
  508. '}'
  509. ]
  510. return code
  511. def CodeNew(self, name):
  512. code = ['%s->%s_data = NULL;' % (name, self._name)]
  513. return code
  514. def CodeFree(self, name):
  515. code = ['if (%s->%s_data != NULL)' % (name, self._name),
  516. ' free (%s->%s_data); ' % (name, self._name)]
  517. return code
  518. def Declaration(self):
  519. dcl = ['char *%s_data;' % self._name]
  520. return dcl
  521. class EntryStruct(Entry):
  522. def __init__(self, type, name, tag, refname):
  523. # Init base class
  524. Entry.__init__(self, type, name, tag)
  525. self._can_be_array = 1
  526. self._refname = refname
  527. self._ctype = 'struct %s*' % refname
  528. def CodeGet(self):
  529. name = self._name
  530. code = [ 'int',
  531. '%s_%s_get(struct %s *msg, %s *value)' % (
  532. self._struct.Name(), name,
  533. self._struct.Name(), self._ctype),
  534. '{',
  535. ' if (msg->%s_set != 1) {' % name,
  536. ' msg->%s_data = %s_new();' % (name, self._refname),
  537. ' if (msg->%s_data == NULL)' % name,
  538. ' return (-1);',
  539. ' msg->%s_set = 1;' % name,
  540. ' }',
  541. ' *value = msg->%s_data;' % name,
  542. ' return (0);',
  543. '}' ]
  544. return code
  545. def CodeAssign(self):
  546. name = self._name
  547. code = """int
  548. %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
  549. const %(ctype)s value)
  550. {
  551. struct evbuffer *tmp = NULL;
  552. if (msg->%(name)s_set) {
  553. %(refname)s_clear(msg->%(name)s_data);
  554. msg->%(name)s_set = 0;
  555. } else {
  556. msg->%(name)s_data = %(refname)s_new();
  557. if (msg->%(name)s_data == NULL) {
  558. event_warn("%%s: %(refname)s_new()", __func__);
  559. goto error;
  560. }
  561. }
  562. if ((tmp = evbuffer_new()) == NULL) {
  563. event_warn("%%s: evbuffer_new()", __func__);
  564. goto error;
  565. }
  566. %(refname)s_marshal(tmp, value);
  567. if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) {
  568. event_warnx("%%s: %(refname)s_unmarshal", __func__);
  569. goto error;
  570. }
  571. msg->%(name)s_set = 1;
  572. evbuffer_free(tmp);
  573. return (0);
  574. error:
  575. if (tmp != NULL)
  576. evbuffer_free(tmp);
  577. if (msg->%(name)s_data != NULL) {
  578. %(refname)s_free(msg->%(name)s_data);
  579. msg->%(name)s_data = NULL;
  580. }
  581. return (-1);
  582. }""" % self.GetTranslation()
  583. return code.split('\n')
  584. def CodeComplete(self, structname):
  585. if self.Optional():
  586. code = [ 'if (%s->%s_set && %s_complete(%s->%s_data) == -1)' % (
  587. structname, self.Name(),
  588. self._refname, structname, self.Name()),
  589. ' return (-1);' ]
  590. else:
  591. code = [ 'if (%s_complete(%s->%s_data) == -1)' % (
  592. self._refname, structname, self.Name()),
  593. ' return (-1);' ]
  594. return code
  595. def CodeUnmarshal(self, buf, tag_name, var_name):
  596. code = ['%s->%s_data = %s_new();' % (
  597. var_name, self._name, self._refname),
  598. 'if (%s->%s_data == NULL)' % (var_name, self._name),
  599. ' return (-1);',
  600. 'if (evtag_unmarshal_%s(%s, %s, %s->%s_data) == -1) {' % (
  601. self._refname, buf, tag_name, var_name, self._name),
  602. ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
  603. self._name ),
  604. ' return (-1);',
  605. '}'
  606. ]
  607. return code
  608. def CodeMarshal(self, buf, tag_name, var_name):
  609. code = ['evtag_marshal_%s(%s, %s, %s->%s_data);' % (
  610. self._refname, buf, tag_name, var_name, self._name)]
  611. return code
  612. def CodeClear(self, structname):
  613. code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
  614. ' %s_free(%s->%s_data);' % (
  615. self._refname, structname, self.Name()),
  616. ' %s->%s_data = NULL;' % (structname, self.Name()),
  617. ' %s->%s_set = 0;' % (structname, self.Name()),
  618. '}'
  619. ]
  620. return code
  621. def CodeNew(self, name):
  622. code = ['%s->%s_data = NULL;' % (name, self._name)]
  623. return code
  624. def CodeFree(self, name):
  625. code = ['if (%s->%s_data != NULL)' % (name, self._name),
  626. ' %s_free(%s->%s_data); ' % (
  627. self._refname, name, self._name)]
  628. return code
  629. def Declaration(self):
  630. dcl = ['%s %s_data;' % (self._ctype, self._name)]
  631. return dcl
  632. class EntryVarBytes(Entry):
  633. def __init__(self, type, name, tag):
  634. # Init base class
  635. Entry.__init__(self, type, name, tag)
  636. self._ctype = 'uint8_t *'
  637. def GetDeclaration(self, funcname):
  638. code = [ 'int %s(struct %s *, %s *, uint32_t *);' % (
  639. funcname, self._struct.Name(), self._ctype ) ]
  640. return code
  641. def AssignDeclaration(self, funcname):
  642. code = [ 'int %s(struct %s *, const %s, uint32_t);' % (
  643. funcname, self._struct.Name(), self._ctype ) ]
  644. return code
  645. def CodeAssign(self):
  646. name = self._name
  647. code = [ 'int',
  648. '%s_%s_assign(struct %s *msg, '
  649. 'const %s value, uint32_t len)' % (
  650. self._struct.Name(), name,
  651. self._struct.Name(), self._ctype),
  652. '{',
  653. ' if (msg->%s_data != NULL)' % name,
  654. ' free (msg->%s_data);' % name,
  655. ' msg->%s_data = malloc(len);' % name,
  656. ' if (msg->%s_data == NULL)' % name,
  657. ' return (-1);',
  658. ' msg->%s_set = 1;' % name,
  659. ' msg->%s_length = len;' % name,
  660. ' memcpy(msg->%s_data, value, len);' % name,
  661. ' return (0);',
  662. '}' ]
  663. return code
  664. def CodeGet(self):
  665. name = self._name
  666. code = [ 'int',
  667. '%s_%s_get(struct %s *msg, %s *value, uint32_t *plen)' % (
  668. self._struct.Name(), name,
  669. self._struct.Name(), self._ctype),
  670. '{',
  671. ' if (msg->%s_set != 1)' % name,
  672. ' return (-1);',
  673. ' *value = msg->%s_data;' % name,
  674. ' *plen = msg->%s_length;' % name,
  675. ' return (0);',
  676. '}' ]
  677. return code
  678. def CodeUnmarshal(self, buf, tag_name, var_name):
  679. code = ['if (evtag_payload_length(%s, &%s->%s_length) == -1)' % (
  680. buf, var_name, self._name),
  681. ' return (-1);',
  682. # We do not want DoS opportunities
  683. 'if (%s->%s_length > EVBUFFER_LENGTH(%s))' % (
  684. var_name, self._name, buf),
  685. ' return (-1);',
  686. 'if ((%s->%s_data = malloc(%s->%s_length)) == NULL)' % (
  687. var_name, self._name, var_name, self._name),
  688. ' return (-1);',
  689. 'if (evtag_unmarshal_fixed(%s, %s, %s->%s_data, '
  690. '%s->%s_length) == -1) {' % (
  691. buf, tag_name, var_name, self._name, var_name, self._name),
  692. ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
  693. self._name ),
  694. ' return (-1);',
  695. '}'
  696. ]
  697. return code
  698. def CodeMarshal(self, buf, tag_name, var_name):
  699. code = ['evtag_marshal(%s, %s, %s->%s_data, %s->%s_length);' % (
  700. buf, tag_name, var_name, self._name, var_name, self._name)]
  701. return code
  702. def CodeClear(self, structname):
  703. code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
  704. ' free (%s->%s_data);' % (structname, self.Name()),
  705. ' %s->%s_data = NULL;' % (structname, self.Name()),
  706. ' %s->%s_length = 0;' % (structname, self.Name()),
  707. ' %s->%s_set = 0;' % (structname, self.Name()),
  708. '}'
  709. ]
  710. return code
  711. def CodeNew(self, name):
  712. code = ['%s->%s_data = NULL;' % (name, self._name),
  713. '%s->%s_length = 0;' % (name, self._name) ]
  714. return code
  715. def CodeFree(self, name):
  716. code = ['if (%s->%s_data != NULL)' % (name, self._name),
  717. ' free (%s->%s_data); ' % (name, self._name)]
  718. return code
  719. def Declaration(self):
  720. dcl = ['uint8_t *%s_data;' % self._name,
  721. 'uint32_t %s_length;' % self._name]
  722. return dcl
  723. class EntryArray(Entry):
  724. def __init__(self, entry):
  725. # Init base class
  726. Entry.__init__(self, entry._type, entry._name, entry._tag)
  727. self._entry = entry
  728. self._refname = entry._refname
  729. self._ctype = 'struct %s *' % self._refname
  730. def GetDeclaration(self, funcname):
  731. """Allows direct access to elements of the array."""
  732. translate = self.GetTranslation()
  733. translate["funcname"] = funcname
  734. code = [
  735. 'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' %
  736. translate ]
  737. return code
  738. def AssignDeclaration(self, funcname):
  739. code = [ 'int %s(struct %s *, int, const %s);' % (
  740. funcname, self._struct.Name(), self._ctype ) ]
  741. return code
  742. def AddDeclaration(self, funcname):
  743. code = [ '%s %s(struct %s *);' % (
  744. self._ctype, funcname, self._struct.Name() ) ]
  745. return code
  746. def CodeGet(self):
  747. code = """int
  748. %(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset,
  749. %(ctype)s *value)
  750. {
  751. if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length)
  752. return (-1);
  753. *value = msg->%(name)s_data[offset];
  754. return (0);
  755. }""" % self.GetTranslation()
  756. return code.split('\n')
  757. def CodeAssign(self):
  758. code = """int
  759. %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,
  760. const %(ctype)s value)
  761. {
  762. struct evbuffer *tmp = NULL;
  763. if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)
  764. return (-1);
  765. %(refname)s_clear(msg->%(name)s_data[off]);
  766. if ((tmp = evbuffer_new()) == NULL) {
  767. event_warn("%%s: evbuffer_new()", __func__);
  768. goto error;
  769. }
  770. %(refname)s_marshal(tmp, value);
  771. if (%(refname)s_unmarshal(msg->%(name)s_data[off], tmp) == -1) {
  772. event_warnx("%%s: %(refname)s_unmarshal", __func__);
  773. goto error;
  774. }
  775. evbuffer_free(tmp);
  776. return (0);
  777. error:
  778. if (tmp != NULL)
  779. evbuffer_free(tmp);
  780. %(refname)s_clear(msg->%(name)s_data[off]);
  781. return (-1);
  782. }""" % self.GetTranslation()
  783. return code.split('\n')
  784. def CodeAdd(self):
  785. code = \
  786. """%(ctype)s
  787. %(parent_name)s_%(name)s_add(struct %(parent_name)s *msg)
  788. {
  789. if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {
  790. int tobe_allocated = msg->%(name)s_num_allocated;
  791. %(ctype)s* new_data = NULL;
  792. tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;
  793. new_data = (%(ctype)s*) realloc(msg->%(name)s_data,
  794. tobe_allocated * sizeof(%(ctype)s));
  795. if (new_data == NULL)
  796. goto error;
  797. msg->%(name)s_data = new_data;
  798. msg->%(name)s_num_allocated = tobe_allocated;
  799. }
  800. msg->%(name)s_data[msg->%(name)s_length - 1] = %(refname)s_new();
  801. if (msg->%(name)s_data[msg->%(name)s_length - 1] == NULL)
  802. goto error;
  803. msg->%(name)s_set = 1;
  804. return (msg->%(name)s_data[msg->%(name)s_length - 1]);
  805. error:
  806. --msg->%(name)s_length;
  807. return (NULL);
  808. }
  809. """ % self.GetTranslation()
  810. return code.split('\n')
  811. def CodeComplete(self, structname):
  812. code = []
  813. translate = self.GetTranslation()
  814. if self.Optional():
  815. code.append( 'if (%(structname)s->%(name)s_set)' % translate)
  816. translate["structname"] = structname
  817. tmp = """{
  818. int i;
  819. for (i = 0; i < %(structname)s->%(name)s_length; ++i) {
  820. if (%(refname)s_complete(%(structname)s->%(name)s_data[i]) == -1)
  821. return (-1);
  822. }
  823. }""" % translate
  824. code.extend(tmp.split('\n'))
  825. return code
  826. def CodeUnmarshal(self, buf, tag_name, var_name):
  827. translate = self.GetTranslation()
  828. translate["var_name"] = var_name
  829. translate["buf"] = buf
  830. translate["tag_name"] = tag_name
  831. code = """if (%(parent_name)s_%(name)s_add(%(var_name)s) == NULL)
  832. return (-1);
  833. if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag_name)s,
  834. %(var_name)s->%(name)s_data[%(var_name)s->%(name)s_length - 1]) == -1) {
  835. --%(var_name)s->%(name)s_length;
  836. event_warnx("%%s: failed to unmarshal %(name)s", __func__);
  837. return (-1);
  838. }""" % translate
  839. return code.split('\n')
  840. def CodeMarshal(self, buf, tag_name, var_name):
  841. code = ['{',
  842. ' int i;',
  843. ' for (i = 0; i < %s->%s_length; ++i) {' % (
  844. var_name, self._name),
  845. ' evtag_marshal_%s(%s, %s, %s->%s_data[i]);' % (
  846. self._refname, buf, tag_name, var_name, self._name),
  847. ' }',
  848. '}'
  849. ]
  850. return code
  851. def CodeClear(self, structname):
  852. code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
  853. ' int i;',
  854. ' for (i = 0; i < %s->%s_length; ++i) {' % (
  855. structname, self.Name()),
  856. ' %s_free(%s->%s_data[i]);' % (
  857. self._refname, structname, self.Name()),
  858. ' }',
  859. ' free(%s->%s_data);' % (structname, self.Name()),
  860. ' %s->%s_data = NULL;' % (structname, self.Name()),
  861. ' %s->%s_set = 0;' % (structname, self.Name()),
  862. ' %s->%s_length = 0;' % (structname, self.Name()),
  863. ' %s->%s_num_allocated = 0;' % (structname, self.Name()),
  864. '}'
  865. ]
  866. return code
  867. def CodeNew(self, name):
  868. code = ['%s->%s_data = NULL;' % (name, self._name),
  869. '%s->%s_length = 0;' % (name, self._name),
  870. '%s->%s_num_allocated = 0;' % (name, self._name)]
  871. return code
  872. def CodeFree(self, name):
  873. code = ['if (%s->%s_data != NULL) {' % (name, self._name),
  874. ' int i;',
  875. ' for (i = 0; i < %s->%s_length; ++i) {' % (
  876. name, self._name),
  877. ' %s_free(%s->%s_data[i]); ' % (
  878. self._refname, name, self._name),
  879. ' %s->%s_data[i] = NULL;' % (name, self._name),
  880. ' }',
  881. ' free(%s->%s_data);' % (name, self._name),
  882. ' %s->%s_data = NULL;' % (name, self._name),
  883. ' %s->%s_length = 0;' % (name, self._name),
  884. ' %s->%s_num_allocated = 0;' % (name, self._name),
  885. '}'
  886. ]
  887. return code
  888. def Declaration(self):
  889. dcl = ['struct %s **%s_data;' % (self._refname, self._name),
  890. 'int %s_length;' % self._name,
  891. 'int %s_num_allocated;' % self._name ]
  892. return dcl
  893. def NormalizeLine(line):
  894. global white
  895. global cppcomment
  896. line = cppcomment.sub('', line)
  897. line = line.strip()
  898. line = white.sub(' ', line)
  899. return line
  900. def ProcessOneEntry(newstruct, entry):
  901. optional = 0
  902. array = 0
  903. entry_type = ''
  904. name = ''
  905. tag = ''
  906. tag_set = None
  907. separator = ''
  908. fixed_length = ''
  909. tokens = entry.split(' ')
  910. while tokens:
  911. token = tokens[0]
  912. tokens = tokens[1:]
  913. if not entry_type:
  914. if not optional and token == 'optional':
  915. optional = 1
  916. continue
  917. if not array and token == 'array':
  918. array = 1
  919. continue
  920. if not entry_type:
  921. entry_type = token
  922. continue
  923. if not name:
  924. res = re.match(r'^([^\[\]]+)(\[.*\])?$', token)
  925. if not res:
  926. print >>sys.stderr, 'Cannot parse name: \"%s\" around %d' % (
  927. entry, line_count)
  928. sys.exit(1)
  929. name = res.group(1)
  930. fixed_length = res.group(2)
  931. if fixed_length:
  932. fixed_length = fixed_length[1:-1]
  933. continue
  934. if not separator:
  935. separator = token
  936. if separator != '=':
  937. print >>sys.stderr, 'Expected "=" after name \"%s\" got %s' % (
  938. name, token)
  939. sys.exit(1)
  940. continue
  941. if not tag_set:
  942. tag_set = 1
  943. if not re.match(r'^(0x)?[0-9]+$', token):
  944. print >>sys.stderr, 'Expected tag number: \"%s\"' % entry
  945. sys.exit(1)
  946. tag = int(token, 0)
  947. continue
  948. print >>sys.stderr, 'Cannot parse \"%s\"' % entry
  949. sys.exit(1)
  950. if not tag_set:
  951. print >>sys.stderr, 'Need tag number: \"%s\"' % entry
  952. sys.exit(1)
  953. # Create the right entry
  954. if entry_type == 'bytes':
  955. if fixed_length:
  956. newentry = EntryBytes(entry_type, name, tag, fixed_length)
  957. else:
  958. newentry = EntryVarBytes(entry_type, name, tag)
  959. elif entry_type == 'int' and not fixed_length:
  960. newentry = EntryInt(entry_type, name, tag)
  961. elif entry_type == 'string' and not fixed_length:
  962. newentry = EntryString(entry_type, name, tag)
  963. else:
  964. res = re.match(r'^struct\[(%s)\]$' % _STRUCT_RE,
  965. entry_type, re.IGNORECASE)
  966. if res:
  967. # References another struct defined in our file
  968. newentry = EntryStruct(entry_type, name, tag, res.group(1))
  969. else:
  970. print >>sys.stderr, 'Bad type: "%s" in "%s"' % (entry_type, entry)
  971. sys.exit(1)
  972. structs = []
  973. if optional:
  974. newentry.MakeOptional()
  975. if array:
  976. newentry.MakeArray()
  977. newentry.SetStruct(newstruct)
  978. newentry.SetLineCount(line_count)
  979. newentry.Verify()
  980. if array:
  981. # We need to encapsulate this entry into a struct
  982. newname = newentry.Name()+ '_array'
  983. # Now borgify the new entry.
  984. newentry = EntryArray(newentry)
  985. newentry.SetStruct(newstruct)
  986. newentry.SetLineCount(line_count)
  987. newentry.MakeArray()
  988. newstruct.AddEntry(newentry)
  989. return structs
  990. def ProcessStruct(data):
  991. tokens = data.split(' ')
  992. # First three tokens are: 'struct' 'name' '{'
  993. newstruct = Struct(tokens[1])
  994. inside = ' '.join(tokens[3:-1])
  995. tokens = inside.split(';')
  996. structs = []
  997. for entry in tokens:
  998. entry = NormalizeLine(entry)
  999. if not entry:
  1000. continue
  1001. # It's possible that new structs get defined in here
  1002. structs.extend(ProcessOneEntry(newstruct, entry))
  1003. structs.append(newstruct)
  1004. return structs
  1005. def GetNextStruct(file):
  1006. global line_count
  1007. global cppdirect
  1008. got_struct = 0
  1009. processed_lines = []
  1010. have_c_comment = 0
  1011. data = ''
  1012. while 1:
  1013. line = file.readline()
  1014. if not line:
  1015. break
  1016. line_count += 1
  1017. line = line[:-1]
  1018. if not have_c_comment and re.search(r'/\*', line):
  1019. if re.search(r'/\*.*\*/', line):
  1020. line = re.sub(r'/\*.*\*/', '', line)
  1021. else:
  1022. line = re.sub(r'/\*.*$', '', line)
  1023. have_c_comment = 1
  1024. if have_c_comment:
  1025. if not re.search(r'\*/', line):
  1026. continue
  1027. have_c_comment = 0
  1028. line = re.sub(r'^.*\*/', '', line)
  1029. line = NormalizeLine(line)
  1030. if not line:
  1031. continue
  1032. if not got_struct:
  1033. if re.match(r'#include ["<].*[>"]', line):
  1034. cppdirect.append(line)
  1035. continue
  1036. if re.match(r'^#(if( |def)|endif)', line):
  1037. cppdirect.append(line)
  1038. continue
  1039. if re.match(r'^#define', line):
  1040. headerdirect.append(line)
  1041. continue
  1042. if not re.match(r'^struct %s {$' % _STRUCT_RE,
  1043. line, re.IGNORECASE):
  1044. print >>sys.stderr, 'Missing struct on line %d: %s' % (
  1045. line_count, line)
  1046. sys.exit(1)
  1047. else:
  1048. got_struct = 1
  1049. data += line
  1050. continue
  1051. # We are inside the struct
  1052. tokens = line.split('}')
  1053. if len(tokens) == 1:
  1054. data += ' ' + line
  1055. continue
  1056. if len(tokens[1]):
  1057. print >>sys.stderr, 'Trailing garbage after struct on line %d' % (
  1058. line_count )
  1059. sys.exit(1)
  1060. # We found the end of the struct
  1061. data += ' %s}' % tokens[0]
  1062. break
  1063. # Remove any comments, that might be in there
  1064. data = re.sub(r'/\*.*\*/', '', data)
  1065. return data
  1066. def Parse(file):
  1067. """
  1068. Parses the input file and returns C code and corresponding header file.
  1069. """
  1070. entities = []
  1071. while 1:
  1072. # Just gets the whole struct nicely formatted
  1073. data = GetNextStruct(file)
  1074. if not data:
  1075. break
  1076. entities.extend(ProcessStruct(data))
  1077. return entities
  1078. def GuardName(name):
  1079. name = '_'.join(name.split('.'))
  1080. name = '_'.join(name.split('/'))
  1081. guard = '_'+name.upper()+'_'
  1082. return guard
  1083. def HeaderPreamble(name):
  1084. guard = GuardName(name)
  1085. pre = (
  1086. '/*\n'
  1087. ' * Automatically generated from %s\n'
  1088. ' */\n\n'
  1089. '#ifndef %s\n'
  1090. '#define %s\n\n' ) % (
  1091. name, guard, guard)
  1092. # insert stdint.h - let's hope everyone has it
  1093. pre += (
  1094. '#include <event-config.h>\n'
  1095. '#ifdef _EVENT_HAVE_STDINT_H\n'
  1096. '#include <stdint.h>\n'
  1097. '#endif\n' )
  1098. for statement in headerdirect:
  1099. pre += '%s\n' % statement
  1100. if headerdirect:
  1101. pre += '\n'
  1102. pre += (
  1103. '#define EVTAG_HAS(msg, member) ((msg)->member##_set == 1)\n'
  1104. '#define EVTAG_ASSIGN(msg, member, args...) '
  1105. '(*(msg)->base->member##_assign)(msg, ## args)\n'
  1106. '#define EVTAG_GET(msg, member, args...) '
  1107. '(*(msg)->base->member##_get)(msg, ## args)\n'
  1108. '#define EVTAG_ADD(msg, member) (*(msg)->base->member##_add)(msg)\n'
  1109. '#define EVTAG_LEN(msg, member) ((msg)->member##_length)\n'
  1110. )
  1111. return pre
  1112. def HeaderPostamble(name):
  1113. guard = GuardName(name)
  1114. return '#endif /* %s */' % guard
  1115. def BodyPreamble(name):
  1116. global _NAME
  1117. global _VERSION
  1118. header_file = '.'.join(name.split('.')[:-1]) + '.gen.h'
  1119. pre = ( '/*\n'
  1120. ' * Automatically generated from %s\n'
  1121. ' * by %s/%s. DO NOT EDIT THIS FILE.\n'
  1122. ' */\n\n' ) % (name, _NAME, _VERSION)
  1123. pre += ( '#include <sys/types.h>\n'
  1124. '#include <sys/time.h>\n'
  1125. '#include <stdlib.h>\n'
  1126. '#include <string.h>\n'
  1127. '#include <assert.h>\n'
  1128. '#include <event.h>\n\n' )
  1129. for statement in cppdirect:
  1130. pre += '%s\n' % statement
  1131. pre += '\n#include "%s"\n\n' % header_file
  1132. pre += 'void event_err(int eval, const char *fmt, ...);\n'
  1133. pre += 'void event_warn(const char *fmt, ...);\n'
  1134. pre += 'void event_errx(int eval, const char *fmt, ...);\n'
  1135. pre += 'void event_warnx(const char *fmt, ...);\n\n'
  1136. return pre
  1137. def main(argv):
  1138. if len(argv) < 2 or not argv[1]:
  1139. print >>sys.stderr, 'Need RPC description file as first argument.'
  1140. sys.exit(1)
  1141. filename = argv[1]
  1142. ext = filename.split('.')[-1]
  1143. if ext != 'rpc':
  1144. print >>sys.stderr, 'Unrecognized file extension: %s' % ext
  1145. sys.exit(1)
  1146. print >>sys.stderr, 'Reading \"%s\"' % filename
  1147. fp = open(filename, 'r')
  1148. entities = Parse(fp)
  1149. fp.close()
  1150. header_file = '.'.join(filename.split('.')[:-1]) + '.gen.h'
  1151. impl_file = '.'.join(filename.split('.')[:-1]) + '.gen.c'
  1152. print >>sys.stderr, '... creating "%s"' % header_file
  1153. header_fp = open(header_file, 'w')
  1154. print >>header_fp, HeaderPreamble(filename)
  1155. # Create forward declarations: allows other structs to reference
  1156. # each other
  1157. for entry in entities:
  1158. entry.PrintForwardDeclaration(header_fp)
  1159. print >>header_fp, ''
  1160. for entry in entities:
  1161. entry.PrintTags(header_fp)
  1162. entry.PrintDeclaration(header_fp)
  1163. print >>header_fp, HeaderPostamble(filename)
  1164. header_fp.close()
  1165. print >>sys.stderr, '... creating "%s"' % impl_file
  1166. impl_fp = open(impl_file, 'w')
  1167. print >>impl_fp, BodyPreamble(filename)
  1168. for entry in entities:
  1169. entry.PrintCode(impl_fp)
  1170. impl_fp.close()
  1171. if __name__ == '__main__':
  1172. main(sys.argv)