A clone of btpd with my configuration changes.
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

1379 строки
45 KiB

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