A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

1379 lignes
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)