Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | #!/usr/bin/env python2 |
michael@0 | 2 | # |
michael@0 | 3 | # Copyright (c) 2005-2007 Niels Provos <provos@citi.umich.edu> |
michael@0 | 4 | # Copyright (c) 2007-2012 Niels Provos and Nick Mathewson |
michael@0 | 5 | # All rights reserved. |
michael@0 | 6 | # |
michael@0 | 7 | # Generates marshaling code based on libevent. |
michael@0 | 8 | |
michael@0 | 9 | # TODO: |
michael@0 | 10 | # 1) use optparse to allow the strategy shell to parse options, and |
michael@0 | 11 | # to allow the instantiated factory (for the specific output language) |
michael@0 | 12 | # to parse remaining options |
michael@0 | 13 | # 2) move the globals into a class that manages execution (including the |
michael@0 | 14 | # progress outputs that space stderr at the moment) |
michael@0 | 15 | # 3) emit other languages |
michael@0 | 16 | |
michael@0 | 17 | import sys |
michael@0 | 18 | import re |
michael@0 | 19 | |
michael@0 | 20 | _NAME = "event_rpcgen.py" |
michael@0 | 21 | _VERSION = "0.1" |
michael@0 | 22 | |
michael@0 | 23 | # Globals |
michael@0 | 24 | line_count = 0 |
michael@0 | 25 | |
michael@0 | 26 | white = re.compile(r'\s+') |
michael@0 | 27 | cppcomment = re.compile(r'\/\/.*$') |
michael@0 | 28 | nonident = re.compile(r'[^a-zA-Z0-9_]') |
michael@0 | 29 | structref = re.compile(r'^struct\[([a-zA-Z_][a-zA-Z0-9_]*)\]$') |
michael@0 | 30 | structdef = re.compile(r'^struct +[a-zA-Z_][a-zA-Z0-9_]* *{$') |
michael@0 | 31 | |
michael@0 | 32 | headerdirect = [] |
michael@0 | 33 | cppdirect = [] |
michael@0 | 34 | |
michael@0 | 35 | def TranslateList(mylist, mydict): |
michael@0 | 36 | return map(lambda x: x % mydict, mylist) |
michael@0 | 37 | |
michael@0 | 38 | # Exception class for parse errors |
michael@0 | 39 | class RpcGenError(Exception): |
michael@0 | 40 | def __init__(self, why): |
michael@0 | 41 | self.why = why |
michael@0 | 42 | def __str__(self): |
michael@0 | 43 | return str(self.why) |
michael@0 | 44 | |
michael@0 | 45 | # Holds everything that makes a struct |
michael@0 | 46 | class Struct: |
michael@0 | 47 | def __init__(self, name): |
michael@0 | 48 | self._name = name |
michael@0 | 49 | self._entries = [] |
michael@0 | 50 | self._tags = {} |
michael@0 | 51 | print >>sys.stderr, ' Created struct: %s' % name |
michael@0 | 52 | |
michael@0 | 53 | def AddEntry(self, entry): |
michael@0 | 54 | if self._tags.has_key(entry.Tag()): |
michael@0 | 55 | raise RpcGenError( |
michael@0 | 56 | 'Entry "%s" duplicates tag number %d from "%s" ' |
michael@0 | 57 | 'around line %d' % (entry.Name(), entry.Tag(), |
michael@0 | 58 | self._tags[entry.Tag()], line_count)) |
michael@0 | 59 | self._entries.append(entry) |
michael@0 | 60 | self._tags[entry.Tag()] = entry.Name() |
michael@0 | 61 | print >>sys.stderr, ' Added entry: %s' % entry.Name() |
michael@0 | 62 | |
michael@0 | 63 | def Name(self): |
michael@0 | 64 | return self._name |
michael@0 | 65 | |
michael@0 | 66 | def EntryTagName(self, entry): |
michael@0 | 67 | """Creates the name inside an enumeration for distinguishing data |
michael@0 | 68 | types.""" |
michael@0 | 69 | name = "%s_%s" % (self._name, entry.Name()) |
michael@0 | 70 | return name.upper() |
michael@0 | 71 | |
michael@0 | 72 | def PrintIndented(self, file, ident, code): |
michael@0 | 73 | """Takes an array, add indentation to each entry and prints it.""" |
michael@0 | 74 | for entry in code: |
michael@0 | 75 | print >>file, '%s%s' % (ident, entry) |
michael@0 | 76 | |
michael@0 | 77 | class StructCCode(Struct): |
michael@0 | 78 | """ Knows how to generate C code for a struct """ |
michael@0 | 79 | |
michael@0 | 80 | def __init__(self, name): |
michael@0 | 81 | Struct.__init__(self, name) |
michael@0 | 82 | |
michael@0 | 83 | def PrintTags(self, file): |
michael@0 | 84 | """Prints the tag definitions for a structure.""" |
michael@0 | 85 | print >>file, '/* Tag definition for %s */' % self._name |
michael@0 | 86 | print >>file, 'enum %s_ {' % self._name.lower() |
michael@0 | 87 | for entry in self._entries: |
michael@0 | 88 | print >>file, ' %s=%d,' % (self.EntryTagName(entry), |
michael@0 | 89 | entry.Tag()) |
michael@0 | 90 | print >>file, ' %s_MAX_TAGS' % (self._name.upper()) |
michael@0 | 91 | print >>file, '};\n' |
michael@0 | 92 | |
michael@0 | 93 | def PrintForwardDeclaration(self, file): |
michael@0 | 94 | print >>file, 'struct %s;' % self._name |
michael@0 | 95 | |
michael@0 | 96 | def PrintDeclaration(self, file): |
michael@0 | 97 | print >>file, '/* Structure declaration for %s */' % self._name |
michael@0 | 98 | print >>file, 'struct %s_access_ {' % self._name |
michael@0 | 99 | for entry in self._entries: |
michael@0 | 100 | dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name()) |
michael@0 | 101 | dcl.extend( |
michael@0 | 102 | entry.GetDeclaration('(*%s_get)' % entry.Name())) |
michael@0 | 103 | if entry.Array(): |
michael@0 | 104 | dcl.extend( |
michael@0 | 105 | entry.AddDeclaration('(*%s_add)' % entry.Name())) |
michael@0 | 106 | self.PrintIndented(file, ' ', dcl) |
michael@0 | 107 | print >>file, '};\n' |
michael@0 | 108 | |
michael@0 | 109 | print >>file, 'struct %s {' % self._name |
michael@0 | 110 | print >>file, ' struct %s_access_ *base;\n' % self._name |
michael@0 | 111 | for entry in self._entries: |
michael@0 | 112 | dcl = entry.Declaration() |
michael@0 | 113 | self.PrintIndented(file, ' ', dcl) |
michael@0 | 114 | print >>file, '' |
michael@0 | 115 | for entry in self._entries: |
michael@0 | 116 | print >>file, ' ev_uint8_t %s_set;' % entry.Name() |
michael@0 | 117 | print >>file, '};\n' |
michael@0 | 118 | |
michael@0 | 119 | print >>file, \ |
michael@0 | 120 | """struct %(name)s *%(name)s_new(void); |
michael@0 | 121 | struct %(name)s *%(name)s_new_with_arg(void *); |
michael@0 | 122 | void %(name)s_free(struct %(name)s *); |
michael@0 | 123 | void %(name)s_clear(struct %(name)s *); |
michael@0 | 124 | void %(name)s_marshal(struct evbuffer *, const struct %(name)s *); |
michael@0 | 125 | int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *); |
michael@0 | 126 | int %(name)s_complete(struct %(name)s *); |
michael@0 | 127 | void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t, |
michael@0 | 128 | const struct %(name)s *); |
michael@0 | 129 | int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t, |
michael@0 | 130 | struct %(name)s *);""" % { 'name' : self._name } |
michael@0 | 131 | |
michael@0 | 132 | |
michael@0 | 133 | # Write a setting function of every variable |
michael@0 | 134 | for entry in self._entries: |
michael@0 | 135 | self.PrintIndented(file, '', entry.AssignDeclaration( |
michael@0 | 136 | entry.AssignFuncName())) |
michael@0 | 137 | self.PrintIndented(file, '', entry.GetDeclaration( |
michael@0 | 138 | entry.GetFuncName())) |
michael@0 | 139 | if entry.Array(): |
michael@0 | 140 | self.PrintIndented(file, '', entry.AddDeclaration( |
michael@0 | 141 | entry.AddFuncName())) |
michael@0 | 142 | |
michael@0 | 143 | print >>file, '/* --- %s done --- */\n' % self._name |
michael@0 | 144 | |
michael@0 | 145 | def PrintCode(self, file): |
michael@0 | 146 | print >>file, ('/*\n' |
michael@0 | 147 | ' * Implementation of %s\n' |
michael@0 | 148 | ' */\n') % self._name |
michael@0 | 149 | |
michael@0 | 150 | print >>file, \ |
michael@0 | 151 | 'static struct %(name)s_access_ __%(name)s_base = {' % \ |
michael@0 | 152 | { 'name' : self._name } |
michael@0 | 153 | for entry in self._entries: |
michael@0 | 154 | self.PrintIndented(file, ' ', entry.CodeBase()) |
michael@0 | 155 | print >>file, '};\n' |
michael@0 | 156 | |
michael@0 | 157 | # Creation |
michael@0 | 158 | print >>file, ( |
michael@0 | 159 | 'struct %(name)s *\n' |
michael@0 | 160 | '%(name)s_new(void)\n' |
michael@0 | 161 | '{\n' |
michael@0 | 162 | ' return %(name)s_new_with_arg(NULL);\n' |
michael@0 | 163 | '}\n' |
michael@0 | 164 | '\n' |
michael@0 | 165 | 'struct %(name)s *\n' |
michael@0 | 166 | '%(name)s_new_with_arg(void *unused)\n' |
michael@0 | 167 | '{\n' |
michael@0 | 168 | ' struct %(name)s *tmp;\n' |
michael@0 | 169 | ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n' |
michael@0 | 170 | ' event_warn("%%s: malloc", __func__);\n' |
michael@0 | 171 | ' return (NULL);\n' |
michael@0 | 172 | ' }\n' |
michael@0 | 173 | ' tmp->base = &__%(name)s_base;\n') % { 'name' : self._name } |
michael@0 | 174 | |
michael@0 | 175 | for entry in self._entries: |
michael@0 | 176 | self.PrintIndented(file, ' ', entry.CodeInitialize('tmp')) |
michael@0 | 177 | print >>file, ' tmp->%s_set = 0;\n' % entry.Name() |
michael@0 | 178 | |
michael@0 | 179 | print >>file, ( |
michael@0 | 180 | ' return (tmp);\n' |
michael@0 | 181 | '}\n') |
michael@0 | 182 | |
michael@0 | 183 | # Adding |
michael@0 | 184 | for entry in self._entries: |
michael@0 | 185 | if entry.Array(): |
michael@0 | 186 | self.PrintIndented(file, '', entry.CodeAdd()) |
michael@0 | 187 | print >>file, '' |
michael@0 | 188 | |
michael@0 | 189 | # Assigning |
michael@0 | 190 | for entry in self._entries: |
michael@0 | 191 | self.PrintIndented(file, '', entry.CodeAssign()) |
michael@0 | 192 | print >>file, '' |
michael@0 | 193 | |
michael@0 | 194 | # Getting |
michael@0 | 195 | for entry in self._entries: |
michael@0 | 196 | self.PrintIndented(file, '', entry.CodeGet()) |
michael@0 | 197 | print >>file, '' |
michael@0 | 198 | |
michael@0 | 199 | # Clearing |
michael@0 | 200 | print >>file, ( 'void\n' |
michael@0 | 201 | '%(name)s_clear(struct %(name)s *tmp)\n' |
michael@0 | 202 | '{' |
michael@0 | 203 | ) % { 'name' : self._name } |
michael@0 | 204 | for entry in self._entries: |
michael@0 | 205 | self.PrintIndented(file, ' ', entry.CodeClear('tmp')) |
michael@0 | 206 | |
michael@0 | 207 | print >>file, '}\n' |
michael@0 | 208 | |
michael@0 | 209 | # Freeing |
michael@0 | 210 | print >>file, ( 'void\n' |
michael@0 | 211 | '%(name)s_free(struct %(name)s *tmp)\n' |
michael@0 | 212 | '{' |
michael@0 | 213 | ) % { 'name' : self._name } |
michael@0 | 214 | |
michael@0 | 215 | for entry in self._entries: |
michael@0 | 216 | self.PrintIndented(file, ' ', entry.CodeFree('tmp')) |
michael@0 | 217 | |
michael@0 | 218 | print >>file, (' free(tmp);\n' |
michael@0 | 219 | '}\n') |
michael@0 | 220 | |
michael@0 | 221 | # Marshaling |
michael@0 | 222 | print >>file, ('void\n' |
michael@0 | 223 | '%(name)s_marshal(struct evbuffer *evbuf, ' |
michael@0 | 224 | 'const struct %(name)s *tmp)' |
michael@0 | 225 | '{') % { 'name' : self._name } |
michael@0 | 226 | for entry in self._entries: |
michael@0 | 227 | indent = ' ' |
michael@0 | 228 | # Optional entries do not have to be set |
michael@0 | 229 | if entry.Optional(): |
michael@0 | 230 | indent += ' ' |
michael@0 | 231 | print >>file, ' if (tmp->%s_set) {' % entry.Name() |
michael@0 | 232 | self.PrintIndented( |
michael@0 | 233 | file, indent, |
michael@0 | 234 | entry.CodeMarshal('evbuf', self.EntryTagName(entry), |
michael@0 | 235 | entry.GetVarName('tmp'), |
michael@0 | 236 | entry.GetVarLen('tmp'))) |
michael@0 | 237 | if entry.Optional(): |
michael@0 | 238 | print >>file, ' }' |
michael@0 | 239 | |
michael@0 | 240 | print >>file, '}\n' |
michael@0 | 241 | |
michael@0 | 242 | # Unmarshaling |
michael@0 | 243 | print >>file, ('int\n' |
michael@0 | 244 | '%(name)s_unmarshal(struct %(name)s *tmp, ' |
michael@0 | 245 | ' struct evbuffer *evbuf)\n' |
michael@0 | 246 | '{\n' |
michael@0 | 247 | ' ev_uint32_t tag;\n' |
michael@0 | 248 | ' while (evbuffer_get_length(evbuf) > 0) {\n' |
michael@0 | 249 | ' if (evtag_peek(evbuf, &tag) == -1)\n' |
michael@0 | 250 | ' return (-1);\n' |
michael@0 | 251 | ' switch (tag) {\n' |
michael@0 | 252 | ) % { 'name' : self._name } |
michael@0 | 253 | for entry in self._entries: |
michael@0 | 254 | print >>file, ' case %s:\n' % self.EntryTagName(entry) |
michael@0 | 255 | if not entry.Array(): |
michael@0 | 256 | print >>file, ( |
michael@0 | 257 | ' if (tmp->%s_set)\n' |
michael@0 | 258 | ' return (-1);' |
michael@0 | 259 | ) % (entry.Name()) |
michael@0 | 260 | |
michael@0 | 261 | self.PrintIndented( |
michael@0 | 262 | file, ' ', |
michael@0 | 263 | entry.CodeUnmarshal('evbuf', |
michael@0 | 264 | self.EntryTagName(entry), |
michael@0 | 265 | entry.GetVarName('tmp'), |
michael@0 | 266 | entry.GetVarLen('tmp'))) |
michael@0 | 267 | |
michael@0 | 268 | print >>file, ( ' tmp->%s_set = 1;\n' % entry.Name() + |
michael@0 | 269 | ' break;\n' ) |
michael@0 | 270 | print >>file, ( ' default:\n' |
michael@0 | 271 | ' return -1;\n' |
michael@0 | 272 | ' }\n' |
michael@0 | 273 | ' }\n' ) |
michael@0 | 274 | # Check if it was decoded completely |
michael@0 | 275 | print >>file, ( ' if (%(name)s_complete(tmp) == -1)\n' |
michael@0 | 276 | ' return (-1);' |
michael@0 | 277 | ) % { 'name' : self._name } |
michael@0 | 278 | |
michael@0 | 279 | # Successfully decoded |
michael@0 | 280 | print >>file, ( ' return (0);\n' |
michael@0 | 281 | '}\n') |
michael@0 | 282 | |
michael@0 | 283 | # Checking if a structure has all the required data |
michael@0 | 284 | print >>file, ( |
michael@0 | 285 | 'int\n' |
michael@0 | 286 | '%(name)s_complete(struct %(name)s *msg)\n' |
michael@0 | 287 | '{' ) % { 'name' : self._name } |
michael@0 | 288 | for entry in self._entries: |
michael@0 | 289 | if not entry.Optional(): |
michael@0 | 290 | code = [ |
michael@0 | 291 | 'if (!msg->%(name)s_set)', |
michael@0 | 292 | ' return (-1);' ] |
michael@0 | 293 | code = TranslateList(code, entry.GetTranslation()) |
michael@0 | 294 | self.PrintIndented( |
michael@0 | 295 | file, ' ', code) |
michael@0 | 296 | |
michael@0 | 297 | self.PrintIndented( |
michael@0 | 298 | file, ' ', |
michael@0 | 299 | entry.CodeComplete('msg', entry.GetVarName('msg'))) |
michael@0 | 300 | print >>file, ( |
michael@0 | 301 | ' return (0);\n' |
michael@0 | 302 | '}\n' ) |
michael@0 | 303 | |
michael@0 | 304 | # Complete message unmarshaling |
michael@0 | 305 | print >>file, ( |
michael@0 | 306 | 'int\n' |
michael@0 | 307 | 'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, ' |
michael@0 | 308 | 'ev_uint32_t need_tag, struct %(name)s *msg)\n' |
michael@0 | 309 | '{\n' |
michael@0 | 310 | ' ev_uint32_t tag;\n' |
michael@0 | 311 | ' int res = -1;\n' |
michael@0 | 312 | '\n' |
michael@0 | 313 | ' struct evbuffer *tmp = evbuffer_new();\n' |
michael@0 | 314 | '\n' |
michael@0 | 315 | ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1' |
michael@0 | 316 | ' || tag != need_tag)\n' |
michael@0 | 317 | ' goto error;\n' |
michael@0 | 318 | '\n' |
michael@0 | 319 | ' if (%(name)s_unmarshal(msg, tmp) == -1)\n' |
michael@0 | 320 | ' goto error;\n' |
michael@0 | 321 | '\n' |
michael@0 | 322 | ' res = 0;\n' |
michael@0 | 323 | '\n' |
michael@0 | 324 | ' error:\n' |
michael@0 | 325 | ' evbuffer_free(tmp);\n' |
michael@0 | 326 | ' return (res);\n' |
michael@0 | 327 | '}\n' ) % { 'name' : self._name } |
michael@0 | 328 | |
michael@0 | 329 | # Complete message marshaling |
michael@0 | 330 | print >>file, ( |
michael@0 | 331 | 'void\n' |
michael@0 | 332 | 'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, ' |
michael@0 | 333 | 'const struct %(name)s *msg)\n' |
michael@0 | 334 | '{\n' |
michael@0 | 335 | ' struct evbuffer *_buf = evbuffer_new();\n' |
michael@0 | 336 | ' assert(_buf != NULL);\n' |
michael@0 | 337 | ' %(name)s_marshal(_buf, msg);\n' |
michael@0 | 338 | ' evtag_marshal_buffer(evbuf, tag, _buf);\n ' |
michael@0 | 339 | ' evbuffer_free(_buf);\n' |
michael@0 | 340 | '}\n' ) % { 'name' : self._name } |
michael@0 | 341 | |
michael@0 | 342 | class Entry: |
michael@0 | 343 | def __init__(self, type, name, tag): |
michael@0 | 344 | self._type = type |
michael@0 | 345 | self._name = name |
michael@0 | 346 | self._tag = int(tag) |
michael@0 | 347 | self._ctype = type |
michael@0 | 348 | self._optional = 0 |
michael@0 | 349 | self._can_be_array = 0 |
michael@0 | 350 | self._array = 0 |
michael@0 | 351 | self._line_count = -1 |
michael@0 | 352 | self._struct = None |
michael@0 | 353 | self._refname = None |
michael@0 | 354 | |
michael@0 | 355 | self._optpointer = True |
michael@0 | 356 | self._optaddarg = True |
michael@0 | 357 | |
michael@0 | 358 | def GetInitializer(self): |
michael@0 | 359 | assert 0, "Entry does not provide initializer" |
michael@0 | 360 | |
michael@0 | 361 | def SetStruct(self, struct): |
michael@0 | 362 | self._struct = struct |
michael@0 | 363 | |
michael@0 | 364 | def LineCount(self): |
michael@0 | 365 | assert self._line_count != -1 |
michael@0 | 366 | return self._line_count |
michael@0 | 367 | |
michael@0 | 368 | def SetLineCount(self, number): |
michael@0 | 369 | self._line_count = number |
michael@0 | 370 | |
michael@0 | 371 | def Array(self): |
michael@0 | 372 | return self._array |
michael@0 | 373 | |
michael@0 | 374 | def Optional(self): |
michael@0 | 375 | return self._optional |
michael@0 | 376 | |
michael@0 | 377 | def Tag(self): |
michael@0 | 378 | return self._tag |
michael@0 | 379 | |
michael@0 | 380 | def Name(self): |
michael@0 | 381 | return self._name |
michael@0 | 382 | |
michael@0 | 383 | def Type(self): |
michael@0 | 384 | return self._type |
michael@0 | 385 | |
michael@0 | 386 | def MakeArray(self, yes=1): |
michael@0 | 387 | self._array = yes |
michael@0 | 388 | |
michael@0 | 389 | def MakeOptional(self): |
michael@0 | 390 | self._optional = 1 |
michael@0 | 391 | |
michael@0 | 392 | def Verify(self): |
michael@0 | 393 | if self.Array() and not self._can_be_array: |
michael@0 | 394 | raise RpcGenError( |
michael@0 | 395 | 'Entry "%s" cannot be created as an array ' |
michael@0 | 396 | 'around line %d' % (self._name, self.LineCount())) |
michael@0 | 397 | if not self._struct: |
michael@0 | 398 | raise RpcGenError( |
michael@0 | 399 | 'Entry "%s" does not know which struct it belongs to ' |
michael@0 | 400 | 'around line %d' % (self._name, self.LineCount())) |
michael@0 | 401 | if self._optional and self._array: |
michael@0 | 402 | raise RpcGenError( |
michael@0 | 403 | 'Entry "%s" has illegal combination of optional and array ' |
michael@0 | 404 | 'around line %d' % (self._name, self.LineCount())) |
michael@0 | 405 | |
michael@0 | 406 | def GetTranslation(self, extradict = {}): |
michael@0 | 407 | mapping = { |
michael@0 | 408 | "parent_name" : self._struct.Name(), |
michael@0 | 409 | "name" : self._name, |
michael@0 | 410 | "ctype" : self._ctype, |
michael@0 | 411 | "refname" : self._refname, |
michael@0 | 412 | "optpointer" : self._optpointer and "*" or "", |
michael@0 | 413 | "optreference" : self._optpointer and "&" or "", |
michael@0 | 414 | "optaddarg" : |
michael@0 | 415 | self._optaddarg and ", const %s value" % self._ctype or "" |
michael@0 | 416 | } |
michael@0 | 417 | for (k, v) in extradict.items(): |
michael@0 | 418 | mapping[k] = v |
michael@0 | 419 | |
michael@0 | 420 | return mapping |
michael@0 | 421 | |
michael@0 | 422 | def GetVarName(self, var): |
michael@0 | 423 | return '%(var)s->%(name)s_data' % self.GetTranslation({ 'var' : var }) |
michael@0 | 424 | |
michael@0 | 425 | def GetVarLen(self, var): |
michael@0 | 426 | return 'sizeof(%s)' % self._ctype |
michael@0 | 427 | |
michael@0 | 428 | def GetFuncName(self): |
michael@0 | 429 | return '%s_%s_get' % (self._struct.Name(), self._name) |
michael@0 | 430 | |
michael@0 | 431 | def GetDeclaration(self, funcname): |
michael@0 | 432 | code = [ 'int %s(struct %s *, %s *);' % ( |
michael@0 | 433 | funcname, self._struct.Name(), self._ctype ) ] |
michael@0 | 434 | return code |
michael@0 | 435 | |
michael@0 | 436 | def CodeGet(self): |
michael@0 | 437 | code = ( |
michael@0 | 438 | 'int', |
michael@0 | 439 | '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, ' |
michael@0 | 440 | '%(ctype)s *value)', |
michael@0 | 441 | '{', |
michael@0 | 442 | ' if (msg->%(name)s_set != 1)', |
michael@0 | 443 | ' return (-1);', |
michael@0 | 444 | ' *value = msg->%(name)s_data;', |
michael@0 | 445 | ' return (0);', |
michael@0 | 446 | '}' ) |
michael@0 | 447 | code = '\n'.join(code) |
michael@0 | 448 | code = code % self.GetTranslation() |
michael@0 | 449 | return code.split('\n') |
michael@0 | 450 | |
michael@0 | 451 | def AssignFuncName(self): |
michael@0 | 452 | return '%s_%s_assign' % (self._struct.Name(), self._name) |
michael@0 | 453 | |
michael@0 | 454 | def AddFuncName(self): |
michael@0 | 455 | return '%s_%s_add' % (self._struct.Name(), self._name) |
michael@0 | 456 | |
michael@0 | 457 | def AssignDeclaration(self, funcname): |
michael@0 | 458 | code = [ 'int %s(struct %s *, const %s);' % ( |
michael@0 | 459 | funcname, self._struct.Name(), self._ctype ) ] |
michael@0 | 460 | return code |
michael@0 | 461 | |
michael@0 | 462 | def CodeAssign(self): |
michael@0 | 463 | code = [ 'int', |
michael@0 | 464 | '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,' |
michael@0 | 465 | ' const %(ctype)s value)', |
michael@0 | 466 | '{', |
michael@0 | 467 | ' msg->%(name)s_set = 1;', |
michael@0 | 468 | ' msg->%(name)s_data = value;', |
michael@0 | 469 | ' return (0);', |
michael@0 | 470 | '}' ] |
michael@0 | 471 | code = '\n'.join(code) |
michael@0 | 472 | code = code % self.GetTranslation() |
michael@0 | 473 | return code.split('\n') |
michael@0 | 474 | |
michael@0 | 475 | def CodeClear(self, structname): |
michael@0 | 476 | code = [ '%s->%s_set = 0;' % (structname, self.Name()) ] |
michael@0 | 477 | |
michael@0 | 478 | return code |
michael@0 | 479 | |
michael@0 | 480 | def CodeComplete(self, structname, var_name): |
michael@0 | 481 | return [] |
michael@0 | 482 | |
michael@0 | 483 | def CodeFree(self, name): |
michael@0 | 484 | return [] |
michael@0 | 485 | |
michael@0 | 486 | def CodeBase(self): |
michael@0 | 487 | code = [ |
michael@0 | 488 | '%(parent_name)s_%(name)s_assign,', |
michael@0 | 489 | '%(parent_name)s_%(name)s_get,' |
michael@0 | 490 | ] |
michael@0 | 491 | if self.Array(): |
michael@0 | 492 | code.append('%(parent_name)s_%(name)s_add,') |
michael@0 | 493 | |
michael@0 | 494 | code = '\n'.join(code) |
michael@0 | 495 | code = code % self.GetTranslation() |
michael@0 | 496 | return code.split('\n') |
michael@0 | 497 | |
michael@0 | 498 | class EntryBytes(Entry): |
michael@0 | 499 | def __init__(self, type, name, tag, length): |
michael@0 | 500 | # Init base class |
michael@0 | 501 | Entry.__init__(self, type, name, tag) |
michael@0 | 502 | |
michael@0 | 503 | self._length = length |
michael@0 | 504 | self._ctype = 'ev_uint8_t' |
michael@0 | 505 | |
michael@0 | 506 | def GetInitializer(self): |
michael@0 | 507 | return "NULL" |
michael@0 | 508 | |
michael@0 | 509 | def GetVarLen(self, var): |
michael@0 | 510 | return '(%s)' % self._length |
michael@0 | 511 | |
michael@0 | 512 | def CodeArrayAdd(self, varname, value): |
michael@0 | 513 | # XXX: copy here |
michael@0 | 514 | return [ '%(varname)s = NULL;' % { 'varname' : varname } ] |
michael@0 | 515 | |
michael@0 | 516 | def GetDeclaration(self, funcname): |
michael@0 | 517 | code = [ 'int %s(struct %s *, %s **);' % ( |
michael@0 | 518 | funcname, self._struct.Name(), self._ctype ) ] |
michael@0 | 519 | return code |
michael@0 | 520 | |
michael@0 | 521 | def AssignDeclaration(self, funcname): |
michael@0 | 522 | code = [ 'int %s(struct %s *, const %s *);' % ( |
michael@0 | 523 | funcname, self._struct.Name(), self._ctype ) ] |
michael@0 | 524 | return code |
michael@0 | 525 | |
michael@0 | 526 | def Declaration(self): |
michael@0 | 527 | dcl = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)] |
michael@0 | 528 | |
michael@0 | 529 | return dcl |
michael@0 | 530 | |
michael@0 | 531 | def CodeGet(self): |
michael@0 | 532 | name = self._name |
michael@0 | 533 | code = [ 'int', |
michael@0 | 534 | '%s_%s_get(struct %s *msg, %s **value)' % ( |
michael@0 | 535 | self._struct.Name(), name, |
michael@0 | 536 | self._struct.Name(), self._ctype), |
michael@0 | 537 | '{', |
michael@0 | 538 | ' if (msg->%s_set != 1)' % name, |
michael@0 | 539 | ' return (-1);', |
michael@0 | 540 | ' *value = msg->%s_data;' % name, |
michael@0 | 541 | ' return (0);', |
michael@0 | 542 | '}' ] |
michael@0 | 543 | return code |
michael@0 | 544 | |
michael@0 | 545 | def CodeAssign(self): |
michael@0 | 546 | name = self._name |
michael@0 | 547 | code = [ 'int', |
michael@0 | 548 | '%s_%s_assign(struct %s *msg, const %s *value)' % ( |
michael@0 | 549 | self._struct.Name(), name, |
michael@0 | 550 | self._struct.Name(), self._ctype), |
michael@0 | 551 | '{', |
michael@0 | 552 | ' msg->%s_set = 1;' % name, |
michael@0 | 553 | ' memcpy(msg->%s_data, value, %s);' % ( |
michael@0 | 554 | name, self._length), |
michael@0 | 555 | ' return (0);', |
michael@0 | 556 | '}' ] |
michael@0 | 557 | return code |
michael@0 | 558 | |
michael@0 | 559 | def CodeUnmarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 560 | code = [ 'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, ' |
michael@0 | 561 | '%(var)s, %(varlen)s) == -1) {', |
michael@0 | 562 | ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', |
michael@0 | 563 | ' return (-1);', |
michael@0 | 564 | '}' |
michael@0 | 565 | ] |
michael@0 | 566 | return TranslateList(code, |
michael@0 | 567 | self.GetTranslation({ |
michael@0 | 568 | 'var' : var_name, |
michael@0 | 569 | 'varlen' : var_len, |
michael@0 | 570 | 'buf' : buf, |
michael@0 | 571 | 'tag' : tag_name })) |
michael@0 | 572 | |
michael@0 | 573 | def CodeMarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 574 | code = ['evtag_marshal(%s, %s, %s, %s);' % ( |
michael@0 | 575 | buf, tag_name, var_name, var_len)] |
michael@0 | 576 | return code |
michael@0 | 577 | |
michael@0 | 578 | def CodeClear(self, structname): |
michael@0 | 579 | code = [ '%s->%s_set = 0;' % (structname, self.Name()), |
michael@0 | 580 | 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( |
michael@0 | 581 | structname, self._name, structname, self._name)] |
michael@0 | 582 | |
michael@0 | 583 | return code |
michael@0 | 584 | |
michael@0 | 585 | def CodeInitialize(self, name): |
michael@0 | 586 | code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( |
michael@0 | 587 | name, self._name, name, self._name)] |
michael@0 | 588 | return code |
michael@0 | 589 | |
michael@0 | 590 | def Verify(self): |
michael@0 | 591 | if not self._length: |
michael@0 | 592 | raise RpcGenError( |
michael@0 | 593 | 'Entry "%s" needs a length ' |
michael@0 | 594 | 'around line %d' % (self._name, self.LineCount())) |
michael@0 | 595 | |
michael@0 | 596 | Entry.Verify(self) |
michael@0 | 597 | |
michael@0 | 598 | class EntryInt(Entry): |
michael@0 | 599 | def __init__(self, type, name, tag, bits=32): |
michael@0 | 600 | # Init base class |
michael@0 | 601 | Entry.__init__(self, type, name, tag) |
michael@0 | 602 | |
michael@0 | 603 | self._can_be_array = 1 |
michael@0 | 604 | if bits == 32: |
michael@0 | 605 | self._ctype = 'ev_uint32_t' |
michael@0 | 606 | self._marshal_type = 'int' |
michael@0 | 607 | if bits == 64: |
michael@0 | 608 | self._ctype = 'ev_uint64_t' |
michael@0 | 609 | self._marshal_type = 'int64' |
michael@0 | 610 | |
michael@0 | 611 | def GetInitializer(self): |
michael@0 | 612 | return "0" |
michael@0 | 613 | |
michael@0 | 614 | def CodeArrayFree(self, var): |
michael@0 | 615 | return [] |
michael@0 | 616 | |
michael@0 | 617 | def CodeArrayAssign(self, varname, srcvar): |
michael@0 | 618 | return [ '%(varname)s = %(srcvar)s;' % { 'varname' : varname, |
michael@0 | 619 | 'srcvar' : srcvar } ] |
michael@0 | 620 | |
michael@0 | 621 | def CodeArrayAdd(self, varname, value): |
michael@0 | 622 | """Returns a new entry of this type.""" |
michael@0 | 623 | return [ '%(varname)s = %(value)s;' % { 'varname' : varname, |
michael@0 | 624 | 'value' : value } ] |
michael@0 | 625 | |
michael@0 | 626 | def CodeUnmarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 627 | code = [ |
michael@0 | 628 | 'if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {', |
michael@0 | 629 | ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', |
michael@0 | 630 | ' return (-1);', |
michael@0 | 631 | '}' ] |
michael@0 | 632 | code = '\n'.join(code) % self.GetTranslation({ |
michael@0 | 633 | 'ma' : self._marshal_type, |
michael@0 | 634 | 'buf' : buf, |
michael@0 | 635 | 'tag' : tag_name, |
michael@0 | 636 | 'var' : var_name }) |
michael@0 | 637 | return code.split('\n') |
michael@0 | 638 | |
michael@0 | 639 | def CodeMarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 640 | code = [ |
michael@0 | 641 | 'evtag_marshal_%s(%s, %s, %s);' % ( |
michael@0 | 642 | self._marshal_type, buf, tag_name, var_name)] |
michael@0 | 643 | return code |
michael@0 | 644 | |
michael@0 | 645 | def Declaration(self): |
michael@0 | 646 | dcl = ['%s %s_data;' % (self._ctype, self._name)] |
michael@0 | 647 | |
michael@0 | 648 | return dcl |
michael@0 | 649 | |
michael@0 | 650 | def CodeInitialize(self, name): |
michael@0 | 651 | code = ['%s->%s_data = 0;' % (name, self._name)] |
michael@0 | 652 | return code |
michael@0 | 653 | |
michael@0 | 654 | class EntryString(Entry): |
michael@0 | 655 | def __init__(self, type, name, tag): |
michael@0 | 656 | # Init base class |
michael@0 | 657 | Entry.__init__(self, type, name, tag) |
michael@0 | 658 | |
michael@0 | 659 | self._can_be_array = 1 |
michael@0 | 660 | self._ctype = 'char *' |
michael@0 | 661 | |
michael@0 | 662 | def GetInitializer(self): |
michael@0 | 663 | return "NULL" |
michael@0 | 664 | |
michael@0 | 665 | def CodeArrayFree(self, varname): |
michael@0 | 666 | code = [ |
michael@0 | 667 | 'if (%(var)s != NULL) free(%(var)s);' ] |
michael@0 | 668 | |
michael@0 | 669 | return TranslateList(code, { 'var' : varname }) |
michael@0 | 670 | |
michael@0 | 671 | def CodeArrayAssign(self, varname, srcvar): |
michael@0 | 672 | code = [ |
michael@0 | 673 | 'if (%(var)s != NULL)', |
michael@0 | 674 | ' free(%(var)s);', |
michael@0 | 675 | '%(var)s = strdup(%(srcvar)s);', |
michael@0 | 676 | 'if (%(var)s == NULL) {', |
michael@0 | 677 | ' event_warnx("%%s: strdup", __func__);', |
michael@0 | 678 | ' return (-1);', |
michael@0 | 679 | '}' ] |
michael@0 | 680 | |
michael@0 | 681 | return TranslateList(code, { 'var' : varname, |
michael@0 | 682 | 'srcvar' : srcvar }) |
michael@0 | 683 | |
michael@0 | 684 | def CodeArrayAdd(self, varname, value): |
michael@0 | 685 | code = [ |
michael@0 | 686 | 'if (%(value)s != NULL) {', |
michael@0 | 687 | ' %(var)s = strdup(%(value)s);', |
michael@0 | 688 | ' if (%(var)s == NULL) {', |
michael@0 | 689 | ' goto error;', |
michael@0 | 690 | ' }', |
michael@0 | 691 | '} else {', |
michael@0 | 692 | ' %(var)s = NULL;', |
michael@0 | 693 | '}' ] |
michael@0 | 694 | |
michael@0 | 695 | return TranslateList(code, { 'var' : varname, |
michael@0 | 696 | 'value' : value }) |
michael@0 | 697 | |
michael@0 | 698 | def GetVarLen(self, var): |
michael@0 | 699 | return 'strlen(%s)' % self.GetVarName(var) |
michael@0 | 700 | |
michael@0 | 701 | def CodeMakeInitalize(self, varname): |
michael@0 | 702 | return '%(varname)s = NULL;' % { 'varname' : varname } |
michael@0 | 703 | |
michael@0 | 704 | def CodeAssign(self): |
michael@0 | 705 | name = self._name |
michael@0 | 706 | code = """int |
michael@0 | 707 | %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, |
michael@0 | 708 | const %(ctype)s value) |
michael@0 | 709 | { |
michael@0 | 710 | if (msg->%(name)s_data != NULL) |
michael@0 | 711 | free(msg->%(name)s_data); |
michael@0 | 712 | if ((msg->%(name)s_data = strdup(value)) == NULL) |
michael@0 | 713 | return (-1); |
michael@0 | 714 | msg->%(name)s_set = 1; |
michael@0 | 715 | return (0); |
michael@0 | 716 | }""" % self.GetTranslation() |
michael@0 | 717 | |
michael@0 | 718 | return code.split('\n') |
michael@0 | 719 | |
michael@0 | 720 | def CodeUnmarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 721 | code = ['if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {', |
michael@0 | 722 | ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', |
michael@0 | 723 | ' return (-1);', |
michael@0 | 724 | '}' |
michael@0 | 725 | ] |
michael@0 | 726 | code = '\n'.join(code) % self.GetTranslation({ |
michael@0 | 727 | 'buf' : buf, |
michael@0 | 728 | 'tag' : tag_name, |
michael@0 | 729 | 'var' : var_name }) |
michael@0 | 730 | return code.split('\n') |
michael@0 | 731 | |
michael@0 | 732 | def CodeMarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 733 | code = ['evtag_marshal_string(%s, %s, %s);' % ( |
michael@0 | 734 | buf, tag_name, var_name)] |
michael@0 | 735 | return code |
michael@0 | 736 | |
michael@0 | 737 | def CodeClear(self, structname): |
michael@0 | 738 | code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), |
michael@0 | 739 | ' free(%s->%s_data);' % (structname, self.Name()), |
michael@0 | 740 | ' %s->%s_data = NULL;' % (structname, self.Name()), |
michael@0 | 741 | ' %s->%s_set = 0;' % (structname, self.Name()), |
michael@0 | 742 | '}' |
michael@0 | 743 | ] |
michael@0 | 744 | |
michael@0 | 745 | return code |
michael@0 | 746 | |
michael@0 | 747 | def CodeInitialize(self, name): |
michael@0 | 748 | code = ['%s->%s_data = NULL;' % (name, self._name)] |
michael@0 | 749 | return code |
michael@0 | 750 | |
michael@0 | 751 | def CodeFree(self, name): |
michael@0 | 752 | code = ['if (%s->%s_data != NULL)' % (name, self._name), |
michael@0 | 753 | ' free (%s->%s_data);' % (name, self._name)] |
michael@0 | 754 | |
michael@0 | 755 | return code |
michael@0 | 756 | |
michael@0 | 757 | def Declaration(self): |
michael@0 | 758 | dcl = ['char *%s_data;' % self._name] |
michael@0 | 759 | |
michael@0 | 760 | return dcl |
michael@0 | 761 | |
michael@0 | 762 | class EntryStruct(Entry): |
michael@0 | 763 | def __init__(self, type, name, tag, refname): |
michael@0 | 764 | # Init base class |
michael@0 | 765 | Entry.__init__(self, type, name, tag) |
michael@0 | 766 | |
michael@0 | 767 | self._optpointer = False |
michael@0 | 768 | self._can_be_array = 1 |
michael@0 | 769 | self._refname = refname |
michael@0 | 770 | self._ctype = 'struct %s*' % refname |
michael@0 | 771 | self._optaddarg = False |
michael@0 | 772 | |
michael@0 | 773 | def GetInitializer(self): |
michael@0 | 774 | return "NULL" |
michael@0 | 775 | |
michael@0 | 776 | def GetVarLen(self, var): |
michael@0 | 777 | return '-1' |
michael@0 | 778 | |
michael@0 | 779 | def CodeArrayAdd(self, varname, value): |
michael@0 | 780 | code = [ |
michael@0 | 781 | '%(varname)s = %(refname)s_new();', |
michael@0 | 782 | 'if (%(varname)s == NULL)', |
michael@0 | 783 | ' goto error;' ] |
michael@0 | 784 | |
michael@0 | 785 | return TranslateList(code, self.GetTranslation({ 'varname' : varname })) |
michael@0 | 786 | |
michael@0 | 787 | def CodeArrayFree(self, var): |
michael@0 | 788 | code = [ '%(refname)s_free(%(var)s);' % self.GetTranslation( |
michael@0 | 789 | { 'var' : var }) ] |
michael@0 | 790 | return code |
michael@0 | 791 | |
michael@0 | 792 | def CodeArrayAssign(self, var, srcvar): |
michael@0 | 793 | code = [ |
michael@0 | 794 | 'int had_error = 0;', |
michael@0 | 795 | 'struct evbuffer *tmp = NULL;', |
michael@0 | 796 | '%(refname)s_clear(%(var)s);', |
michael@0 | 797 | 'if ((tmp = evbuffer_new()) == NULL) {', |
michael@0 | 798 | ' event_warn("%%s: evbuffer_new()", __func__);', |
michael@0 | 799 | ' had_error = 1;', |
michael@0 | 800 | ' goto done;', |
michael@0 | 801 | '}', |
michael@0 | 802 | '%(refname)s_marshal(tmp, %(srcvar)s);', |
michael@0 | 803 | 'if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {', |
michael@0 | 804 | ' event_warnx("%%s: %(refname)s_unmarshal", __func__);', |
michael@0 | 805 | ' had_error = 1;', |
michael@0 | 806 | ' goto done;', |
michael@0 | 807 | '}', |
michael@0 | 808 | 'done:' |
michael@0 | 809 | 'if (tmp != NULL)', |
michael@0 | 810 | ' evbuffer_free(tmp);', |
michael@0 | 811 | 'if (had_error) {', |
michael@0 | 812 | ' %(refname)s_clear(%(var)s);', |
michael@0 | 813 | ' return (-1);', |
michael@0 | 814 | '}' ] |
michael@0 | 815 | |
michael@0 | 816 | return TranslateList(code, self.GetTranslation({ |
michael@0 | 817 | 'var' : var, |
michael@0 | 818 | 'srcvar' : srcvar})) |
michael@0 | 819 | |
michael@0 | 820 | def CodeGet(self): |
michael@0 | 821 | name = self._name |
michael@0 | 822 | code = [ 'int', |
michael@0 | 823 | '%s_%s_get(struct %s *msg, %s *value)' % ( |
michael@0 | 824 | self._struct.Name(), name, |
michael@0 | 825 | self._struct.Name(), self._ctype), |
michael@0 | 826 | '{', |
michael@0 | 827 | ' if (msg->%s_set != 1) {' % name, |
michael@0 | 828 | ' msg->%s_data = %s_new();' % (name, self._refname), |
michael@0 | 829 | ' if (msg->%s_data == NULL)' % name, |
michael@0 | 830 | ' return (-1);', |
michael@0 | 831 | ' msg->%s_set = 1;' % name, |
michael@0 | 832 | ' }', |
michael@0 | 833 | ' *value = msg->%s_data;' % name, |
michael@0 | 834 | ' return (0);', |
michael@0 | 835 | '}' ] |
michael@0 | 836 | return code |
michael@0 | 837 | |
michael@0 | 838 | def CodeAssign(self): |
michael@0 | 839 | name = self._name |
michael@0 | 840 | code = """int |
michael@0 | 841 | %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, |
michael@0 | 842 | const %(ctype)s value) |
michael@0 | 843 | { |
michael@0 | 844 | struct evbuffer *tmp = NULL; |
michael@0 | 845 | if (msg->%(name)s_set) { |
michael@0 | 846 | %(refname)s_clear(msg->%(name)s_data); |
michael@0 | 847 | msg->%(name)s_set = 0; |
michael@0 | 848 | } else { |
michael@0 | 849 | msg->%(name)s_data = %(refname)s_new(); |
michael@0 | 850 | if (msg->%(name)s_data == NULL) { |
michael@0 | 851 | event_warn("%%s: %(refname)s_new()", __func__); |
michael@0 | 852 | goto error; |
michael@0 | 853 | } |
michael@0 | 854 | } |
michael@0 | 855 | if ((tmp = evbuffer_new()) == NULL) { |
michael@0 | 856 | event_warn("%%s: evbuffer_new()", __func__); |
michael@0 | 857 | goto error; |
michael@0 | 858 | } |
michael@0 | 859 | %(refname)s_marshal(tmp, value); |
michael@0 | 860 | if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) { |
michael@0 | 861 | event_warnx("%%s: %(refname)s_unmarshal", __func__); |
michael@0 | 862 | goto error; |
michael@0 | 863 | } |
michael@0 | 864 | msg->%(name)s_set = 1; |
michael@0 | 865 | evbuffer_free(tmp); |
michael@0 | 866 | return (0); |
michael@0 | 867 | error: |
michael@0 | 868 | if (tmp != NULL) |
michael@0 | 869 | evbuffer_free(tmp); |
michael@0 | 870 | if (msg->%(name)s_data != NULL) { |
michael@0 | 871 | %(refname)s_free(msg->%(name)s_data); |
michael@0 | 872 | msg->%(name)s_data = NULL; |
michael@0 | 873 | } |
michael@0 | 874 | return (-1); |
michael@0 | 875 | }""" % self.GetTranslation() |
michael@0 | 876 | return code.split('\n') |
michael@0 | 877 | |
michael@0 | 878 | def CodeComplete(self, structname, var_name): |
michael@0 | 879 | code = [ 'if (%(structname)s->%(name)s_set && ' |
michael@0 | 880 | '%(refname)s_complete(%(var)s) == -1)', |
michael@0 | 881 | ' return (-1);' ] |
michael@0 | 882 | |
michael@0 | 883 | return TranslateList(code, self.GetTranslation({ |
michael@0 | 884 | 'structname' : structname, |
michael@0 | 885 | 'var' : var_name })) |
michael@0 | 886 | |
michael@0 | 887 | def CodeUnmarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 888 | code = ['%(var)s = %(refname)s_new();', |
michael@0 | 889 | 'if (%(var)s == NULL)', |
michael@0 | 890 | ' return (-1);', |
michael@0 | 891 | 'if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag)s, ' |
michael@0 | 892 | '%(var)s) == -1) {', |
michael@0 | 893 | ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', |
michael@0 | 894 | ' return (-1);', |
michael@0 | 895 | '}' |
michael@0 | 896 | ] |
michael@0 | 897 | code = '\n'.join(code) % self.GetTranslation({ |
michael@0 | 898 | 'buf' : buf, |
michael@0 | 899 | 'tag' : tag_name, |
michael@0 | 900 | 'var' : var_name }) |
michael@0 | 901 | return code.split('\n') |
michael@0 | 902 | |
michael@0 | 903 | def CodeMarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 904 | code = ['evtag_marshal_%s(%s, %s, %s);' % ( |
michael@0 | 905 | self._refname, buf, tag_name, var_name)] |
michael@0 | 906 | return code |
michael@0 | 907 | |
michael@0 | 908 | def CodeClear(self, structname): |
michael@0 | 909 | code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), |
michael@0 | 910 | ' %s_free(%s->%s_data);' % ( |
michael@0 | 911 | self._refname, structname, self.Name()), |
michael@0 | 912 | ' %s->%s_data = NULL;' % (structname, self.Name()), |
michael@0 | 913 | ' %s->%s_set = 0;' % (structname, self.Name()), |
michael@0 | 914 | '}' |
michael@0 | 915 | ] |
michael@0 | 916 | |
michael@0 | 917 | return code |
michael@0 | 918 | |
michael@0 | 919 | def CodeInitialize(self, name): |
michael@0 | 920 | code = ['%s->%s_data = NULL;' % (name, self._name)] |
michael@0 | 921 | return code |
michael@0 | 922 | |
michael@0 | 923 | def CodeFree(self, name): |
michael@0 | 924 | code = ['if (%s->%s_data != NULL)' % (name, self._name), |
michael@0 | 925 | ' %s_free(%s->%s_data);' % ( |
michael@0 | 926 | self._refname, name, self._name)] |
michael@0 | 927 | |
michael@0 | 928 | return code |
michael@0 | 929 | |
michael@0 | 930 | def Declaration(self): |
michael@0 | 931 | dcl = ['%s %s_data;' % (self._ctype, self._name)] |
michael@0 | 932 | |
michael@0 | 933 | return dcl |
michael@0 | 934 | |
michael@0 | 935 | class EntryVarBytes(Entry): |
michael@0 | 936 | def __init__(self, type, name, tag): |
michael@0 | 937 | # Init base class |
michael@0 | 938 | Entry.__init__(self, type, name, tag) |
michael@0 | 939 | |
michael@0 | 940 | self._ctype = 'ev_uint8_t *' |
michael@0 | 941 | |
michael@0 | 942 | def GetInitializer(self): |
michael@0 | 943 | return "NULL" |
michael@0 | 944 | |
michael@0 | 945 | def GetVarLen(self, var): |
michael@0 | 946 | return '%(var)s->%(name)s_length' % self.GetTranslation({ 'var' : var }) |
michael@0 | 947 | |
michael@0 | 948 | def CodeArrayAdd(self, varname, value): |
michael@0 | 949 | # xxx: copy |
michael@0 | 950 | return [ '%(varname)s = NULL;' % { 'varname' : varname } ] |
michael@0 | 951 | |
michael@0 | 952 | def GetDeclaration(self, funcname): |
michael@0 | 953 | code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % ( |
michael@0 | 954 | funcname, self._struct.Name(), self._ctype ) ] |
michael@0 | 955 | return code |
michael@0 | 956 | |
michael@0 | 957 | def AssignDeclaration(self, funcname): |
michael@0 | 958 | code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % ( |
michael@0 | 959 | funcname, self._struct.Name(), self._ctype ) ] |
michael@0 | 960 | return code |
michael@0 | 961 | |
michael@0 | 962 | def CodeAssign(self): |
michael@0 | 963 | name = self._name |
michael@0 | 964 | code = [ 'int', |
michael@0 | 965 | '%s_%s_assign(struct %s *msg, ' |
michael@0 | 966 | 'const %s value, ev_uint32_t len)' % ( |
michael@0 | 967 | self._struct.Name(), name, |
michael@0 | 968 | self._struct.Name(), self._ctype), |
michael@0 | 969 | '{', |
michael@0 | 970 | ' if (msg->%s_data != NULL)' % name, |
michael@0 | 971 | ' free (msg->%s_data);' % name, |
michael@0 | 972 | ' msg->%s_data = malloc(len);' % name, |
michael@0 | 973 | ' if (msg->%s_data == NULL)' % name, |
michael@0 | 974 | ' return (-1);', |
michael@0 | 975 | ' msg->%s_set = 1;' % name, |
michael@0 | 976 | ' msg->%s_length = len;' % name, |
michael@0 | 977 | ' memcpy(msg->%s_data, value, len);' % name, |
michael@0 | 978 | ' return (0);', |
michael@0 | 979 | '}' ] |
michael@0 | 980 | return code |
michael@0 | 981 | |
michael@0 | 982 | def CodeGet(self): |
michael@0 | 983 | name = self._name |
michael@0 | 984 | code = [ 'int', |
michael@0 | 985 | '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % ( |
michael@0 | 986 | self._struct.Name(), name, |
michael@0 | 987 | self._struct.Name(), self._ctype), |
michael@0 | 988 | '{', |
michael@0 | 989 | ' if (msg->%s_set != 1)' % name, |
michael@0 | 990 | ' return (-1);', |
michael@0 | 991 | ' *value = msg->%s_data;' % name, |
michael@0 | 992 | ' *plen = msg->%s_length;' % name, |
michael@0 | 993 | ' return (0);', |
michael@0 | 994 | '}' ] |
michael@0 | 995 | return code |
michael@0 | 996 | |
michael@0 | 997 | def CodeUnmarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 998 | code = ['if (evtag_payload_length(%(buf)s, &%(varlen)s) == -1)', |
michael@0 | 999 | ' return (-1);', |
michael@0 | 1000 | # We do not want DoS opportunities |
michael@0 | 1001 | 'if (%(varlen)s > evbuffer_get_length(%(buf)s))', |
michael@0 | 1002 | ' return (-1);', |
michael@0 | 1003 | 'if ((%(var)s = malloc(%(varlen)s)) == NULL)', |
michael@0 | 1004 | ' return (-1);', |
michael@0 | 1005 | 'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, %(var)s, ' |
michael@0 | 1006 | '%(varlen)s) == -1) {', |
michael@0 | 1007 | ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', |
michael@0 | 1008 | ' return (-1);', |
michael@0 | 1009 | '}' |
michael@0 | 1010 | ] |
michael@0 | 1011 | code = '\n'.join(code) % self.GetTranslation({ |
michael@0 | 1012 | 'buf' : buf, |
michael@0 | 1013 | 'tag' : tag_name, |
michael@0 | 1014 | 'var' : var_name, |
michael@0 | 1015 | 'varlen' : var_len }) |
michael@0 | 1016 | return code.split('\n') |
michael@0 | 1017 | |
michael@0 | 1018 | def CodeMarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 1019 | code = ['evtag_marshal(%s, %s, %s, %s);' % ( |
michael@0 | 1020 | buf, tag_name, var_name, var_len)] |
michael@0 | 1021 | return code |
michael@0 | 1022 | |
michael@0 | 1023 | def CodeClear(self, structname): |
michael@0 | 1024 | code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), |
michael@0 | 1025 | ' free (%s->%s_data);' % (structname, self.Name()), |
michael@0 | 1026 | ' %s->%s_data = NULL;' % (structname, self.Name()), |
michael@0 | 1027 | ' %s->%s_length = 0;' % (structname, self.Name()), |
michael@0 | 1028 | ' %s->%s_set = 0;' % (structname, self.Name()), |
michael@0 | 1029 | '}' |
michael@0 | 1030 | ] |
michael@0 | 1031 | |
michael@0 | 1032 | return code |
michael@0 | 1033 | |
michael@0 | 1034 | def CodeInitialize(self, name): |
michael@0 | 1035 | code = ['%s->%s_data = NULL;' % (name, self._name), |
michael@0 | 1036 | '%s->%s_length = 0;' % (name, self._name) ] |
michael@0 | 1037 | return code |
michael@0 | 1038 | |
michael@0 | 1039 | def CodeFree(self, name): |
michael@0 | 1040 | code = ['if (%s->%s_data != NULL)' % (name, self._name), |
michael@0 | 1041 | ' free(%s->%s_data);' % (name, self._name)] |
michael@0 | 1042 | |
michael@0 | 1043 | return code |
michael@0 | 1044 | |
michael@0 | 1045 | def Declaration(self): |
michael@0 | 1046 | dcl = ['ev_uint8_t *%s_data;' % self._name, |
michael@0 | 1047 | 'ev_uint32_t %s_length;' % self._name] |
michael@0 | 1048 | |
michael@0 | 1049 | return dcl |
michael@0 | 1050 | |
michael@0 | 1051 | class EntryArray(Entry): |
michael@0 | 1052 | def __init__(self, entry): |
michael@0 | 1053 | # Init base class |
michael@0 | 1054 | Entry.__init__(self, entry._type, entry._name, entry._tag) |
michael@0 | 1055 | |
michael@0 | 1056 | self._entry = entry |
michael@0 | 1057 | self._refname = entry._refname |
michael@0 | 1058 | self._ctype = self._entry._ctype |
michael@0 | 1059 | self._optional = True |
michael@0 | 1060 | self._optpointer = self._entry._optpointer |
michael@0 | 1061 | self._optaddarg = self._entry._optaddarg |
michael@0 | 1062 | |
michael@0 | 1063 | # provide a new function for accessing the variable name |
michael@0 | 1064 | def GetVarName(var_name): |
michael@0 | 1065 | return '%(var)s->%(name)s_data[%(index)s]' % \ |
michael@0 | 1066 | self._entry.GetTranslation({'var' : var_name, |
michael@0 | 1067 | 'index' : self._index}) |
michael@0 | 1068 | self._entry.GetVarName = GetVarName |
michael@0 | 1069 | |
michael@0 | 1070 | def GetInitializer(self): |
michael@0 | 1071 | return "NULL" |
michael@0 | 1072 | |
michael@0 | 1073 | def GetVarName(self, var_name): |
michael@0 | 1074 | return var_name |
michael@0 | 1075 | |
michael@0 | 1076 | def GetVarLen(self, var_name): |
michael@0 | 1077 | return '-1' |
michael@0 | 1078 | |
michael@0 | 1079 | def GetDeclaration(self, funcname): |
michael@0 | 1080 | """Allows direct access to elements of the array.""" |
michael@0 | 1081 | code = [ |
michael@0 | 1082 | 'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' % |
michael@0 | 1083 | self.GetTranslation({ 'funcname' : funcname }) ] |
michael@0 | 1084 | return code |
michael@0 | 1085 | |
michael@0 | 1086 | def AssignDeclaration(self, funcname): |
michael@0 | 1087 | code = [ 'int %s(struct %s *, int, const %s);' % ( |
michael@0 | 1088 | funcname, self._struct.Name(), self._ctype ) ] |
michael@0 | 1089 | return code |
michael@0 | 1090 | |
michael@0 | 1091 | def AddDeclaration(self, funcname): |
michael@0 | 1092 | code = [ |
michael@0 | 1093 | '%(ctype)s %(optpointer)s ' |
michael@0 | 1094 | '%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);' % \ |
michael@0 | 1095 | self.GetTranslation({ 'funcname' : funcname }) ] |
michael@0 | 1096 | return code |
michael@0 | 1097 | |
michael@0 | 1098 | def CodeGet(self): |
michael@0 | 1099 | code = """int |
michael@0 | 1100 | %(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset, |
michael@0 | 1101 | %(ctype)s *value) |
michael@0 | 1102 | { |
michael@0 | 1103 | if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length) |
michael@0 | 1104 | return (-1); |
michael@0 | 1105 | *value = msg->%(name)s_data[offset]; |
michael@0 | 1106 | return (0); |
michael@0 | 1107 | }""" % self.GetTranslation() |
michael@0 | 1108 | |
michael@0 | 1109 | return code.split('\n') |
michael@0 | 1110 | |
michael@0 | 1111 | def CodeAssign(self): |
michael@0 | 1112 | code = [ |
michael@0 | 1113 | 'int', |
michael@0 | 1114 | '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,', |
michael@0 | 1115 | ' const %(ctype)s value)', |
michael@0 | 1116 | '{', |
michael@0 | 1117 | ' if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)', |
michael@0 | 1118 | ' return (-1);\n', |
michael@0 | 1119 | ' {' ] |
michael@0 | 1120 | code = TranslateList(code, self.GetTranslation()) |
michael@0 | 1121 | |
michael@0 | 1122 | codearrayassign = self._entry.CodeArrayAssign( |
michael@0 | 1123 | 'msg->%(name)s_data[off]' % self.GetTranslation(), 'value') |
michael@0 | 1124 | code += map(lambda x: ' ' + x, codearrayassign) |
michael@0 | 1125 | |
michael@0 | 1126 | code += TranslateList([ |
michael@0 | 1127 | ' }', |
michael@0 | 1128 | ' return (0);', |
michael@0 | 1129 | '}' ], self.GetTranslation()) |
michael@0 | 1130 | |
michael@0 | 1131 | return code |
michael@0 | 1132 | |
michael@0 | 1133 | def CodeAdd(self): |
michael@0 | 1134 | codearrayadd = self._entry.CodeArrayAdd( |
michael@0 | 1135 | 'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(), |
michael@0 | 1136 | 'value') |
michael@0 | 1137 | code = [ |
michael@0 | 1138 | 'static int', |
michael@0 | 1139 | '%(parent_name)s_%(name)s_expand_to_hold_more(' |
michael@0 | 1140 | 'struct %(parent_name)s *msg)', |
michael@0 | 1141 | '{', |
michael@0 | 1142 | ' int tobe_allocated = msg->%(name)s_num_allocated;', |
michael@0 | 1143 | ' %(ctype)s* new_data = NULL;', |
michael@0 | 1144 | ' tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;', |
michael@0 | 1145 | ' new_data = (%(ctype)s*) realloc(msg->%(name)s_data,', |
michael@0 | 1146 | ' tobe_allocated * sizeof(%(ctype)s));', |
michael@0 | 1147 | ' if (new_data == NULL)', |
michael@0 | 1148 | ' return -1;', |
michael@0 | 1149 | ' msg->%(name)s_data = new_data;', |
michael@0 | 1150 | ' msg->%(name)s_num_allocated = tobe_allocated;', |
michael@0 | 1151 | ' return 0;' |
michael@0 | 1152 | '}', |
michael@0 | 1153 | '', |
michael@0 | 1154 | '%(ctype)s %(optpointer)s', |
michael@0 | 1155 | '%(parent_name)s_%(name)s_add(' |
michael@0 | 1156 | 'struct %(parent_name)s *msg%(optaddarg)s)', |
michael@0 | 1157 | '{', |
michael@0 | 1158 | ' if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {', |
michael@0 | 1159 | ' if (%(parent_name)s_%(name)s_expand_to_hold_more(msg)<0)', |
michael@0 | 1160 | ' goto error;', |
michael@0 | 1161 | ' }' ] |
michael@0 | 1162 | |
michael@0 | 1163 | code = TranslateList(code, self.GetTranslation()) |
michael@0 | 1164 | |
michael@0 | 1165 | code += map(lambda x: ' ' + x, codearrayadd) |
michael@0 | 1166 | |
michael@0 | 1167 | code += TranslateList([ |
michael@0 | 1168 | ' msg->%(name)s_set = 1;', |
michael@0 | 1169 | ' return %(optreference)s(msg->%(name)s_data[' |
michael@0 | 1170 | 'msg->%(name)s_length - 1]);', |
michael@0 | 1171 | 'error:', |
michael@0 | 1172 | ' --msg->%(name)s_length;', |
michael@0 | 1173 | ' return (NULL);', |
michael@0 | 1174 | '}' ], self.GetTranslation()) |
michael@0 | 1175 | |
michael@0 | 1176 | return code |
michael@0 | 1177 | |
michael@0 | 1178 | def CodeComplete(self, structname, var_name): |
michael@0 | 1179 | self._index = 'i' |
michael@0 | 1180 | tmp = self._entry.CodeComplete(structname, self._entry.GetVarName(var_name)) |
michael@0 | 1181 | # skip the whole loop if there is nothing to check |
michael@0 | 1182 | if not tmp: |
michael@0 | 1183 | return [] |
michael@0 | 1184 | |
michael@0 | 1185 | translate = self.GetTranslation({ 'structname' : structname }) |
michael@0 | 1186 | code = [ |
michael@0 | 1187 | '{', |
michael@0 | 1188 | ' int i;', |
michael@0 | 1189 | ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ] |
michael@0 | 1190 | |
michael@0 | 1191 | code = TranslateList(code, translate) |
michael@0 | 1192 | |
michael@0 | 1193 | code += map(lambda x: ' ' + x, tmp) |
michael@0 | 1194 | |
michael@0 | 1195 | code += [ |
michael@0 | 1196 | ' }', |
michael@0 | 1197 | '}' ] |
michael@0 | 1198 | |
michael@0 | 1199 | return code |
michael@0 | 1200 | |
michael@0 | 1201 | def CodeUnmarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 1202 | translate = self.GetTranslation({ 'var' : var_name, |
michael@0 | 1203 | 'buf' : buf, |
michael@0 | 1204 | 'tag' : tag_name, |
michael@0 | 1205 | 'init' : self._entry.GetInitializer()}) |
michael@0 | 1206 | code = [ |
michael@0 | 1207 | 'if (%(var)s->%(name)s_length >= %(var)s->%(name)s_num_allocated &&', |
michael@0 | 1208 | ' %(parent_name)s_%(name)s_expand_to_hold_more(%(var)s) < 0) {', |
michael@0 | 1209 | ' puts("HEY NOW");', |
michael@0 | 1210 | ' return (-1);', |
michael@0 | 1211 | '}'] |
michael@0 | 1212 | |
michael@0 | 1213 | # the unmarshal code directly returns |
michael@0 | 1214 | code = TranslateList(code, translate) |
michael@0 | 1215 | |
michael@0 | 1216 | self._index = '%(var)s->%(name)s_length' % translate |
michael@0 | 1217 | code += self._entry.CodeUnmarshal(buf, tag_name, |
michael@0 | 1218 | self._entry.GetVarName(var_name), |
michael@0 | 1219 | self._entry.GetVarLen(var_name)) |
michael@0 | 1220 | |
michael@0 | 1221 | code += [ '++%(var)s->%(name)s_length;' % translate ] |
michael@0 | 1222 | |
michael@0 | 1223 | return code |
michael@0 | 1224 | |
michael@0 | 1225 | def CodeMarshal(self, buf, tag_name, var_name, var_len): |
michael@0 | 1226 | code = ['{', |
michael@0 | 1227 | ' int i;', |
michael@0 | 1228 | ' for (i = 0; i < %(var)s->%(name)s_length; ++i) {' ] |
michael@0 | 1229 | |
michael@0 | 1230 | self._index = 'i' |
michael@0 | 1231 | code += self._entry.CodeMarshal(buf, tag_name, |
michael@0 | 1232 | self._entry.GetVarName(var_name), |
michael@0 | 1233 | self._entry.GetVarLen(var_name)) |
michael@0 | 1234 | code += [' }', |
michael@0 | 1235 | '}' |
michael@0 | 1236 | ] |
michael@0 | 1237 | |
michael@0 | 1238 | code = "\n".join(code) % self.GetTranslation({ 'var' : var_name }) |
michael@0 | 1239 | |
michael@0 | 1240 | return code.split('\n') |
michael@0 | 1241 | |
michael@0 | 1242 | def CodeClear(self, structname): |
michael@0 | 1243 | translate = self.GetTranslation({ 'structname' : structname }) |
michael@0 | 1244 | codearrayfree = self._entry.CodeArrayFree( |
michael@0 | 1245 | '%(structname)s->%(name)s_data[i]' % self.GetTranslation( |
michael@0 | 1246 | { 'structname' : structname } )) |
michael@0 | 1247 | |
michael@0 | 1248 | code = [ 'if (%(structname)s->%(name)s_set == 1) {' ] |
michael@0 | 1249 | |
michael@0 | 1250 | if codearrayfree: |
michael@0 | 1251 | code += [ |
michael@0 | 1252 | ' int i;', |
michael@0 | 1253 | ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ] |
michael@0 | 1254 | |
michael@0 | 1255 | code = TranslateList(code, translate) |
michael@0 | 1256 | |
michael@0 | 1257 | if codearrayfree: |
michael@0 | 1258 | code += map(lambda x: ' ' + x, codearrayfree) |
michael@0 | 1259 | code += [ |
michael@0 | 1260 | ' }' ] |
michael@0 | 1261 | |
michael@0 | 1262 | code += TranslateList([ |
michael@0 | 1263 | ' free(%(structname)s->%(name)s_data);', |
michael@0 | 1264 | ' %(structname)s->%(name)s_data = NULL;', |
michael@0 | 1265 | ' %(structname)s->%(name)s_set = 0;', |
michael@0 | 1266 | ' %(structname)s->%(name)s_length = 0;', |
michael@0 | 1267 | ' %(structname)s->%(name)s_num_allocated = 0;', |
michael@0 | 1268 | '}' |
michael@0 | 1269 | ], translate) |
michael@0 | 1270 | |
michael@0 | 1271 | return code |
michael@0 | 1272 | |
michael@0 | 1273 | def CodeInitialize(self, name): |
michael@0 | 1274 | code = ['%s->%s_data = NULL;' % (name, self._name), |
michael@0 | 1275 | '%s->%s_length = 0;' % (name, self._name), |
michael@0 | 1276 | '%s->%s_num_allocated = 0;' % (name, self._name)] |
michael@0 | 1277 | return code |
michael@0 | 1278 | |
michael@0 | 1279 | def CodeFree(self, structname): |
michael@0 | 1280 | code = self.CodeClear(structname); |
michael@0 | 1281 | |
michael@0 | 1282 | code += TranslateList([ |
michael@0 | 1283 | 'free(%(structname)s->%(name)s_data);' ], |
michael@0 | 1284 | self.GetTranslation({'structname' : structname })) |
michael@0 | 1285 | |
michael@0 | 1286 | return code |
michael@0 | 1287 | |
michael@0 | 1288 | def Declaration(self): |
michael@0 | 1289 | dcl = ['%s *%s_data;' % (self._ctype, self._name), |
michael@0 | 1290 | 'int %s_length;' % self._name, |
michael@0 | 1291 | 'int %s_num_allocated;' % self._name ] |
michael@0 | 1292 | |
michael@0 | 1293 | return dcl |
michael@0 | 1294 | |
michael@0 | 1295 | def NormalizeLine(line): |
michael@0 | 1296 | global white |
michael@0 | 1297 | global cppcomment |
michael@0 | 1298 | |
michael@0 | 1299 | line = cppcomment.sub('', line) |
michael@0 | 1300 | line = line.strip() |
michael@0 | 1301 | line = white.sub(' ', line) |
michael@0 | 1302 | |
michael@0 | 1303 | return line |
michael@0 | 1304 | |
michael@0 | 1305 | def ProcessOneEntry(factory, newstruct, entry): |
michael@0 | 1306 | optional = 0 |
michael@0 | 1307 | array = 0 |
michael@0 | 1308 | entry_type = '' |
michael@0 | 1309 | name = '' |
michael@0 | 1310 | tag = '' |
michael@0 | 1311 | tag_set = None |
michael@0 | 1312 | separator = '' |
michael@0 | 1313 | fixed_length = '' |
michael@0 | 1314 | |
michael@0 | 1315 | tokens = entry.split(' ') |
michael@0 | 1316 | while tokens: |
michael@0 | 1317 | token = tokens[0] |
michael@0 | 1318 | tokens = tokens[1:] |
michael@0 | 1319 | |
michael@0 | 1320 | if not entry_type: |
michael@0 | 1321 | if not optional and token == 'optional': |
michael@0 | 1322 | optional = 1 |
michael@0 | 1323 | continue |
michael@0 | 1324 | |
michael@0 | 1325 | if not array and token == 'array': |
michael@0 | 1326 | array = 1 |
michael@0 | 1327 | continue |
michael@0 | 1328 | |
michael@0 | 1329 | if not entry_type: |
michael@0 | 1330 | entry_type = token |
michael@0 | 1331 | continue |
michael@0 | 1332 | |
michael@0 | 1333 | if not name: |
michael@0 | 1334 | res = re.match(r'^([^\[\]]+)(\[.*\])?$', token) |
michael@0 | 1335 | if not res: |
michael@0 | 1336 | raise RpcGenError( |
michael@0 | 1337 | 'Cannot parse name: \"%s\" ' |
michael@0 | 1338 | 'around line %d' % (entry, line_count)) |
michael@0 | 1339 | name = res.group(1) |
michael@0 | 1340 | fixed_length = res.group(2) |
michael@0 | 1341 | if fixed_length: |
michael@0 | 1342 | fixed_length = fixed_length[1:-1] |
michael@0 | 1343 | continue |
michael@0 | 1344 | |
michael@0 | 1345 | if not separator: |
michael@0 | 1346 | separator = token |
michael@0 | 1347 | if separator != '=': |
michael@0 | 1348 | raise RpcGenError('Expected "=" after name \"%s\" got %s' |
michael@0 | 1349 | % (name, token)) |
michael@0 | 1350 | continue |
michael@0 | 1351 | |
michael@0 | 1352 | if not tag_set: |
michael@0 | 1353 | tag_set = 1 |
michael@0 | 1354 | if not re.match(r'^(0x)?[0-9]+$', token): |
michael@0 | 1355 | raise RpcGenError('Expected tag number: \"%s\"' % entry) |
michael@0 | 1356 | tag = int(token, 0) |
michael@0 | 1357 | continue |
michael@0 | 1358 | |
michael@0 | 1359 | raise RpcGenError('Cannot parse \"%s\"' % entry) |
michael@0 | 1360 | |
michael@0 | 1361 | if not tag_set: |
michael@0 | 1362 | raise RpcGenError('Need tag number: \"%s\"' % entry) |
michael@0 | 1363 | |
michael@0 | 1364 | # Create the right entry |
michael@0 | 1365 | if entry_type == 'bytes': |
michael@0 | 1366 | if fixed_length: |
michael@0 | 1367 | newentry = factory.EntryBytes(entry_type, name, tag, fixed_length) |
michael@0 | 1368 | else: |
michael@0 | 1369 | newentry = factory.EntryVarBytes(entry_type, name, tag) |
michael@0 | 1370 | elif entry_type == 'int' and not fixed_length: |
michael@0 | 1371 | newentry = factory.EntryInt(entry_type, name, tag) |
michael@0 | 1372 | elif entry_type == 'int64' and not fixed_length: |
michael@0 | 1373 | newentry = factory.EntryInt(entry_type, name, tag, bits=64) |
michael@0 | 1374 | elif entry_type == 'string' and not fixed_length: |
michael@0 | 1375 | newentry = factory.EntryString(entry_type, name, tag) |
michael@0 | 1376 | else: |
michael@0 | 1377 | res = structref.match(entry_type) |
michael@0 | 1378 | if res: |
michael@0 | 1379 | # References another struct defined in our file |
michael@0 | 1380 | newentry = factory.EntryStruct(entry_type, name, tag, res.group(1)) |
michael@0 | 1381 | else: |
michael@0 | 1382 | raise RpcGenError('Bad type: "%s" in "%s"' % (entry_type, entry)) |
michael@0 | 1383 | |
michael@0 | 1384 | structs = [] |
michael@0 | 1385 | |
michael@0 | 1386 | if optional: |
michael@0 | 1387 | newentry.MakeOptional() |
michael@0 | 1388 | if array: |
michael@0 | 1389 | newentry.MakeArray() |
michael@0 | 1390 | |
michael@0 | 1391 | newentry.SetStruct(newstruct) |
michael@0 | 1392 | newentry.SetLineCount(line_count) |
michael@0 | 1393 | newentry.Verify() |
michael@0 | 1394 | |
michael@0 | 1395 | if array: |
michael@0 | 1396 | # We need to encapsulate this entry into a struct |
michael@0 | 1397 | newname = newentry.Name()+ '_array' |
michael@0 | 1398 | |
michael@0 | 1399 | # Now borgify the new entry. |
michael@0 | 1400 | newentry = factory.EntryArray(newentry) |
michael@0 | 1401 | newentry.SetStruct(newstruct) |
michael@0 | 1402 | newentry.SetLineCount(line_count) |
michael@0 | 1403 | newentry.MakeArray() |
michael@0 | 1404 | |
michael@0 | 1405 | newstruct.AddEntry(newentry) |
michael@0 | 1406 | |
michael@0 | 1407 | return structs |
michael@0 | 1408 | |
michael@0 | 1409 | def ProcessStruct(factory, data): |
michael@0 | 1410 | tokens = data.split(' ') |
michael@0 | 1411 | |
michael@0 | 1412 | # First three tokens are: 'struct' 'name' '{' |
michael@0 | 1413 | newstruct = factory.Struct(tokens[1]) |
michael@0 | 1414 | |
michael@0 | 1415 | inside = ' '.join(tokens[3:-1]) |
michael@0 | 1416 | |
michael@0 | 1417 | tokens = inside.split(';') |
michael@0 | 1418 | |
michael@0 | 1419 | structs = [] |
michael@0 | 1420 | |
michael@0 | 1421 | for entry in tokens: |
michael@0 | 1422 | entry = NormalizeLine(entry) |
michael@0 | 1423 | if not entry: |
michael@0 | 1424 | continue |
michael@0 | 1425 | |
michael@0 | 1426 | # It's possible that new structs get defined in here |
michael@0 | 1427 | structs.extend(ProcessOneEntry(factory, newstruct, entry)) |
michael@0 | 1428 | |
michael@0 | 1429 | structs.append(newstruct) |
michael@0 | 1430 | return structs |
michael@0 | 1431 | |
michael@0 | 1432 | def GetNextStruct(file): |
michael@0 | 1433 | global line_count |
michael@0 | 1434 | global cppdirect |
michael@0 | 1435 | |
michael@0 | 1436 | got_struct = 0 |
michael@0 | 1437 | |
michael@0 | 1438 | processed_lines = [] |
michael@0 | 1439 | |
michael@0 | 1440 | have_c_comment = 0 |
michael@0 | 1441 | data = '' |
michael@0 | 1442 | while 1: |
michael@0 | 1443 | line = file.readline() |
michael@0 | 1444 | if not line: |
michael@0 | 1445 | break |
michael@0 | 1446 | |
michael@0 | 1447 | line_count += 1 |
michael@0 | 1448 | line = line[:-1] |
michael@0 | 1449 | |
michael@0 | 1450 | if not have_c_comment and re.search(r'/\*', line): |
michael@0 | 1451 | if re.search(r'/\*.*?\*/', line): |
michael@0 | 1452 | line = re.sub(r'/\*.*?\*/', '', line) |
michael@0 | 1453 | else: |
michael@0 | 1454 | line = re.sub(r'/\*.*$', '', line) |
michael@0 | 1455 | have_c_comment = 1 |
michael@0 | 1456 | |
michael@0 | 1457 | if have_c_comment: |
michael@0 | 1458 | if not re.search(r'\*/', line): |
michael@0 | 1459 | continue |
michael@0 | 1460 | have_c_comment = 0 |
michael@0 | 1461 | line = re.sub(r'^.*\*/', '', line) |
michael@0 | 1462 | |
michael@0 | 1463 | line = NormalizeLine(line) |
michael@0 | 1464 | |
michael@0 | 1465 | if not line: |
michael@0 | 1466 | continue |
michael@0 | 1467 | |
michael@0 | 1468 | if not got_struct: |
michael@0 | 1469 | if re.match(r'#include ["<].*[>"]', line): |
michael@0 | 1470 | cppdirect.append(line) |
michael@0 | 1471 | continue |
michael@0 | 1472 | |
michael@0 | 1473 | if re.match(r'^#(if( |def)|endif)', line): |
michael@0 | 1474 | cppdirect.append(line) |
michael@0 | 1475 | continue |
michael@0 | 1476 | |
michael@0 | 1477 | if re.match(r'^#define', line): |
michael@0 | 1478 | headerdirect.append(line) |
michael@0 | 1479 | continue |
michael@0 | 1480 | |
michael@0 | 1481 | if not structdef.match(line): |
michael@0 | 1482 | raise RpcGenError('Missing struct on line %d: %s' |
michael@0 | 1483 | % (line_count, line)) |
michael@0 | 1484 | else: |
michael@0 | 1485 | got_struct = 1 |
michael@0 | 1486 | data += line |
michael@0 | 1487 | continue |
michael@0 | 1488 | |
michael@0 | 1489 | # We are inside the struct |
michael@0 | 1490 | tokens = line.split('}') |
michael@0 | 1491 | if len(tokens) == 1: |
michael@0 | 1492 | data += ' ' + line |
michael@0 | 1493 | continue |
michael@0 | 1494 | |
michael@0 | 1495 | if len(tokens[1]): |
michael@0 | 1496 | raise RpcGenError('Trailing garbage after struct on line %d' |
michael@0 | 1497 | % line_count) |
michael@0 | 1498 | |
michael@0 | 1499 | # We found the end of the struct |
michael@0 | 1500 | data += ' %s}' % tokens[0] |
michael@0 | 1501 | break |
michael@0 | 1502 | |
michael@0 | 1503 | # Remove any comments, that might be in there |
michael@0 | 1504 | data = re.sub(r'/\*.*\*/', '', data) |
michael@0 | 1505 | |
michael@0 | 1506 | return data |
michael@0 | 1507 | |
michael@0 | 1508 | |
michael@0 | 1509 | def Parse(factory, file): |
michael@0 | 1510 | """ |
michael@0 | 1511 | Parses the input file and returns C code and corresponding header file. |
michael@0 | 1512 | """ |
michael@0 | 1513 | |
michael@0 | 1514 | entities = [] |
michael@0 | 1515 | |
michael@0 | 1516 | while 1: |
michael@0 | 1517 | # Just gets the whole struct nicely formatted |
michael@0 | 1518 | data = GetNextStruct(file) |
michael@0 | 1519 | |
michael@0 | 1520 | if not data: |
michael@0 | 1521 | break |
michael@0 | 1522 | |
michael@0 | 1523 | entities.extend(ProcessStruct(factory, data)) |
michael@0 | 1524 | |
michael@0 | 1525 | return entities |
michael@0 | 1526 | |
michael@0 | 1527 | class CCodeGenerator: |
michael@0 | 1528 | def __init__(self): |
michael@0 | 1529 | pass |
michael@0 | 1530 | |
michael@0 | 1531 | def GuardName(self, name): |
michael@0 | 1532 | # Use the complete provided path to the input file, with all |
michael@0 | 1533 | # non-identifier characters replaced with underscores, to |
michael@0 | 1534 | # reduce the chance of a collision between guard macros. |
michael@0 | 1535 | return '_' + nonident.sub('_', name).upper() + '_' |
michael@0 | 1536 | |
michael@0 | 1537 | def HeaderPreamble(self, name): |
michael@0 | 1538 | guard = self.GuardName(name) |
michael@0 | 1539 | pre = ( |
michael@0 | 1540 | '/*\n' |
michael@0 | 1541 | ' * Automatically generated from %s\n' |
michael@0 | 1542 | ' */\n\n' |
michael@0 | 1543 | '#ifndef %s\n' |
michael@0 | 1544 | '#define %s\n\n' ) % ( |
michael@0 | 1545 | name, guard, guard) |
michael@0 | 1546 | |
michael@0 | 1547 | for statement in headerdirect: |
michael@0 | 1548 | pre += '%s\n' % statement |
michael@0 | 1549 | if headerdirect: |
michael@0 | 1550 | pre += '\n' |
michael@0 | 1551 | |
michael@0 | 1552 | pre += ( |
michael@0 | 1553 | '#include <event2/util.h> /* for ev_uint*_t */\n' |
michael@0 | 1554 | '#include <event2/rpc.h>\n' |
michael@0 | 1555 | ) |
michael@0 | 1556 | |
michael@0 | 1557 | return pre |
michael@0 | 1558 | |
michael@0 | 1559 | def HeaderPostamble(self, name): |
michael@0 | 1560 | guard = self.GuardName(name) |
michael@0 | 1561 | return '#endif /* %s */' % guard |
michael@0 | 1562 | |
michael@0 | 1563 | def BodyPreamble(self, name, header_file): |
michael@0 | 1564 | global _NAME |
michael@0 | 1565 | global _VERSION |
michael@0 | 1566 | |
michael@0 | 1567 | slash = header_file.rfind('/') |
michael@0 | 1568 | if slash != -1: |
michael@0 | 1569 | header_file = header_file[slash+1:] |
michael@0 | 1570 | |
michael@0 | 1571 | pre = ( '/*\n' |
michael@0 | 1572 | ' * Automatically generated from %s\n' |
michael@0 | 1573 | ' * by %s/%s. DO NOT EDIT THIS FILE.\n' |
michael@0 | 1574 | ' */\n\n' ) % (name, _NAME, _VERSION) |
michael@0 | 1575 | pre += ( '#include <stdlib.h>\n' |
michael@0 | 1576 | '#include <string.h>\n' |
michael@0 | 1577 | '#include <assert.h>\n' |
michael@0 | 1578 | '#include <event2/event-config.h>\n' |
michael@0 | 1579 | '#include <event2/event.h>\n' |
michael@0 | 1580 | '#include <event2/buffer.h>\n' |
michael@0 | 1581 | '#include <event2/tag.h>\n\n' |
michael@0 | 1582 | '#ifdef _EVENT___func__\n' |
michael@0 | 1583 | '#define __func__ _EVENT___func__\n' |
michael@0 | 1584 | '#endif\n\n' |
michael@0 | 1585 | ) |
michael@0 | 1586 | |
michael@0 | 1587 | for statement in cppdirect: |
michael@0 | 1588 | pre += '%s\n' % statement |
michael@0 | 1589 | |
michael@0 | 1590 | pre += '\n#include "%s"\n\n' % header_file |
michael@0 | 1591 | |
michael@0 | 1592 | pre += 'void event_warn(const char *fmt, ...);\n' |
michael@0 | 1593 | pre += 'void event_warnx(const char *fmt, ...);\n\n' |
michael@0 | 1594 | |
michael@0 | 1595 | return pre |
michael@0 | 1596 | |
michael@0 | 1597 | def HeaderFilename(self, filename): |
michael@0 | 1598 | return '.'.join(filename.split('.')[:-1]) + '.h' |
michael@0 | 1599 | |
michael@0 | 1600 | def CodeFilename(self, filename): |
michael@0 | 1601 | return '.'.join(filename.split('.')[:-1]) + '.gen.c' |
michael@0 | 1602 | |
michael@0 | 1603 | def Struct(self, name): |
michael@0 | 1604 | return StructCCode(name) |
michael@0 | 1605 | |
michael@0 | 1606 | def EntryBytes(self, entry_type, name, tag, fixed_length): |
michael@0 | 1607 | return EntryBytes(entry_type, name, tag, fixed_length) |
michael@0 | 1608 | |
michael@0 | 1609 | def EntryVarBytes(self, entry_type, name, tag): |
michael@0 | 1610 | return EntryVarBytes(entry_type, name, tag) |
michael@0 | 1611 | |
michael@0 | 1612 | def EntryInt(self, entry_type, name, tag, bits=32): |
michael@0 | 1613 | return EntryInt(entry_type, name, tag, bits) |
michael@0 | 1614 | |
michael@0 | 1615 | def EntryString(self, entry_type, name, tag): |
michael@0 | 1616 | return EntryString(entry_type, name, tag) |
michael@0 | 1617 | |
michael@0 | 1618 | def EntryStruct(self, entry_type, name, tag, struct_name): |
michael@0 | 1619 | return EntryStruct(entry_type, name, tag, struct_name) |
michael@0 | 1620 | |
michael@0 | 1621 | def EntryArray(self, entry): |
michael@0 | 1622 | return EntryArray(entry) |
michael@0 | 1623 | |
michael@0 | 1624 | class Usage(RpcGenError): |
michael@0 | 1625 | def __init__(self, argv0): |
michael@0 | 1626 | RpcGenError.__init__("usage: %s input.rpc [[output.h] output.c]" |
michael@0 | 1627 | % argv0) |
michael@0 | 1628 | |
michael@0 | 1629 | class CommandLine: |
michael@0 | 1630 | def __init__(self, argv): |
michael@0 | 1631 | """Initialize a command-line to launch event_rpcgen, as if |
michael@0 | 1632 | from a command-line with CommandLine(sys.argv). If you're |
michael@0 | 1633 | calling this directly, remember to provide a dummy value |
michael@0 | 1634 | for sys.argv[0] |
michael@0 | 1635 | """ |
michael@0 | 1636 | self.filename = None |
michael@0 | 1637 | self.header_file = None |
michael@0 | 1638 | self.impl_file = None |
michael@0 | 1639 | self.factory = CCodeGenerator() |
michael@0 | 1640 | |
michael@0 | 1641 | if len(argv) < 2 or len(argv) > 4: |
michael@0 | 1642 | raise Usage(argv[0]) |
michael@0 | 1643 | |
michael@0 | 1644 | self.filename = argv[1].replace('\\', '/') |
michael@0 | 1645 | if len(argv) == 3: |
michael@0 | 1646 | self.impl_file = argv[2].replace('\\', '/') |
michael@0 | 1647 | if len(argv) == 4: |
michael@0 | 1648 | self.header_file = argv[2].replace('\\', '/') |
michael@0 | 1649 | self.impl_file = argv[3].replace('\\', '/') |
michael@0 | 1650 | |
michael@0 | 1651 | if not self.filename: |
michael@0 | 1652 | raise Usage(argv[0]) |
michael@0 | 1653 | |
michael@0 | 1654 | if not self.impl_file: |
michael@0 | 1655 | self.impl_file = self.factory.CodeFilename(self.filename) |
michael@0 | 1656 | |
michael@0 | 1657 | if not self.header_file: |
michael@0 | 1658 | self.header_file = self.factory.HeaderFilename(self.impl_file) |
michael@0 | 1659 | |
michael@0 | 1660 | if not self.impl_file.endswith('.c'): |
michael@0 | 1661 | raise RpcGenError("can only generate C implementation files") |
michael@0 | 1662 | if not self.header_file.endswith('.h'): |
michael@0 | 1663 | raise RpcGenError("can only generate C header files") |
michael@0 | 1664 | |
michael@0 | 1665 | def run(self): |
michael@0 | 1666 | filename = self.filename |
michael@0 | 1667 | header_file = self.header_file |
michael@0 | 1668 | impl_file = self.impl_file |
michael@0 | 1669 | factory = self.factory |
michael@0 | 1670 | |
michael@0 | 1671 | print >>sys.stderr, 'Reading \"%s\"' % filename |
michael@0 | 1672 | |
michael@0 | 1673 | fp = open(filename, 'r') |
michael@0 | 1674 | entities = Parse(factory, fp) |
michael@0 | 1675 | fp.close() |
michael@0 | 1676 | |
michael@0 | 1677 | print >>sys.stderr, '... creating "%s"' % header_file |
michael@0 | 1678 | header_fp = open(header_file, 'w') |
michael@0 | 1679 | print >>header_fp, factory.HeaderPreamble(filename) |
michael@0 | 1680 | |
michael@0 | 1681 | # Create forward declarations: allows other structs to reference |
michael@0 | 1682 | # each other |
michael@0 | 1683 | for entry in entities: |
michael@0 | 1684 | entry.PrintForwardDeclaration(header_fp) |
michael@0 | 1685 | print >>header_fp, '' |
michael@0 | 1686 | |
michael@0 | 1687 | for entry in entities: |
michael@0 | 1688 | entry.PrintTags(header_fp) |
michael@0 | 1689 | entry.PrintDeclaration(header_fp) |
michael@0 | 1690 | print >>header_fp, factory.HeaderPostamble(filename) |
michael@0 | 1691 | header_fp.close() |
michael@0 | 1692 | |
michael@0 | 1693 | print >>sys.stderr, '... creating "%s"' % impl_file |
michael@0 | 1694 | impl_fp = open(impl_file, 'w') |
michael@0 | 1695 | print >>impl_fp, factory.BodyPreamble(filename, header_file) |
michael@0 | 1696 | for entry in entities: |
michael@0 | 1697 | entry.PrintCode(impl_fp) |
michael@0 | 1698 | impl_fp.close() |
michael@0 | 1699 | |
michael@0 | 1700 | if __name__ == '__main__': |
michael@0 | 1701 | try: |
michael@0 | 1702 | CommandLine(sys.argv).run() |
michael@0 | 1703 | sys.exit(0) |
michael@0 | 1704 | |
michael@0 | 1705 | except RpcGenError, e: |
michael@0 | 1706 | print >>sys.stderr, e |
michael@0 | 1707 | sys.exit(1) |
michael@0 | 1708 | |
michael@0 | 1709 | except EnvironmentError, e: |
michael@0 | 1710 | if e.filename and e.strerror: |
michael@0 | 1711 | print >>sys.stderr, "%s: %s" % (e.filename, e.strerror) |
michael@0 | 1712 | sys.exit(1) |
michael@0 | 1713 | elif e.strerror: |
michael@0 | 1714 | print >> sys.stderr, e.strerror |
michael@0 | 1715 | sys.exit(1) |
michael@0 | 1716 | else: |
michael@0 | 1717 | raise |