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