1*a466cc55SCy Schubert#!/usr/bin/env python 22b15cb3dSCy Schubert# 32b15cb3dSCy Schubert# Copyright (c) 2005-2007 Niels Provos <provos@citi.umich.edu> 42b15cb3dSCy Schubert# Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 52b15cb3dSCy Schubert# All rights reserved. 62b15cb3dSCy Schubert# 72b15cb3dSCy Schubert# Generates marshaling code based on libevent. 82b15cb3dSCy Schubert 9*a466cc55SCy Schubert# pylint: disable=too-many-lines 10*a466cc55SCy Schubert# pylint: disable=too-many-branches 11*a466cc55SCy Schubert# pylint: disable=too-many-public-methods 12*a466cc55SCy Schubert# pylint: disable=too-many-statements 13*a466cc55SCy Schubert# pylint: disable=global-statement 142b15cb3dSCy Schubert 15*a466cc55SCy Schubert# TODO: 16*a466cc55SCy Schubert# 1) propagate the arguments/options parsed by argparse down to the 17*a466cc55SCy Schubert# instantiated factory objects. 18*a466cc55SCy Schubert# 2) move the globals into a class that manages execution, including the 19*a466cc55SCy Schubert# progress outputs that go to stderr at the moment. 20*a466cc55SCy Schubert# 3) emit other languages. 21*a466cc55SCy Schubert 22*a466cc55SCy Schubertimport argparse 232b15cb3dSCy Schubertimport re 24*a466cc55SCy Schubertimport sys 252b15cb3dSCy Schubert 262b15cb3dSCy Schubert_NAME = "event_rpcgen.py" 272b15cb3dSCy Schubert_VERSION = "0.1" 282b15cb3dSCy Schubert 292b15cb3dSCy Schubert# Globals 30*a466cc55SCy SchubertLINE_COUNT = 0 312b15cb3dSCy Schubert 32*a466cc55SCy SchubertCPPCOMMENT_RE = re.compile(r"\/\/.*$") 33*a466cc55SCy SchubertNONIDENT_RE = re.compile(r"\W") 34*a466cc55SCy SchubertPREPROCESSOR_DEF_RE = re.compile(r"^#define") 35*a466cc55SCy SchubertSTRUCT_REF_RE = re.compile(r"^struct\[(?P<name>[a-zA-Z_][a-zA-Z0-9_]*)\]$") 36*a466cc55SCy SchubertSTRUCT_DEF_RE = re.compile(r"^struct +[a-zA-Z_][a-zA-Z0-9_]* *{$") 37*a466cc55SCy SchubertWHITESPACE_RE = re.compile(r"\s+") 382b15cb3dSCy Schubert 39*a466cc55SCy SchubertHEADER_DIRECT = [] 40*a466cc55SCy SchubertCPP_DIRECT = [] 412b15cb3dSCy Schubert 42*a466cc55SCy SchubertQUIETLY = False 43*a466cc55SCy Schubert 442b15cb3dSCy Schubert 452b15cb3dSCy Schubertdef declare(s): 462b15cb3dSCy Schubert if not QUIETLY: 47*a466cc55SCy Schubert print(s) 48*a466cc55SCy Schubert 492b15cb3dSCy Schubert 502b15cb3dSCy Schubertdef TranslateList(mylist, mydict): 51*a466cc55SCy Schubert return [x % mydict for x in mylist] 522b15cb3dSCy Schubert 53*a466cc55SCy Schubert 542b15cb3dSCy Schubertclass RpcGenError(Exception): 55*a466cc55SCy Schubert """An Exception class for parse errors.""" 56*a466cc55SCy Schubert 57*a466cc55SCy Schubert def __init__(self, why): # pylint: disable=super-init-not-called 582b15cb3dSCy Schubert self.why = why 59*a466cc55SCy Schubert 602b15cb3dSCy Schubert def __str__(self): 612b15cb3dSCy Schubert return str(self.why) 622b15cb3dSCy Schubert 63*a466cc55SCy Schubert 642b15cb3dSCy Schubert# Holds everything that makes a struct 65*a466cc55SCy Schubertclass Struct(object): 662b15cb3dSCy Schubert def __init__(self, name): 672b15cb3dSCy Schubert self._name = name 682b15cb3dSCy Schubert self._entries = [] 692b15cb3dSCy Schubert self._tags = {} 70*a466cc55SCy Schubert declare(" Created struct: %s" % name) 712b15cb3dSCy Schubert 722b15cb3dSCy Schubert def AddEntry(self, entry): 73*a466cc55SCy Schubert if entry.Tag() in self._tags: 742b15cb3dSCy Schubert raise RpcGenError( 752b15cb3dSCy Schubert 'Entry "%s" duplicates tag number %d from "%s" ' 76*a466cc55SCy Schubert "around line %d" 77*a466cc55SCy Schubert % (entry.Name(), entry.Tag(), self._tags[entry.Tag()], LINE_COUNT) 78*a466cc55SCy Schubert ) 792b15cb3dSCy Schubert self._entries.append(entry) 802b15cb3dSCy Schubert self._tags[entry.Tag()] = entry.Name() 81*a466cc55SCy Schubert declare(" Added entry: %s" % entry.Name()) 822b15cb3dSCy Schubert 832b15cb3dSCy Schubert def Name(self): 842b15cb3dSCy Schubert return self._name 852b15cb3dSCy Schubert 862b15cb3dSCy Schubert def EntryTagName(self, entry): 872b15cb3dSCy Schubert """Creates the name inside an enumeration for distinguishing data 882b15cb3dSCy Schubert types.""" 892b15cb3dSCy Schubert name = "%s_%s" % (self._name, entry.Name()) 902b15cb3dSCy Schubert return name.upper() 912b15cb3dSCy Schubert 92*a466cc55SCy Schubert @staticmethod 93*a466cc55SCy Schubert def PrintIndented(filep, ident, code): 942b15cb3dSCy Schubert """Takes an array, add indentation to each entry and prints it.""" 952b15cb3dSCy Schubert for entry in code: 96*a466cc55SCy Schubert filep.write("%s%s\n" % (ident, entry)) 97*a466cc55SCy Schubert 982b15cb3dSCy Schubert 992b15cb3dSCy Schubertclass StructCCode(Struct): 1002b15cb3dSCy Schubert """ Knows how to generate C code for a struct """ 1012b15cb3dSCy Schubert 1022b15cb3dSCy Schubert def __init__(self, name): 1032b15cb3dSCy Schubert Struct.__init__(self, name) 1042b15cb3dSCy Schubert 105*a466cc55SCy Schubert def PrintTags(self, filep): 1062b15cb3dSCy Schubert """Prints the tag definitions for a structure.""" 107*a466cc55SCy Schubert filep.write("/* Tag definition for %s */\n" % self._name) 108*a466cc55SCy Schubert filep.write("enum %s_ {\n" % self._name.lower()) 1092b15cb3dSCy Schubert for entry in self._entries: 110*a466cc55SCy Schubert filep.write(" %s=%d,\n" % (self.EntryTagName(entry), entry.Tag())) 111*a466cc55SCy Schubert filep.write(" %s_MAX_TAGS\n" % (self._name.upper())) 112*a466cc55SCy Schubert filep.write("};\n\n") 1132b15cb3dSCy Schubert 114*a466cc55SCy Schubert def PrintForwardDeclaration(self, filep): 115*a466cc55SCy Schubert filep.write("struct %s;\n" % self._name) 1162b15cb3dSCy Schubert 117*a466cc55SCy Schubert def PrintDeclaration(self, filep): 118*a466cc55SCy Schubert filep.write("/* Structure declaration for %s */\n" % self._name) 119*a466cc55SCy Schubert filep.write("struct %s_access_ {\n" % self._name) 1202b15cb3dSCy Schubert for entry in self._entries: 121*a466cc55SCy Schubert dcl = entry.AssignDeclaration("(*%s_assign)" % entry.Name()) 122*a466cc55SCy Schubert dcl.extend(entry.GetDeclaration("(*%s_get)" % entry.Name())) 1232b15cb3dSCy Schubert if entry.Array(): 124*a466cc55SCy Schubert dcl.extend(entry.AddDeclaration("(*%s_add)" % entry.Name())) 125*a466cc55SCy Schubert self.PrintIndented(filep, " ", dcl) 126*a466cc55SCy Schubert filep.write("};\n\n") 1272b15cb3dSCy Schubert 128*a466cc55SCy Schubert filep.write("struct %s {\n" % self._name) 129*a466cc55SCy Schubert filep.write(" struct %s_access_ *base;\n\n" % self._name) 1302b15cb3dSCy Schubert for entry in self._entries: 1312b15cb3dSCy Schubert dcl = entry.Declaration() 132*a466cc55SCy Schubert self.PrintIndented(filep, " ", dcl) 133*a466cc55SCy Schubert filep.write("\n") 1342b15cb3dSCy Schubert for entry in self._entries: 135*a466cc55SCy Schubert filep.write(" ev_uint8_t %s_set;\n" % entry.Name()) 136*a466cc55SCy Schubert filep.write("};\n\n") 1372b15cb3dSCy Schubert 138*a466cc55SCy Schubert filep.write( 1392b15cb3dSCy Schubert """struct %(name)s *%(name)s_new(void); 1402b15cb3dSCy Schubertstruct %(name)s *%(name)s_new_with_arg(void *); 1412b15cb3dSCy Schubertvoid %(name)s_free(struct %(name)s *); 1422b15cb3dSCy Schubertvoid %(name)s_clear(struct %(name)s *); 1432b15cb3dSCy Schubertvoid %(name)s_marshal(struct evbuffer *, const struct %(name)s *); 1442b15cb3dSCy Schubertint %(name)s_unmarshal(struct %(name)s *, struct evbuffer *); 1452b15cb3dSCy Schubertint %(name)s_complete(struct %(name)s *); 1462b15cb3dSCy Schubertvoid evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t, 1472b15cb3dSCy Schubert const struct %(name)s *); 1482b15cb3dSCy Schubertint evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t, 149*a466cc55SCy Schubert struct %(name)s *);\n""" 150*a466cc55SCy Schubert % {"name": self._name} 151*a466cc55SCy Schubert ) 1522b15cb3dSCy Schubert 1532b15cb3dSCy Schubert # Write a setting function of every variable 1542b15cb3dSCy Schubert for entry in self._entries: 155*a466cc55SCy Schubert self.PrintIndented( 156*a466cc55SCy Schubert filep, "", entry.AssignDeclaration(entry.AssignFuncName()) 157*a466cc55SCy Schubert ) 158*a466cc55SCy Schubert self.PrintIndented(filep, "", entry.GetDeclaration(entry.GetFuncName())) 1592b15cb3dSCy Schubert if entry.Array(): 160*a466cc55SCy Schubert self.PrintIndented(filep, "", entry.AddDeclaration(entry.AddFuncName())) 1612b15cb3dSCy Schubert 162*a466cc55SCy Schubert filep.write("/* --- %s done --- */\n\n" % self._name) 1632b15cb3dSCy Schubert 164*a466cc55SCy Schubert def PrintCode(self, filep): 165*a466cc55SCy Schubert filep.write( 166*a466cc55SCy Schubert """/* 167*a466cc55SCy Schubert * Implementation of %s 168*a466cc55SCy Schubert */ 169*a466cc55SCy Schubert""" 170*a466cc55SCy Schubert % (self._name) 171*a466cc55SCy Schubert ) 1722b15cb3dSCy Schubert 173*a466cc55SCy Schubert filep.write( 174*a466cc55SCy Schubert """ 175*a466cc55SCy Schubertstatic struct %(name)s_access_ %(name)s_base__ = { 176*a466cc55SCy Schubert""" 177*a466cc55SCy Schubert % {"name": self._name} 178*a466cc55SCy Schubert ) 1792b15cb3dSCy Schubert for entry in self._entries: 180*a466cc55SCy Schubert self.PrintIndented(filep, " ", entry.CodeBase()) 181*a466cc55SCy Schubert filep.write("};\n\n") 1822b15cb3dSCy Schubert 1832b15cb3dSCy Schubert # Creation 184*a466cc55SCy Schubert filep.write( 185*a466cc55SCy Schubert """struct %(name)s * 186*a466cc55SCy Schubert%(name)s_new(void) 187*a466cc55SCy Schubert{ 188*a466cc55SCy Schubert return %(name)s_new_with_arg(NULL); 189*a466cc55SCy Schubert} 190*a466cc55SCy Schubert 191*a466cc55SCy Schubertstruct %(name)s * 192*a466cc55SCy Schubert%(name)s_new_with_arg(void *unused) 193*a466cc55SCy Schubert{ 194*a466cc55SCy Schubert struct %(name)s *tmp; 195*a466cc55SCy Schubert if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) { 196*a466cc55SCy Schubert event_warn("%%s: malloc", __func__); 197*a466cc55SCy Schubert return (NULL); 198*a466cc55SCy Schubert } 199*a466cc55SCy Schubert tmp->base = &%(name)s_base__; 200*a466cc55SCy Schubert 201*a466cc55SCy Schubert""" 202*a466cc55SCy Schubert % {"name": self._name} 203*a466cc55SCy Schubert ) 2042b15cb3dSCy Schubert 2052b15cb3dSCy Schubert for entry in self._entries: 206*a466cc55SCy Schubert self.PrintIndented(filep, " ", entry.CodeInitialize("tmp")) 207*a466cc55SCy Schubert filep.write(" tmp->%s_set = 0;\n\n" % entry.Name()) 2082b15cb3dSCy Schubert 209*a466cc55SCy Schubert filep.write( 210*a466cc55SCy Schubert """ return (tmp); 211*a466cc55SCy Schubert} 212*a466cc55SCy Schubert 213*a466cc55SCy Schubert""" 214*a466cc55SCy Schubert ) 2152b15cb3dSCy Schubert 2162b15cb3dSCy Schubert # Adding 2172b15cb3dSCy Schubert for entry in self._entries: 2182b15cb3dSCy Schubert if entry.Array(): 219*a466cc55SCy Schubert self.PrintIndented(filep, "", entry.CodeAdd()) 220*a466cc55SCy Schubert filep.write("\n") 2212b15cb3dSCy Schubert 2222b15cb3dSCy Schubert # Assigning 2232b15cb3dSCy Schubert for entry in self._entries: 224*a466cc55SCy Schubert self.PrintIndented(filep, "", entry.CodeAssign()) 225*a466cc55SCy Schubert filep.write("\n") 2262b15cb3dSCy Schubert 2272b15cb3dSCy Schubert # Getting 2282b15cb3dSCy Schubert for entry in self._entries: 229*a466cc55SCy Schubert self.PrintIndented(filep, "", entry.CodeGet()) 230*a466cc55SCy Schubert filep.write("\n") 2312b15cb3dSCy Schubert 2322b15cb3dSCy Schubert # Clearing 233*a466cc55SCy Schubert filep.write( 234*a466cc55SCy Schubert """void 235*a466cc55SCy Schubert%(name)s_clear(struct %(name)s *tmp) 236*a466cc55SCy Schubert{ 237*a466cc55SCy Schubert""" 238*a466cc55SCy Schubert % {"name": self._name} 239*a466cc55SCy Schubert ) 2402b15cb3dSCy Schubert for entry in self._entries: 241*a466cc55SCy Schubert self.PrintIndented(filep, " ", entry.CodeClear("tmp")) 2422b15cb3dSCy Schubert 243*a466cc55SCy Schubert filep.write("}\n\n") 2442b15cb3dSCy Schubert 2452b15cb3dSCy Schubert # Freeing 246*a466cc55SCy Schubert filep.write( 247*a466cc55SCy Schubert """void 248*a466cc55SCy Schubert%(name)s_free(struct %(name)s *tmp) 249*a466cc55SCy Schubert{ 250*a466cc55SCy Schubert""" 251*a466cc55SCy Schubert % {"name": self._name} 252*a466cc55SCy Schubert ) 2532b15cb3dSCy Schubert 2542b15cb3dSCy Schubert for entry in self._entries: 255*a466cc55SCy Schubert self.PrintIndented(filep, " ", entry.CodeFree("tmp")) 2562b15cb3dSCy Schubert 257*a466cc55SCy Schubert filep.write( 258*a466cc55SCy Schubert """ free(tmp); 259*a466cc55SCy Schubert} 260*a466cc55SCy Schubert 261*a466cc55SCy Schubert""" 262*a466cc55SCy Schubert ) 2632b15cb3dSCy Schubert 2642b15cb3dSCy Schubert # Marshaling 265*a466cc55SCy Schubert filep.write( 266*a466cc55SCy Schubert """void 267*a466cc55SCy Schubert%(name)s_marshal(struct evbuffer *evbuf, const struct %(name)s *tmp) { 268*a466cc55SCy Schubert""" 269*a466cc55SCy Schubert % {"name": self._name} 270*a466cc55SCy Schubert ) 2712b15cb3dSCy Schubert for entry in self._entries: 272*a466cc55SCy Schubert indent = " " 2732b15cb3dSCy Schubert # Optional entries do not have to be set 2742b15cb3dSCy Schubert if entry.Optional(): 275*a466cc55SCy Schubert indent += " " 276*a466cc55SCy Schubert filep.write(" if (tmp->%s_set) {\n" % entry.Name()) 2772b15cb3dSCy Schubert self.PrintIndented( 278*a466cc55SCy Schubert filep, 279*a466cc55SCy Schubert indent, 280*a466cc55SCy Schubert entry.CodeMarshal( 281*a466cc55SCy Schubert "evbuf", 282*a466cc55SCy Schubert self.EntryTagName(entry), 283*a466cc55SCy Schubert entry.GetVarName("tmp"), 284*a466cc55SCy Schubert entry.GetVarLen("tmp"), 285*a466cc55SCy Schubert ), 286*a466cc55SCy Schubert ) 2872b15cb3dSCy Schubert if entry.Optional(): 288*a466cc55SCy Schubert filep.write(" }\n") 2892b15cb3dSCy Schubert 290*a466cc55SCy Schubert filep.write("}\n\n") 2912b15cb3dSCy Schubert 2922b15cb3dSCy Schubert # Unmarshaling 293*a466cc55SCy Schubert filep.write( 294*a466cc55SCy Schubert """int 295*a466cc55SCy Schubert%(name)s_unmarshal(struct %(name)s *tmp, struct evbuffer *evbuf) 296*a466cc55SCy Schubert{ 297*a466cc55SCy Schubert ev_uint32_t tag; 298*a466cc55SCy Schubert while (evbuffer_get_length(evbuf) > 0) { 299*a466cc55SCy Schubert if (evtag_peek(evbuf, &tag) == -1) 300*a466cc55SCy Schubert return (-1); 301*a466cc55SCy Schubert switch (tag) { 302*a466cc55SCy Schubert 303*a466cc55SCy Schubert""" 304*a466cc55SCy Schubert % {"name": self._name} 305*a466cc55SCy Schubert ) 3062b15cb3dSCy Schubert for entry in self._entries: 307*a466cc55SCy Schubert filep.write(" case %s:\n" % (self.EntryTagName(entry))) 3082b15cb3dSCy Schubert if not entry.Array(): 309*a466cc55SCy Schubert filep.write( 310*a466cc55SCy Schubert """ if (tmp->%s_set) 311*a466cc55SCy Schubert return (-1); 312*a466cc55SCy Schubert""" 313*a466cc55SCy Schubert % (entry.Name()) 314*a466cc55SCy Schubert ) 3152b15cb3dSCy Schubert 3162b15cb3dSCy Schubert self.PrintIndented( 317*a466cc55SCy Schubert filep, 318*a466cc55SCy Schubert " ", 319*a466cc55SCy Schubert entry.CodeUnmarshal( 320*a466cc55SCy Schubert "evbuf", 3212b15cb3dSCy Schubert self.EntryTagName(entry), 322*a466cc55SCy Schubert entry.GetVarName("tmp"), 323*a466cc55SCy Schubert entry.GetVarLen("tmp"), 324*a466cc55SCy Schubert ), 325*a466cc55SCy Schubert ) 3262b15cb3dSCy Schubert 327*a466cc55SCy Schubert filep.write( 328*a466cc55SCy Schubert """ tmp->%s_set = 1; 329*a466cc55SCy Schubert break; 330*a466cc55SCy Schubert""" 331*a466cc55SCy Schubert % (entry.Name()) 332*a466cc55SCy Schubert ) 333*a466cc55SCy Schubert filep.write( 334*a466cc55SCy Schubert """ default: 335*a466cc55SCy Schubert return -1; 336*a466cc55SCy Schubert } 337*a466cc55SCy Schubert } 338*a466cc55SCy Schubert 339*a466cc55SCy Schubert""" 340*a466cc55SCy Schubert ) 3412b15cb3dSCy Schubert # Check if it was decoded completely 342*a466cc55SCy Schubert filep.write( 343*a466cc55SCy Schubert """ if (%(name)s_complete(tmp) == -1) 344*a466cc55SCy Schubert return (-1); 345*a466cc55SCy Schubert return (0); 346*a466cc55SCy Schubert} 347*a466cc55SCy Schubert""" 348*a466cc55SCy Schubert % {"name": self._name} 349*a466cc55SCy Schubert ) 3502b15cb3dSCy Schubert 3512b15cb3dSCy Schubert # Checking if a structure has all the required data 352*a466cc55SCy Schubert filep.write( 353*a466cc55SCy Schubert """ 354*a466cc55SCy Schubertint 355*a466cc55SCy Schubert%(name)s_complete(struct %(name)s *msg) 356*a466cc55SCy Schubert{ 357*a466cc55SCy Schubert""" 358*a466cc55SCy Schubert % {"name": self._name} 359*a466cc55SCy Schubert ) 3602b15cb3dSCy Schubert for entry in self._entries: 3612b15cb3dSCy Schubert if not entry.Optional(): 3622b15cb3dSCy Schubert code = [ 363*a466cc55SCy Schubert """if (!msg->%(name)s_set) 364*a466cc55SCy Schubert return (-1);""" 365*a466cc55SCy Schubert ] 3662b15cb3dSCy Schubert code = TranslateList(code, entry.GetTranslation()) 367*a466cc55SCy Schubert self.PrintIndented(filep, " ", code) 3682b15cb3dSCy Schubert 3692b15cb3dSCy Schubert self.PrintIndented( 370*a466cc55SCy Schubert filep, " ", entry.CodeComplete("msg", entry.GetVarName("msg")) 371*a466cc55SCy Schubert ) 372*a466cc55SCy Schubert filep.write( 373*a466cc55SCy Schubert """ return (0); 374*a466cc55SCy Schubert} 375*a466cc55SCy Schubert""" 376*a466cc55SCy Schubert ) 3772b15cb3dSCy Schubert 3782b15cb3dSCy Schubert # Complete message unmarshaling 379*a466cc55SCy Schubert filep.write( 380*a466cc55SCy Schubert """ 381*a466cc55SCy Schubertint 382*a466cc55SCy Schubertevtag_unmarshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t need_tag, 383*a466cc55SCy Schubert struct %(name)s *msg) 384*a466cc55SCy Schubert{ 385*a466cc55SCy Schubert ev_uint32_t tag; 386*a466cc55SCy Schubert int res = -1; 387*a466cc55SCy Schubert 388*a466cc55SCy Schubert struct evbuffer *tmp = evbuffer_new(); 389*a466cc55SCy Schubert 390*a466cc55SCy Schubert if (evtag_unmarshal(evbuf, &tag, tmp) == -1 || tag != need_tag) 391*a466cc55SCy Schubert goto error; 392*a466cc55SCy Schubert 393*a466cc55SCy Schubert if (%(name)s_unmarshal(msg, tmp) == -1) 394*a466cc55SCy Schubert goto error; 395*a466cc55SCy Schubert 396*a466cc55SCy Schubert res = 0; 397*a466cc55SCy Schubert 398*a466cc55SCy Schubert error: 399*a466cc55SCy Schubert evbuffer_free(tmp); 400*a466cc55SCy Schubert return (res); 401*a466cc55SCy Schubert} 402*a466cc55SCy Schubert""" 403*a466cc55SCy Schubert % {"name": self._name} 404*a466cc55SCy Schubert ) 4052b15cb3dSCy Schubert 4062b15cb3dSCy Schubert # Complete message marshaling 407*a466cc55SCy Schubert filep.write( 408*a466cc55SCy Schubert """ 409*a466cc55SCy Schubertvoid 410*a466cc55SCy Schubertevtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, 411*a466cc55SCy Schubert const struct %(name)s *msg) 412*a466cc55SCy Schubert{ 413*a466cc55SCy Schubert struct evbuffer *buf_ = evbuffer_new(); 414*a466cc55SCy Schubert assert(buf_ != NULL); 415*a466cc55SCy Schubert %(name)s_marshal(buf_, msg); 416*a466cc55SCy Schubert evtag_marshal_buffer(evbuf, tag, buf_); 417*a466cc55SCy Schubert evbuffer_free(buf_); 418*a466cc55SCy Schubert} 4192b15cb3dSCy Schubert 420*a466cc55SCy Schubert""" 421*a466cc55SCy Schubert % {"name": self._name} 422*a466cc55SCy Schubert ) 423*a466cc55SCy Schubert 424*a466cc55SCy Schubert 425*a466cc55SCy Schubertclass Entry(object): 426*a466cc55SCy Schubert def __init__(self, ent_type, name, tag): 427*a466cc55SCy Schubert self._type = ent_type 4282b15cb3dSCy Schubert self._name = name 4292b15cb3dSCy Schubert self._tag = int(tag) 430*a466cc55SCy Schubert self._ctype = ent_type 431*a466cc55SCy Schubert self._optional = False 432*a466cc55SCy Schubert self._can_be_array = False 433*a466cc55SCy Schubert self._array = False 4342b15cb3dSCy Schubert self._line_count = -1 4352b15cb3dSCy Schubert self._struct = None 4362b15cb3dSCy Schubert self._refname = None 4372b15cb3dSCy Schubert 4382b15cb3dSCy Schubert self._optpointer = True 4392b15cb3dSCy Schubert self._optaddarg = True 4402b15cb3dSCy Schubert 441*a466cc55SCy Schubert @staticmethod 442*a466cc55SCy Schubert def GetInitializer(): 443*a466cc55SCy Schubert raise NotImplementedError("Entry does not provide an initializer") 4442b15cb3dSCy Schubert 4452b15cb3dSCy Schubert def SetStruct(self, struct): 4462b15cb3dSCy Schubert self._struct = struct 4472b15cb3dSCy Schubert 4482b15cb3dSCy Schubert def LineCount(self): 4492b15cb3dSCy Schubert assert self._line_count != -1 4502b15cb3dSCy Schubert return self._line_count 4512b15cb3dSCy Schubert 4522b15cb3dSCy Schubert def SetLineCount(self, number): 4532b15cb3dSCy Schubert self._line_count = number 4542b15cb3dSCy Schubert 4552b15cb3dSCy Schubert def Array(self): 4562b15cb3dSCy Schubert return self._array 4572b15cb3dSCy Schubert 4582b15cb3dSCy Schubert def Optional(self): 4592b15cb3dSCy Schubert return self._optional 4602b15cb3dSCy Schubert 4612b15cb3dSCy Schubert def Tag(self): 4622b15cb3dSCy Schubert return self._tag 4632b15cb3dSCy Schubert 4642b15cb3dSCy Schubert def Name(self): 4652b15cb3dSCy Schubert return self._name 4662b15cb3dSCy Schubert 4672b15cb3dSCy Schubert def Type(self): 4682b15cb3dSCy Schubert return self._type 4692b15cb3dSCy Schubert 470*a466cc55SCy Schubert def MakeArray(self): 471*a466cc55SCy Schubert self._array = True 4722b15cb3dSCy Schubert 4732b15cb3dSCy Schubert def MakeOptional(self): 474*a466cc55SCy Schubert self._optional = True 4752b15cb3dSCy Schubert 4762b15cb3dSCy Schubert def Verify(self): 4772b15cb3dSCy Schubert if self.Array() and not self._can_be_array: 4782b15cb3dSCy Schubert raise RpcGenError( 4792b15cb3dSCy Schubert 'Entry "%s" cannot be created as an array ' 480*a466cc55SCy Schubert "around line %d" % (self._name, self.LineCount()) 481*a466cc55SCy Schubert ) 4822b15cb3dSCy Schubert if not self._struct: 4832b15cb3dSCy Schubert raise RpcGenError( 4842b15cb3dSCy Schubert 'Entry "%s" does not know which struct it belongs to ' 485*a466cc55SCy Schubert "around line %d" % (self._name, self.LineCount()) 486*a466cc55SCy Schubert ) 4872b15cb3dSCy Schubert if self._optional and self._array: 4882b15cb3dSCy Schubert raise RpcGenError( 4892b15cb3dSCy Schubert 'Entry "%s" has illegal combination of optional and array ' 490*a466cc55SCy Schubert "around line %d" % (self._name, self.LineCount()) 491*a466cc55SCy Schubert ) 4922b15cb3dSCy Schubert 493*a466cc55SCy Schubert def GetTranslation(self, extradict=None): 494*a466cc55SCy Schubert if extradict is None: 495*a466cc55SCy Schubert extradict = {} 4962b15cb3dSCy Schubert mapping = { 4972b15cb3dSCy Schubert "parent_name": self._struct.Name(), 4982b15cb3dSCy Schubert "name": self._name, 4992b15cb3dSCy Schubert "ctype": self._ctype, 5002b15cb3dSCy Schubert "refname": self._refname, 5012b15cb3dSCy Schubert "optpointer": self._optpointer and "*" or "", 5022b15cb3dSCy Schubert "optreference": self._optpointer and "&" or "", 503*a466cc55SCy Schubert "optaddarg": self._optaddarg and ", const %s value" % self._ctype or "", 5042b15cb3dSCy Schubert } 505*a466cc55SCy Schubert for (k, v) in list(extradict.items()): 5062b15cb3dSCy Schubert mapping[k] = v 5072b15cb3dSCy Schubert 5082b15cb3dSCy Schubert return mapping 5092b15cb3dSCy Schubert 5102b15cb3dSCy Schubert def GetVarName(self, var): 511*a466cc55SCy Schubert return "%(var)s->%(name)s_data" % self.GetTranslation({"var": var}) 5122b15cb3dSCy Schubert 513*a466cc55SCy Schubert def GetVarLen(self, _var): 514*a466cc55SCy Schubert return "sizeof(%s)" % self._ctype 5152b15cb3dSCy Schubert 5162b15cb3dSCy Schubert def GetFuncName(self): 517*a466cc55SCy Schubert return "%s_%s_get" % (self._struct.Name(), self._name) 5182b15cb3dSCy Schubert 5192b15cb3dSCy Schubert def GetDeclaration(self, funcname): 520*a466cc55SCy Schubert code = [ 521*a466cc55SCy Schubert "int %s(struct %s *, %s *);" % (funcname, self._struct.Name(), self._ctype) 522*a466cc55SCy Schubert ] 5232b15cb3dSCy Schubert return code 5242b15cb3dSCy Schubert 5252b15cb3dSCy Schubert def CodeGet(self): 526*a466cc55SCy Schubert code = """int 527*a466cc55SCy Schubert%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, %(ctype)s *value) 528*a466cc55SCy Schubert{ 529*a466cc55SCy Schubert if (msg->%(name)s_set != 1) 530*a466cc55SCy Schubert return (-1); 531*a466cc55SCy Schubert *value = msg->%(name)s_data; 532*a466cc55SCy Schubert return (0); 533*a466cc55SCy Schubert}""" 5342b15cb3dSCy Schubert code = code % self.GetTranslation() 535*a466cc55SCy Schubert return code.split("\n") 5362b15cb3dSCy Schubert 5372b15cb3dSCy Schubert def AssignFuncName(self): 538*a466cc55SCy Schubert return "%s_%s_assign" % (self._struct.Name(), self._name) 5392b15cb3dSCy Schubert 5402b15cb3dSCy Schubert def AddFuncName(self): 541*a466cc55SCy Schubert return "%s_%s_add" % (self._struct.Name(), self._name) 5422b15cb3dSCy Schubert 5432b15cb3dSCy Schubert def AssignDeclaration(self, funcname): 544*a466cc55SCy Schubert code = [ 545*a466cc55SCy Schubert "int %s(struct %s *, const %s);" 546*a466cc55SCy Schubert % (funcname, self._struct.Name(), self._ctype) 547*a466cc55SCy Schubert ] 5482b15cb3dSCy Schubert return code 5492b15cb3dSCy Schubert 5502b15cb3dSCy Schubert def CodeAssign(self): 551*a466cc55SCy Schubert code = [ 552*a466cc55SCy Schubert "int", 553*a466cc55SCy Schubert "%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg," 554*a466cc55SCy Schubert " const %(ctype)s value)", 555*a466cc55SCy Schubert "{", 556*a466cc55SCy Schubert " msg->%(name)s_set = 1;", 557*a466cc55SCy Schubert " msg->%(name)s_data = value;", 558*a466cc55SCy Schubert " return (0);", 559*a466cc55SCy Schubert "}", 560*a466cc55SCy Schubert ] 561*a466cc55SCy Schubert code = "\n".join(code) 5622b15cb3dSCy Schubert code = code % self.GetTranslation() 563*a466cc55SCy Schubert return code.split("\n") 5642b15cb3dSCy Schubert 5652b15cb3dSCy Schubert def CodeClear(self, structname): 566*a466cc55SCy Schubert code = ["%s->%s_set = 0;" % (structname, self.Name())] 5672b15cb3dSCy Schubert 5682b15cb3dSCy Schubert return code 5692b15cb3dSCy Schubert 570*a466cc55SCy Schubert @staticmethod 571*a466cc55SCy Schubert def CodeComplete(_structname, _var_name): 5722b15cb3dSCy Schubert return [] 5732b15cb3dSCy Schubert 574*a466cc55SCy Schubert @staticmethod 575*a466cc55SCy Schubert def CodeFree(_name): 5762b15cb3dSCy Schubert return [] 5772b15cb3dSCy Schubert 5782b15cb3dSCy Schubert def CodeBase(self): 579*a466cc55SCy Schubert code = ["%(parent_name)s_%(name)s_assign,", "%(parent_name)s_%(name)s_get,"] 5802b15cb3dSCy Schubert if self.Array(): 581*a466cc55SCy Schubert code.append("%(parent_name)s_%(name)s_add,") 5822b15cb3dSCy Schubert 583*a466cc55SCy Schubert code = "\n".join(code) 5842b15cb3dSCy Schubert code = code % self.GetTranslation() 585*a466cc55SCy Schubert return code.split("\n") 586*a466cc55SCy Schubert 5872b15cb3dSCy Schubert 5882b15cb3dSCy Schubertclass EntryBytes(Entry): 589*a466cc55SCy Schubert def __init__(self, ent_type, name, tag, length): 5902b15cb3dSCy Schubert # Init base class 591*a466cc55SCy Schubert super(EntryBytes, self).__init__(ent_type, name, tag) 5922b15cb3dSCy Schubert 5932b15cb3dSCy Schubert self._length = length 594*a466cc55SCy Schubert self._ctype = "ev_uint8_t" 5952b15cb3dSCy Schubert 596*a466cc55SCy Schubert @staticmethod 597*a466cc55SCy Schubert def GetInitializer(): 5982b15cb3dSCy Schubert return "NULL" 5992b15cb3dSCy Schubert 600*a466cc55SCy Schubert def GetVarLen(self, _var): 601*a466cc55SCy Schubert return "(%s)" % self._length 6022b15cb3dSCy Schubert 603*a466cc55SCy Schubert @staticmethod 604*a466cc55SCy Schubert def CodeArrayAdd(varname, _value): 6052b15cb3dSCy Schubert # XXX: copy here 606*a466cc55SCy Schubert return ["%(varname)s = NULL;" % {"varname": varname}] 6072b15cb3dSCy Schubert 6082b15cb3dSCy Schubert def GetDeclaration(self, funcname): 609*a466cc55SCy Schubert code = [ 610*a466cc55SCy Schubert "int %s(struct %s *, %s **);" % (funcname, self._struct.Name(), self._ctype) 611*a466cc55SCy Schubert ] 6122b15cb3dSCy Schubert return code 6132b15cb3dSCy Schubert 6142b15cb3dSCy Schubert def AssignDeclaration(self, funcname): 615*a466cc55SCy Schubert code = [ 616*a466cc55SCy Schubert "int %s(struct %s *, const %s *);" 617*a466cc55SCy Schubert % (funcname, self._struct.Name(), self._ctype) 618*a466cc55SCy Schubert ] 6192b15cb3dSCy Schubert return code 6202b15cb3dSCy Schubert 6212b15cb3dSCy Schubert def Declaration(self): 622*a466cc55SCy Schubert dcl = ["ev_uint8_t %s_data[%s];" % (self._name, self._length)] 6232b15cb3dSCy Schubert 6242b15cb3dSCy Schubert return dcl 6252b15cb3dSCy Schubert 6262b15cb3dSCy Schubert def CodeGet(self): 6272b15cb3dSCy Schubert name = self._name 628*a466cc55SCy Schubert code = [ 629*a466cc55SCy Schubert "int", 630*a466cc55SCy Schubert "%s_%s_get(struct %s *msg, %s **value)" 631*a466cc55SCy Schubert % (self._struct.Name(), name, self._struct.Name(), self._ctype), 632*a466cc55SCy Schubert "{", 633*a466cc55SCy Schubert " if (msg->%s_set != 1)" % name, 634*a466cc55SCy Schubert " return (-1);", 635*a466cc55SCy Schubert " *value = msg->%s_data;" % name, 636*a466cc55SCy Schubert " return (0);", 637*a466cc55SCy Schubert "}", 638*a466cc55SCy Schubert ] 6392b15cb3dSCy Schubert return code 6402b15cb3dSCy Schubert 6412b15cb3dSCy Schubert def CodeAssign(self): 6422b15cb3dSCy Schubert name = self._name 643*a466cc55SCy Schubert code = [ 644*a466cc55SCy Schubert "int", 645*a466cc55SCy Schubert "%s_%s_assign(struct %s *msg, const %s *value)" 646*a466cc55SCy Schubert % (self._struct.Name(), name, self._struct.Name(), self._ctype), 647*a466cc55SCy Schubert "{", 648*a466cc55SCy Schubert " msg->%s_set = 1;" % name, 649*a466cc55SCy Schubert " memcpy(msg->%s_data, value, %s);" % (name, self._length), 650*a466cc55SCy Schubert " return (0);", 651*a466cc55SCy Schubert "}", 652*a466cc55SCy Schubert ] 6532b15cb3dSCy Schubert return code 6542b15cb3dSCy Schubert 6552b15cb3dSCy Schubert def CodeUnmarshal(self, buf, tag_name, var_name, var_len): 656*a466cc55SCy Schubert code = [ 657*a466cc55SCy Schubert "if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, " 658*a466cc55SCy Schubert "%(var)s, %(varlen)s) == -1) {", 6592b15cb3dSCy Schubert ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 660*a466cc55SCy Schubert " return (-1);", 661*a466cc55SCy Schubert "}", 6622b15cb3dSCy Schubert ] 663*a466cc55SCy Schubert return TranslateList( 664*a466cc55SCy Schubert code, 665*a466cc55SCy Schubert self.GetTranslation( 666*a466cc55SCy Schubert {"var": var_name, "varlen": var_len, "buf": buf, "tag": tag_name} 667*a466cc55SCy Schubert ), 668*a466cc55SCy Schubert ) 6692b15cb3dSCy Schubert 670*a466cc55SCy Schubert @staticmethod 671*a466cc55SCy Schubert def CodeMarshal(buf, tag_name, var_name, var_len): 672*a466cc55SCy Schubert code = ["evtag_marshal(%s, %s, %s, %s);" % (buf, tag_name, var_name, var_len)] 6732b15cb3dSCy Schubert return code 6742b15cb3dSCy Schubert 6752b15cb3dSCy Schubert def CodeClear(self, structname): 676*a466cc55SCy Schubert code = [ 677*a466cc55SCy Schubert "%s->%s_set = 0;" % (structname, self.Name()), 678*a466cc55SCy Schubert "memset(%s->%s_data, 0, sizeof(%s->%s_data));" 679*a466cc55SCy Schubert % (structname, self._name, structname, self._name), 680*a466cc55SCy Schubert ] 6812b15cb3dSCy Schubert 6822b15cb3dSCy Schubert return code 6832b15cb3dSCy Schubert 6842b15cb3dSCy Schubert def CodeInitialize(self, name): 685*a466cc55SCy Schubert code = [ 686*a466cc55SCy Schubert "memset(%s->%s_data, 0, sizeof(%s->%s_data));" 687*a466cc55SCy Schubert % (name, self._name, name, self._name) 688*a466cc55SCy Schubert ] 6892b15cb3dSCy Schubert return code 6902b15cb3dSCy Schubert 6912b15cb3dSCy Schubert def Verify(self): 6922b15cb3dSCy Schubert if not self._length: 6932b15cb3dSCy Schubert raise RpcGenError( 6942b15cb3dSCy Schubert 'Entry "%s" needs a length ' 695*a466cc55SCy Schubert "around line %d" % (self._name, self.LineCount()) 696*a466cc55SCy Schubert ) 6972b15cb3dSCy Schubert 698*a466cc55SCy Schubert super(EntryBytes, self).Verify() 699*a466cc55SCy Schubert 7002b15cb3dSCy Schubert 7012b15cb3dSCy Schubertclass EntryInt(Entry): 702*a466cc55SCy Schubert def __init__(self, ent_type, name, tag, bits=32): 7032b15cb3dSCy Schubert # Init base class 704*a466cc55SCy Schubert super(EntryInt, self).__init__(ent_type, name, tag) 7052b15cb3dSCy Schubert 706*a466cc55SCy Schubert self._can_be_array = True 7072b15cb3dSCy Schubert if bits == 32: 708*a466cc55SCy Schubert self._ctype = "ev_uint32_t" 709*a466cc55SCy Schubert self._marshal_type = "int" 7102b15cb3dSCy Schubert if bits == 64: 711*a466cc55SCy Schubert self._ctype = "ev_uint64_t" 712*a466cc55SCy Schubert self._marshal_type = "int64" 7132b15cb3dSCy Schubert 714*a466cc55SCy Schubert @staticmethod 715*a466cc55SCy Schubert def GetInitializer(): 7162b15cb3dSCy Schubert return "0" 7172b15cb3dSCy Schubert 718*a466cc55SCy Schubert @staticmethod 719*a466cc55SCy Schubert def CodeArrayFree(_var): 7202b15cb3dSCy Schubert return [] 7212b15cb3dSCy Schubert 722*a466cc55SCy Schubert @staticmethod 723*a466cc55SCy Schubert def CodeArrayAssign(varname, srcvar): 724*a466cc55SCy Schubert return ["%(varname)s = %(srcvar)s;" % {"varname": varname, "srcvar": srcvar}] 7252b15cb3dSCy Schubert 726*a466cc55SCy Schubert @staticmethod 727*a466cc55SCy Schubert def CodeArrayAdd(varname, value): 7282b15cb3dSCy Schubert """Returns a new entry of this type.""" 729*a466cc55SCy Schubert return ["%(varname)s = %(value)s;" % {"varname": varname, "value": value}] 7302b15cb3dSCy Schubert 731*a466cc55SCy Schubert def CodeUnmarshal(self, buf, tag_name, var_name, _var_len): 7322b15cb3dSCy Schubert code = [ 733*a466cc55SCy Schubert "if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {", 7342b15cb3dSCy Schubert ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 735*a466cc55SCy Schubert " return (-1);", 736*a466cc55SCy Schubert "}", 737*a466cc55SCy Schubert ] 738*a466cc55SCy Schubert code = "\n".join(code) % self.GetTranslation( 739*a466cc55SCy Schubert {"ma": self._marshal_type, "buf": buf, "tag": tag_name, "var": var_name} 740*a466cc55SCy Schubert ) 741*a466cc55SCy Schubert return code.split("\n") 7422b15cb3dSCy Schubert 743*a466cc55SCy Schubert def CodeMarshal(self, buf, tag_name, var_name, _var_len): 7442b15cb3dSCy Schubert code = [ 745*a466cc55SCy Schubert "evtag_marshal_%s(%s, %s, %s);" 746*a466cc55SCy Schubert % (self._marshal_type, buf, tag_name, var_name) 747*a466cc55SCy Schubert ] 7482b15cb3dSCy Schubert return code 7492b15cb3dSCy Schubert 7502b15cb3dSCy Schubert def Declaration(self): 751*a466cc55SCy Schubert dcl = ["%s %s_data;" % (self._ctype, self._name)] 7522b15cb3dSCy Schubert 7532b15cb3dSCy Schubert return dcl 7542b15cb3dSCy Schubert 7552b15cb3dSCy Schubert def CodeInitialize(self, name): 756*a466cc55SCy Schubert code = ["%s->%s_data = 0;" % (name, self._name)] 7572b15cb3dSCy Schubert return code 7582b15cb3dSCy Schubert 759*a466cc55SCy Schubert 7602b15cb3dSCy Schubertclass EntryString(Entry): 761*a466cc55SCy Schubert def __init__(self, ent_type, name, tag): 7622b15cb3dSCy Schubert # Init base class 763*a466cc55SCy Schubert super(EntryString, self).__init__(ent_type, name, tag) 7642b15cb3dSCy Schubert 765*a466cc55SCy Schubert self._can_be_array = True 766*a466cc55SCy Schubert self._ctype = "char *" 7672b15cb3dSCy Schubert 768*a466cc55SCy Schubert @staticmethod 769*a466cc55SCy Schubert def GetInitializer(): 7702b15cb3dSCy Schubert return "NULL" 7712b15cb3dSCy Schubert 772*a466cc55SCy Schubert @staticmethod 773*a466cc55SCy Schubert def CodeArrayFree(varname): 774*a466cc55SCy Schubert code = ["if (%(var)s != NULL) free(%(var)s);"] 7752b15cb3dSCy Schubert 776*a466cc55SCy Schubert return TranslateList(code, {"var": varname}) 7772b15cb3dSCy Schubert 778*a466cc55SCy Schubert @staticmethod 779*a466cc55SCy Schubert def CodeArrayAssign(varname, srcvar): 7802b15cb3dSCy Schubert code = [ 781*a466cc55SCy Schubert "if (%(var)s != NULL)", 782*a466cc55SCy Schubert " free(%(var)s);", 783*a466cc55SCy Schubert "%(var)s = strdup(%(srcvar)s);", 784*a466cc55SCy Schubert "if (%(var)s == NULL) {", 7852b15cb3dSCy Schubert ' event_warnx("%%s: strdup", __func__);', 786*a466cc55SCy Schubert " return (-1);", 787*a466cc55SCy Schubert "}", 788*a466cc55SCy Schubert ] 7892b15cb3dSCy Schubert 790*a466cc55SCy Schubert return TranslateList(code, {"var": varname, "srcvar": srcvar}) 7912b15cb3dSCy Schubert 792*a466cc55SCy Schubert @staticmethod 793*a466cc55SCy Schubert def CodeArrayAdd(varname, value): 7942b15cb3dSCy Schubert code = [ 795*a466cc55SCy Schubert "if (%(value)s != NULL) {", 796*a466cc55SCy Schubert " %(var)s = strdup(%(value)s);", 797*a466cc55SCy Schubert " if (%(var)s == NULL) {", 798*a466cc55SCy Schubert " goto error;", 799*a466cc55SCy Schubert " }", 800*a466cc55SCy Schubert "} else {", 801*a466cc55SCy Schubert " %(var)s = NULL;", 802*a466cc55SCy Schubert "}", 803*a466cc55SCy Schubert ] 8042b15cb3dSCy Schubert 805*a466cc55SCy Schubert return TranslateList(code, {"var": varname, "value": value}) 8062b15cb3dSCy Schubert 8072b15cb3dSCy Schubert def GetVarLen(self, var): 808*a466cc55SCy Schubert return "strlen(%s)" % self.GetVarName(var) 8092b15cb3dSCy Schubert 810*a466cc55SCy Schubert @staticmethod 811*a466cc55SCy Schubert def CodeMakeInitalize(varname): 812*a466cc55SCy Schubert return "%(varname)s = NULL;" % {"varname": varname} 8132b15cb3dSCy Schubert 8142b15cb3dSCy Schubert def CodeAssign(self): 8152b15cb3dSCy Schubert code = """int 8162b15cb3dSCy Schubert%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, 8172b15cb3dSCy Schubert const %(ctype)s value) 8182b15cb3dSCy Schubert{ 8192b15cb3dSCy Schubert if (msg->%(name)s_data != NULL) 8202b15cb3dSCy Schubert free(msg->%(name)s_data); 8212b15cb3dSCy Schubert if ((msg->%(name)s_data = strdup(value)) == NULL) 8222b15cb3dSCy Schubert return (-1); 8232b15cb3dSCy Schubert msg->%(name)s_set = 1; 8242b15cb3dSCy Schubert return (0); 825*a466cc55SCy Schubert}""" % ( 826*a466cc55SCy Schubert self.GetTranslation() 827*a466cc55SCy Schubert ) 8282b15cb3dSCy Schubert 829*a466cc55SCy Schubert return code.split("\n") 8302b15cb3dSCy Schubert 831*a466cc55SCy Schubert def CodeUnmarshal(self, buf, tag_name, var_name, _var_len): 832*a466cc55SCy Schubert code = [ 833*a466cc55SCy Schubert "if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {", 8342b15cb3dSCy Schubert ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 835*a466cc55SCy Schubert " return (-1);", 836*a466cc55SCy Schubert "}", 8372b15cb3dSCy Schubert ] 838*a466cc55SCy Schubert code = "\n".join(code) % self.GetTranslation( 839*a466cc55SCy Schubert {"buf": buf, "tag": tag_name, "var": var_name} 840*a466cc55SCy Schubert ) 841*a466cc55SCy Schubert return code.split("\n") 8422b15cb3dSCy Schubert 843*a466cc55SCy Schubert @staticmethod 844*a466cc55SCy Schubert def CodeMarshal(buf, tag_name, var_name, _var_len): 845*a466cc55SCy Schubert code = ["evtag_marshal_string(%s, %s, %s);" % (buf, tag_name, var_name)] 8462b15cb3dSCy Schubert return code 8472b15cb3dSCy Schubert 8482b15cb3dSCy Schubert def CodeClear(self, structname): 849*a466cc55SCy Schubert code = [ 850*a466cc55SCy Schubert "if (%s->%s_set == 1) {" % (structname, self.Name()), 851*a466cc55SCy Schubert " free(%s->%s_data);" % (structname, self.Name()), 852*a466cc55SCy Schubert " %s->%s_data = NULL;" % (structname, self.Name()), 853*a466cc55SCy Schubert " %s->%s_set = 0;" % (structname, self.Name()), 854*a466cc55SCy Schubert "}", 8552b15cb3dSCy Schubert ] 8562b15cb3dSCy Schubert 8572b15cb3dSCy Schubert return code 8582b15cb3dSCy Schubert 8592b15cb3dSCy Schubert def CodeInitialize(self, name): 860*a466cc55SCy Schubert code = ["%s->%s_data = NULL;" % (name, self._name)] 8612b15cb3dSCy Schubert return code 8622b15cb3dSCy Schubert 8632b15cb3dSCy Schubert def CodeFree(self, name): 864*a466cc55SCy Schubert code = [ 865*a466cc55SCy Schubert "if (%s->%s_data != NULL)" % (name, self._name), 866*a466cc55SCy Schubert " free (%s->%s_data);" % (name, self._name), 867*a466cc55SCy Schubert ] 8682b15cb3dSCy Schubert 8692b15cb3dSCy Schubert return code 8702b15cb3dSCy Schubert 8712b15cb3dSCy Schubert def Declaration(self): 872*a466cc55SCy Schubert dcl = ["char *%s_data;" % self._name] 8732b15cb3dSCy Schubert 8742b15cb3dSCy Schubert return dcl 8752b15cb3dSCy Schubert 876*a466cc55SCy Schubert 8772b15cb3dSCy Schubertclass EntryStruct(Entry): 878*a466cc55SCy Schubert def __init__(self, ent_type, name, tag, refname): 8792b15cb3dSCy Schubert # Init base class 880*a466cc55SCy Schubert super(EntryStruct, self).__init__(ent_type, name, tag) 8812b15cb3dSCy Schubert 8822b15cb3dSCy Schubert self._optpointer = False 883*a466cc55SCy Schubert self._can_be_array = True 8842b15cb3dSCy Schubert self._refname = refname 885*a466cc55SCy Schubert self._ctype = "struct %s*" % refname 8862b15cb3dSCy Schubert self._optaddarg = False 8872b15cb3dSCy Schubert 8882b15cb3dSCy Schubert def GetInitializer(self): 8892b15cb3dSCy Schubert return "NULL" 8902b15cb3dSCy Schubert 891*a466cc55SCy Schubert def GetVarLen(self, _var): 892*a466cc55SCy Schubert return "-1" 8932b15cb3dSCy Schubert 894*a466cc55SCy Schubert def CodeArrayAdd(self, varname, _value): 8952b15cb3dSCy Schubert code = [ 896*a466cc55SCy Schubert "%(varname)s = %(refname)s_new();", 897*a466cc55SCy Schubert "if (%(varname)s == NULL)", 898*a466cc55SCy Schubert " goto error;", 899*a466cc55SCy Schubert ] 9002b15cb3dSCy Schubert 901*a466cc55SCy Schubert return TranslateList(code, self.GetTranslation({"varname": varname})) 9022b15cb3dSCy Schubert 9032b15cb3dSCy Schubert def CodeArrayFree(self, var): 904*a466cc55SCy Schubert code = ["%(refname)s_free(%(var)s);" % self.GetTranslation({"var": var})] 9052b15cb3dSCy Schubert return code 9062b15cb3dSCy Schubert 9072b15cb3dSCy Schubert def CodeArrayAssign(self, var, srcvar): 9082b15cb3dSCy Schubert code = [ 909*a466cc55SCy Schubert "int had_error = 0;", 910*a466cc55SCy Schubert "struct evbuffer *tmp = NULL;", 911*a466cc55SCy Schubert "%(refname)s_clear(%(var)s);", 912*a466cc55SCy Schubert "if ((tmp = evbuffer_new()) == NULL) {", 9132b15cb3dSCy Schubert ' event_warn("%%s: evbuffer_new()", __func__);', 914*a466cc55SCy Schubert " had_error = 1;", 915*a466cc55SCy Schubert " goto done;", 916*a466cc55SCy Schubert "}", 917*a466cc55SCy Schubert "%(refname)s_marshal(tmp, %(srcvar)s);", 918*a466cc55SCy Schubert "if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {", 9192b15cb3dSCy Schubert ' event_warnx("%%s: %(refname)s_unmarshal", __func__);', 920*a466cc55SCy Schubert " had_error = 1;", 921*a466cc55SCy Schubert " goto done;", 922*a466cc55SCy Schubert "}", 923*a466cc55SCy Schubert "done:", 924*a466cc55SCy Schubert "if (tmp != NULL)", 925*a466cc55SCy Schubert " evbuffer_free(tmp);", 926*a466cc55SCy Schubert "if (had_error) {", 927*a466cc55SCy Schubert " %(refname)s_clear(%(var)s);", 928*a466cc55SCy Schubert " return (-1);", 929*a466cc55SCy Schubert "}", 930*a466cc55SCy Schubert ] 9312b15cb3dSCy Schubert 932*a466cc55SCy Schubert return TranslateList(code, self.GetTranslation({"var": var, "srcvar": srcvar})) 9332b15cb3dSCy Schubert 9342b15cb3dSCy Schubert def CodeGet(self): 9352b15cb3dSCy Schubert name = self._name 936*a466cc55SCy Schubert code = [ 937*a466cc55SCy Schubert "int", 938*a466cc55SCy Schubert "%s_%s_get(struct %s *msg, %s *value)" 939*a466cc55SCy Schubert % (self._struct.Name(), name, self._struct.Name(), self._ctype), 940*a466cc55SCy Schubert "{", 941*a466cc55SCy Schubert " if (msg->%s_set != 1) {" % name, 942*a466cc55SCy Schubert " msg->%s_data = %s_new();" % (name, self._refname), 943*a466cc55SCy Schubert " if (msg->%s_data == NULL)" % name, 944*a466cc55SCy Schubert " return (-1);", 945*a466cc55SCy Schubert " msg->%s_set = 1;" % name, 946*a466cc55SCy Schubert " }", 947*a466cc55SCy Schubert " *value = msg->%s_data;" % name, 948*a466cc55SCy Schubert " return (0);", 949*a466cc55SCy Schubert "}", 950*a466cc55SCy Schubert ] 9512b15cb3dSCy Schubert return code 9522b15cb3dSCy Schubert 9532b15cb3dSCy Schubert def CodeAssign(self): 954*a466cc55SCy Schubert code = ( 955*a466cc55SCy Schubert """int 9562b15cb3dSCy Schubert%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, 9572b15cb3dSCy Schubert const %(ctype)s value) 9582b15cb3dSCy Schubert{ 9592b15cb3dSCy Schubert struct evbuffer *tmp = NULL; 9602b15cb3dSCy Schubert if (msg->%(name)s_set) { 9612b15cb3dSCy Schubert %(refname)s_clear(msg->%(name)s_data); 9622b15cb3dSCy Schubert msg->%(name)s_set = 0; 9632b15cb3dSCy Schubert } else { 9642b15cb3dSCy Schubert msg->%(name)s_data = %(refname)s_new(); 9652b15cb3dSCy Schubert if (msg->%(name)s_data == NULL) { 9662b15cb3dSCy Schubert event_warn("%%s: %(refname)s_new()", __func__); 9672b15cb3dSCy Schubert goto error; 9682b15cb3dSCy Schubert } 9692b15cb3dSCy Schubert } 9702b15cb3dSCy Schubert if ((tmp = evbuffer_new()) == NULL) { 9712b15cb3dSCy Schubert event_warn("%%s: evbuffer_new()", __func__); 9722b15cb3dSCy Schubert goto error; 9732b15cb3dSCy Schubert } 9742b15cb3dSCy Schubert %(refname)s_marshal(tmp, value); 9752b15cb3dSCy Schubert if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) { 9762b15cb3dSCy Schubert event_warnx("%%s: %(refname)s_unmarshal", __func__); 9772b15cb3dSCy Schubert goto error; 9782b15cb3dSCy Schubert } 9792b15cb3dSCy Schubert msg->%(name)s_set = 1; 9802b15cb3dSCy Schubert evbuffer_free(tmp); 9812b15cb3dSCy Schubert return (0); 9822b15cb3dSCy Schubert error: 9832b15cb3dSCy Schubert if (tmp != NULL) 9842b15cb3dSCy Schubert evbuffer_free(tmp); 9852b15cb3dSCy Schubert if (msg->%(name)s_data != NULL) { 9862b15cb3dSCy Schubert %(refname)s_free(msg->%(name)s_data); 9872b15cb3dSCy Schubert msg->%(name)s_data = NULL; 9882b15cb3dSCy Schubert } 9892b15cb3dSCy Schubert return (-1); 990*a466cc55SCy Schubert}""" 991*a466cc55SCy Schubert % self.GetTranslation() 992*a466cc55SCy Schubert ) 993*a466cc55SCy Schubert return code.split("\n") 9942b15cb3dSCy Schubert 9952b15cb3dSCy Schubert def CodeComplete(self, structname, var_name): 996*a466cc55SCy Schubert code = [ 997*a466cc55SCy Schubert "if (%(structname)s->%(name)s_set && " 998*a466cc55SCy Schubert "%(refname)s_complete(%(var)s) == -1)", 999*a466cc55SCy Schubert " return (-1);", 10002b15cb3dSCy Schubert ] 10012b15cb3dSCy Schubert 1002*a466cc55SCy Schubert return TranslateList( 1003*a466cc55SCy Schubert code, self.GetTranslation({"structname": structname, "var": var_name}) 1004*a466cc55SCy Schubert ) 1005*a466cc55SCy Schubert 1006*a466cc55SCy Schubert def CodeUnmarshal(self, buf, tag_name, var_name, _var_len): 1007*a466cc55SCy Schubert code = [ 1008*a466cc55SCy Schubert "%(var)s = %(refname)s_new();", 1009*a466cc55SCy Schubert "if (%(var)s == NULL)", 1010*a466cc55SCy Schubert " return (-1);", 1011*a466cc55SCy Schubert "if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag)s, ", 1012*a466cc55SCy Schubert " %(var)s) == -1) {", 1013*a466cc55SCy Schubert ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 1014*a466cc55SCy Schubert " return (-1);", 1015*a466cc55SCy Schubert "}", 1016*a466cc55SCy Schubert ] 1017*a466cc55SCy Schubert code = "\n".join(code) % self.GetTranslation( 1018*a466cc55SCy Schubert {"buf": buf, "tag": tag_name, "var": var_name} 1019*a466cc55SCy Schubert ) 1020*a466cc55SCy Schubert return code.split("\n") 1021*a466cc55SCy Schubert 1022*a466cc55SCy Schubert def CodeMarshal(self, buf, tag_name, var_name, _var_len): 1023*a466cc55SCy Schubert code = [ 1024*a466cc55SCy Schubert "evtag_marshal_%s(%s, %s, %s);" % (self._refname, buf, tag_name, var_name) 1025*a466cc55SCy Schubert ] 10262b15cb3dSCy Schubert return code 10272b15cb3dSCy Schubert 10282b15cb3dSCy Schubert def CodeClear(self, structname): 1029*a466cc55SCy Schubert code = [ 1030*a466cc55SCy Schubert "if (%s->%s_set == 1) {" % (structname, self.Name()), 1031*a466cc55SCy Schubert " %s_free(%s->%s_data);" % (self._refname, structname, self.Name()), 1032*a466cc55SCy Schubert " %s->%s_data = NULL;" % (structname, self.Name()), 1033*a466cc55SCy Schubert " %s->%s_set = 0;" % (structname, self.Name()), 1034*a466cc55SCy Schubert "}", 10352b15cb3dSCy Schubert ] 10362b15cb3dSCy Schubert 10372b15cb3dSCy Schubert return code 10382b15cb3dSCy Schubert 10392b15cb3dSCy Schubert def CodeInitialize(self, name): 1040*a466cc55SCy Schubert code = ["%s->%s_data = NULL;" % (name, self._name)] 10412b15cb3dSCy Schubert return code 10422b15cb3dSCy Schubert 10432b15cb3dSCy Schubert def CodeFree(self, name): 1044*a466cc55SCy Schubert code = [ 1045*a466cc55SCy Schubert "if (%s->%s_data != NULL)" % (name, self._name), 1046*a466cc55SCy Schubert " %s_free(%s->%s_data);" % (self._refname, name, self._name), 1047*a466cc55SCy Schubert ] 10482b15cb3dSCy Schubert 10492b15cb3dSCy Schubert return code 10502b15cb3dSCy Schubert 10512b15cb3dSCy Schubert def Declaration(self): 1052*a466cc55SCy Schubert dcl = ["%s %s_data;" % (self._ctype, self._name)] 10532b15cb3dSCy Schubert 10542b15cb3dSCy Schubert return dcl 10552b15cb3dSCy Schubert 1056*a466cc55SCy Schubert 10572b15cb3dSCy Schubertclass EntryVarBytes(Entry): 1058*a466cc55SCy Schubert def __init__(self, ent_type, name, tag): 10592b15cb3dSCy Schubert # Init base class 1060*a466cc55SCy Schubert super(EntryVarBytes, self).__init__(ent_type, name, tag) 10612b15cb3dSCy Schubert 1062*a466cc55SCy Schubert self._ctype = "ev_uint8_t *" 10632b15cb3dSCy Schubert 1064*a466cc55SCy Schubert @staticmethod 1065*a466cc55SCy Schubert def GetInitializer(): 10662b15cb3dSCy Schubert return "NULL" 10672b15cb3dSCy Schubert 10682b15cb3dSCy Schubert def GetVarLen(self, var): 1069*a466cc55SCy Schubert return "%(var)s->%(name)s_length" % self.GetTranslation({"var": var}) 10702b15cb3dSCy Schubert 1071*a466cc55SCy Schubert @staticmethod 1072*a466cc55SCy Schubert def CodeArrayAdd(varname, _value): 10732b15cb3dSCy Schubert # xxx: copy 1074*a466cc55SCy Schubert return ["%(varname)s = NULL;" % {"varname": varname}] 10752b15cb3dSCy Schubert 10762b15cb3dSCy Schubert def GetDeclaration(self, funcname): 1077*a466cc55SCy Schubert code = [ 1078*a466cc55SCy Schubert "int %s(struct %s *, %s *, ev_uint32_t *);" 1079*a466cc55SCy Schubert % (funcname, self._struct.Name(), self._ctype) 1080*a466cc55SCy Schubert ] 10812b15cb3dSCy Schubert return code 10822b15cb3dSCy Schubert 10832b15cb3dSCy Schubert def AssignDeclaration(self, funcname): 1084*a466cc55SCy Schubert code = [ 1085*a466cc55SCy Schubert "int %s(struct %s *, const %s, ev_uint32_t);" 1086*a466cc55SCy Schubert % (funcname, self._struct.Name(), self._ctype) 1087*a466cc55SCy Schubert ] 10882b15cb3dSCy Schubert return code 10892b15cb3dSCy Schubert 10902b15cb3dSCy Schubert def CodeAssign(self): 10912b15cb3dSCy Schubert name = self._name 1092*a466cc55SCy Schubert code = [ 1093*a466cc55SCy Schubert "int", 1094*a466cc55SCy Schubert "%s_%s_assign(struct %s *msg, " 1095*a466cc55SCy Schubert "const %s value, ev_uint32_t len)" 1096*a466cc55SCy Schubert % (self._struct.Name(), name, self._struct.Name(), self._ctype), 1097*a466cc55SCy Schubert "{", 1098*a466cc55SCy Schubert " if (msg->%s_data != NULL)" % name, 1099*a466cc55SCy Schubert " free (msg->%s_data);" % name, 1100*a466cc55SCy Schubert " msg->%s_data = malloc(len);" % name, 1101*a466cc55SCy Schubert " if (msg->%s_data == NULL)" % name, 1102*a466cc55SCy Schubert " return (-1);", 1103*a466cc55SCy Schubert " msg->%s_set = 1;" % name, 1104*a466cc55SCy Schubert " msg->%s_length = len;" % name, 1105*a466cc55SCy Schubert " memcpy(msg->%s_data, value, len);" % name, 1106*a466cc55SCy Schubert " return (0);", 1107*a466cc55SCy Schubert "}", 1108*a466cc55SCy Schubert ] 11092b15cb3dSCy Schubert return code 11102b15cb3dSCy Schubert 11112b15cb3dSCy Schubert def CodeGet(self): 11122b15cb3dSCy Schubert name = self._name 1113*a466cc55SCy Schubert code = [ 1114*a466cc55SCy Schubert "int", 1115*a466cc55SCy Schubert "%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)" 1116*a466cc55SCy Schubert % (self._struct.Name(), name, self._struct.Name(), self._ctype), 1117*a466cc55SCy Schubert "{", 1118*a466cc55SCy Schubert " if (msg->%s_set != 1)" % name, 1119*a466cc55SCy Schubert " return (-1);", 1120*a466cc55SCy Schubert " *value = msg->%s_data;" % name, 1121*a466cc55SCy Schubert " *plen = msg->%s_length;" % name, 1122*a466cc55SCy Schubert " return (0);", 1123*a466cc55SCy Schubert "}", 1124*a466cc55SCy Schubert ] 11252b15cb3dSCy Schubert return code 11262b15cb3dSCy Schubert 11272b15cb3dSCy Schubert def CodeUnmarshal(self, buf, tag_name, var_name, var_len): 1128*a466cc55SCy Schubert code = [ 1129*a466cc55SCy Schubert "if (evtag_payload_length(%(buf)s, &%(varlen)s) == -1)", 1130*a466cc55SCy Schubert " return (-1);", 11312b15cb3dSCy Schubert # We do not want DoS opportunities 1132*a466cc55SCy Schubert "if (%(varlen)s > evbuffer_get_length(%(buf)s))", 1133*a466cc55SCy Schubert " return (-1);", 1134*a466cc55SCy Schubert "if ((%(var)s = malloc(%(varlen)s)) == NULL)", 1135*a466cc55SCy Schubert " return (-1);", 1136*a466cc55SCy Schubert "if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, %(var)s, " 1137*a466cc55SCy Schubert "%(varlen)s) == -1) {", 11382b15cb3dSCy Schubert ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 1139*a466cc55SCy Schubert " return (-1);", 1140*a466cc55SCy Schubert "}", 11412b15cb3dSCy Schubert ] 1142*a466cc55SCy Schubert code = "\n".join(code) % self.GetTranslation( 1143*a466cc55SCy Schubert {"buf": buf, "tag": tag_name, "var": var_name, "varlen": var_len} 1144*a466cc55SCy Schubert ) 1145*a466cc55SCy Schubert return code.split("\n") 11462b15cb3dSCy Schubert 1147*a466cc55SCy Schubert @staticmethod 1148*a466cc55SCy Schubert def CodeMarshal(buf, tag_name, var_name, var_len): 1149*a466cc55SCy Schubert code = ["evtag_marshal(%s, %s, %s, %s);" % (buf, tag_name, var_name, var_len)] 11502b15cb3dSCy Schubert return code 11512b15cb3dSCy Schubert 11522b15cb3dSCy Schubert def CodeClear(self, structname): 1153*a466cc55SCy Schubert code = [ 1154*a466cc55SCy Schubert "if (%s->%s_set == 1) {" % (structname, self.Name()), 1155*a466cc55SCy Schubert " free (%s->%s_data);" % (structname, self.Name()), 1156*a466cc55SCy Schubert " %s->%s_data = NULL;" % (structname, self.Name()), 1157*a466cc55SCy Schubert " %s->%s_length = 0;" % (structname, self.Name()), 1158*a466cc55SCy Schubert " %s->%s_set = 0;" % (structname, self.Name()), 1159*a466cc55SCy Schubert "}", 11602b15cb3dSCy Schubert ] 11612b15cb3dSCy Schubert 11622b15cb3dSCy Schubert return code 11632b15cb3dSCy Schubert 11642b15cb3dSCy Schubert def CodeInitialize(self, name): 1165*a466cc55SCy Schubert code = [ 1166*a466cc55SCy Schubert "%s->%s_data = NULL;" % (name, self._name), 1167*a466cc55SCy Schubert "%s->%s_length = 0;" % (name, self._name), 1168*a466cc55SCy Schubert ] 11692b15cb3dSCy Schubert return code 11702b15cb3dSCy Schubert 11712b15cb3dSCy Schubert def CodeFree(self, name): 1172*a466cc55SCy Schubert code = [ 1173*a466cc55SCy Schubert "if (%s->%s_data != NULL)" % (name, self._name), 1174*a466cc55SCy Schubert " free(%s->%s_data);" % (name, self._name), 1175*a466cc55SCy Schubert ] 11762b15cb3dSCy Schubert 11772b15cb3dSCy Schubert return code 11782b15cb3dSCy Schubert 11792b15cb3dSCy Schubert def Declaration(self): 1180*a466cc55SCy Schubert dcl = [ 1181*a466cc55SCy Schubert "ev_uint8_t *%s_data;" % self._name, 1182*a466cc55SCy Schubert "ev_uint32_t %s_length;" % self._name, 1183*a466cc55SCy Schubert ] 11842b15cb3dSCy Schubert 11852b15cb3dSCy Schubert return dcl 11862b15cb3dSCy Schubert 1187*a466cc55SCy Schubert 11882b15cb3dSCy Schubertclass EntryArray(Entry): 1189*a466cc55SCy Schubert _index = None 1190*a466cc55SCy Schubert 11912b15cb3dSCy Schubert def __init__(self, entry): 11922b15cb3dSCy Schubert # Init base class 1193*a466cc55SCy Schubert super(EntryArray, self).__init__(entry._type, entry._name, entry._tag) 11942b15cb3dSCy Schubert 11952b15cb3dSCy Schubert self._entry = entry 11962b15cb3dSCy Schubert self._refname = entry._refname 11972b15cb3dSCy Schubert self._ctype = self._entry._ctype 11982b15cb3dSCy Schubert self._optional = True 11992b15cb3dSCy Schubert self._optpointer = self._entry._optpointer 12002b15cb3dSCy Schubert self._optaddarg = self._entry._optaddarg 12012b15cb3dSCy Schubert 12022b15cb3dSCy Schubert # provide a new function for accessing the variable name 12032b15cb3dSCy Schubert def GetVarName(var_name): 1204*a466cc55SCy Schubert return "%(var)s->%(name)s_data[%(index)s]" % self._entry.GetTranslation( 1205*a466cc55SCy Schubert {"var": var_name, "index": self._index} 1206*a466cc55SCy Schubert ) 1207*a466cc55SCy Schubert 12082b15cb3dSCy Schubert self._entry.GetVarName = GetVarName 12092b15cb3dSCy Schubert 12102b15cb3dSCy Schubert def GetInitializer(self): 12112b15cb3dSCy Schubert return "NULL" 12122b15cb3dSCy Schubert 1213*a466cc55SCy Schubert def GetVarName(self, var): 1214*a466cc55SCy Schubert return var 12152b15cb3dSCy Schubert 1216*a466cc55SCy Schubert def GetVarLen(self, _var_name): 1217*a466cc55SCy Schubert return "-1" 12182b15cb3dSCy Schubert 12192b15cb3dSCy Schubert def GetDeclaration(self, funcname): 12202b15cb3dSCy Schubert """Allows direct access to elements of the array.""" 12212b15cb3dSCy Schubert code = [ 1222*a466cc55SCy Schubert "int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);" 1223*a466cc55SCy Schubert % self.GetTranslation({"funcname": funcname}) 1224*a466cc55SCy Schubert ] 12252b15cb3dSCy Schubert return code 12262b15cb3dSCy Schubert 12272b15cb3dSCy Schubert def AssignDeclaration(self, funcname): 1228*a466cc55SCy Schubert code = [ 1229*a466cc55SCy Schubert "int %s(struct %s *, int, const %s);" 1230*a466cc55SCy Schubert % (funcname, self._struct.Name(), self._ctype) 1231*a466cc55SCy Schubert ] 12322b15cb3dSCy Schubert return code 12332b15cb3dSCy Schubert 12342b15cb3dSCy Schubert def AddDeclaration(self, funcname): 12352b15cb3dSCy Schubert code = [ 1236*a466cc55SCy Schubert "%(ctype)s %(optpointer)s " 1237*a466cc55SCy Schubert "%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);" 1238*a466cc55SCy Schubert % self.GetTranslation({"funcname": funcname}) 1239*a466cc55SCy Schubert ] 12402b15cb3dSCy Schubert return code 12412b15cb3dSCy Schubert 12422b15cb3dSCy Schubert def CodeGet(self): 12432b15cb3dSCy Schubert code = """int 12442b15cb3dSCy Schubert%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset, 12452b15cb3dSCy Schubert %(ctype)s *value) 12462b15cb3dSCy Schubert{ 12472b15cb3dSCy Schubert if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length) 12482b15cb3dSCy Schubert return (-1); 12492b15cb3dSCy Schubert *value = msg->%(name)s_data[offset]; 12502b15cb3dSCy Schubert return (0); 1251*a466cc55SCy Schubert} 1252*a466cc55SCy Schubert""" % ( 1253*a466cc55SCy Schubert self.GetTranslation() 1254*a466cc55SCy Schubert ) 12552b15cb3dSCy Schubert 1256*a466cc55SCy Schubert return code.splitlines() 12572b15cb3dSCy Schubert 12582b15cb3dSCy Schubert def CodeAssign(self): 12592b15cb3dSCy Schubert code = [ 1260*a466cc55SCy Schubert "int", 1261*a466cc55SCy Schubert "%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,", 1262*a466cc55SCy Schubert " const %(ctype)s value)", 1263*a466cc55SCy Schubert "{", 1264*a466cc55SCy Schubert " if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)", 1265*a466cc55SCy Schubert " return (-1);", 1266*a466cc55SCy Schubert "", 1267*a466cc55SCy Schubert " {", 1268*a466cc55SCy Schubert ] 12692b15cb3dSCy Schubert code = TranslateList(code, self.GetTranslation()) 12702b15cb3dSCy Schubert 12712b15cb3dSCy Schubert codearrayassign = self._entry.CodeArrayAssign( 1272*a466cc55SCy Schubert "msg->%(name)s_data[off]" % self.GetTranslation(), "value" 1273*a466cc55SCy Schubert ) 1274*a466cc55SCy Schubert code += [" " + x for x in codearrayassign] 12752b15cb3dSCy Schubert 1276*a466cc55SCy Schubert code += TranslateList([" }", " return (0);", "}"], self.GetTranslation()) 12772b15cb3dSCy Schubert 12782b15cb3dSCy Schubert return code 12792b15cb3dSCy Schubert 12802b15cb3dSCy Schubert def CodeAdd(self): 12812b15cb3dSCy Schubert codearrayadd = self._entry.CodeArrayAdd( 1282*a466cc55SCy Schubert "msg->%(name)s_data[msg->%(name)s_length - 1]" % self.GetTranslation(), 1283*a466cc55SCy Schubert "value", 1284*a466cc55SCy Schubert ) 12852b15cb3dSCy Schubert code = [ 1286*a466cc55SCy Schubert "static int", 1287*a466cc55SCy Schubert "%(parent_name)s_%(name)s_expand_to_hold_more(" 1288*a466cc55SCy Schubert "struct %(parent_name)s *msg)", 1289*a466cc55SCy Schubert "{", 1290*a466cc55SCy Schubert " int tobe_allocated = msg->%(name)s_num_allocated;", 1291*a466cc55SCy Schubert " %(ctype)s* new_data = NULL;", 1292*a466cc55SCy Schubert " tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;", 1293*a466cc55SCy Schubert " new_data = (%(ctype)s*) realloc(msg->%(name)s_data,", 1294*a466cc55SCy Schubert " tobe_allocated * sizeof(%(ctype)s));", 1295*a466cc55SCy Schubert " if (new_data == NULL)", 1296*a466cc55SCy Schubert " return -1;", 1297*a466cc55SCy Schubert " msg->%(name)s_data = new_data;", 1298*a466cc55SCy Schubert " msg->%(name)s_num_allocated = tobe_allocated;", 1299*a466cc55SCy Schubert " return 0;", 1300*a466cc55SCy Schubert "}", 1301*a466cc55SCy Schubert "", 1302*a466cc55SCy Schubert "%(ctype)s %(optpointer)s", 1303*a466cc55SCy Schubert "%(parent_name)s_%(name)s_add(struct %(parent_name)s *msg%(optaddarg)s)", 1304*a466cc55SCy Schubert "{", 1305*a466cc55SCy Schubert " if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {", 1306*a466cc55SCy Schubert " if (%(parent_name)s_%(name)s_expand_to_hold_more(msg)<0)", 1307*a466cc55SCy Schubert " goto error;", 1308*a466cc55SCy Schubert " }", 1309*a466cc55SCy Schubert ] 13102b15cb3dSCy Schubert 13112b15cb3dSCy Schubert code = TranslateList(code, self.GetTranslation()) 13122b15cb3dSCy Schubert 1313*a466cc55SCy Schubert code += [" " + x for x in codearrayadd] 13142b15cb3dSCy Schubert 1315*a466cc55SCy Schubert code += TranslateList( 1316*a466cc55SCy Schubert [ 1317*a466cc55SCy Schubert " msg->%(name)s_set = 1;", 1318*a466cc55SCy Schubert " return %(optreference)s(msg->%(name)s_data[" 1319*a466cc55SCy Schubert "msg->%(name)s_length - 1]);", 1320*a466cc55SCy Schubert "error:", 1321*a466cc55SCy Schubert " --msg->%(name)s_length;", 1322*a466cc55SCy Schubert " return (NULL);", 1323*a466cc55SCy Schubert "}", 1324*a466cc55SCy Schubert ], 1325*a466cc55SCy Schubert self.GetTranslation(), 1326*a466cc55SCy Schubert ) 13272b15cb3dSCy Schubert 13282b15cb3dSCy Schubert return code 13292b15cb3dSCy Schubert 13302b15cb3dSCy Schubert def CodeComplete(self, structname, var_name): 1331*a466cc55SCy Schubert self._index = "i" 13322b15cb3dSCy Schubert tmp = self._entry.CodeComplete(structname, self._entry.GetVarName(var_name)) 13332b15cb3dSCy Schubert # skip the whole loop if there is nothing to check 13342b15cb3dSCy Schubert if not tmp: 13352b15cb3dSCy Schubert return [] 13362b15cb3dSCy Schubert 1337*a466cc55SCy Schubert translate = self.GetTranslation({"structname": structname}) 13382b15cb3dSCy Schubert code = [ 1339*a466cc55SCy Schubert "{", 1340*a466cc55SCy Schubert " int i;", 1341*a466cc55SCy Schubert " for (i = 0; i < %(structname)s->%(name)s_length; ++i) {", 1342*a466cc55SCy Schubert ] 13432b15cb3dSCy Schubert 13442b15cb3dSCy Schubert code = TranslateList(code, translate) 13452b15cb3dSCy Schubert 1346*a466cc55SCy Schubert code += [" " + x for x in tmp] 13472b15cb3dSCy Schubert 1348*a466cc55SCy Schubert code += [" }", "}"] 13492b15cb3dSCy Schubert 13502b15cb3dSCy Schubert return code 13512b15cb3dSCy Schubert 1352*a466cc55SCy Schubert def CodeUnmarshal(self, buf, tag_name, var_name, _var_len): 1353*a466cc55SCy Schubert translate = self.GetTranslation( 1354*a466cc55SCy Schubert { 1355*a466cc55SCy Schubert "var": var_name, 1356*a466cc55SCy Schubert "buf": buf, 1357*a466cc55SCy Schubert "tag": tag_name, 1358*a466cc55SCy Schubert "init": self._entry.GetInitializer(), 1359*a466cc55SCy Schubert } 1360*a466cc55SCy Schubert ) 13612b15cb3dSCy Schubert code = [ 1362*a466cc55SCy Schubert "if (%(var)s->%(name)s_length >= %(var)s->%(name)s_num_allocated &&", 1363*a466cc55SCy Schubert " %(parent_name)s_%(name)s_expand_to_hold_more(%(var)s) < 0) {", 13642b15cb3dSCy Schubert ' puts("HEY NOW");', 1365*a466cc55SCy Schubert " return (-1);", 1366*a466cc55SCy Schubert "}", 1367*a466cc55SCy Schubert ] 13682b15cb3dSCy Schubert 13692b15cb3dSCy Schubert # the unmarshal code directly returns 13702b15cb3dSCy Schubert code = TranslateList(code, translate) 13712b15cb3dSCy Schubert 1372*a466cc55SCy Schubert self._index = "%(var)s->%(name)s_length" % translate 1373*a466cc55SCy Schubert code += self._entry.CodeUnmarshal( 1374*a466cc55SCy Schubert buf, 1375*a466cc55SCy Schubert tag_name, 13762b15cb3dSCy Schubert self._entry.GetVarName(var_name), 1377*a466cc55SCy Schubert self._entry.GetVarLen(var_name), 1378*a466cc55SCy Schubert ) 13792b15cb3dSCy Schubert 1380*a466cc55SCy Schubert code += ["++%(var)s->%(name)s_length;" % translate] 13812b15cb3dSCy Schubert 13822b15cb3dSCy Schubert return code 13832b15cb3dSCy Schubert 1384*a466cc55SCy Schubert def CodeMarshal(self, buf, tag_name, var_name, _var_len): 1385*a466cc55SCy Schubert code = ["{", " int i;", " for (i = 0; i < %(var)s->%(name)s_length; ++i) {"] 13862b15cb3dSCy Schubert 1387*a466cc55SCy Schubert self._index = "i" 1388*a466cc55SCy Schubert code += self._entry.CodeMarshal( 1389*a466cc55SCy Schubert buf, 1390*a466cc55SCy Schubert tag_name, 13912b15cb3dSCy Schubert self._entry.GetVarName(var_name), 1392*a466cc55SCy Schubert self._entry.GetVarLen(var_name), 1393*a466cc55SCy Schubert ) 1394*a466cc55SCy Schubert code += [" }", "}"] 13952b15cb3dSCy Schubert 1396*a466cc55SCy Schubert code = "\n".join(code) % self.GetTranslation({"var": var_name}) 13972b15cb3dSCy Schubert 1398*a466cc55SCy Schubert return code.split("\n") 13992b15cb3dSCy Schubert 14002b15cb3dSCy Schubert def CodeClear(self, structname): 1401*a466cc55SCy Schubert translate = self.GetTranslation({"structname": structname}) 14022b15cb3dSCy Schubert codearrayfree = self._entry.CodeArrayFree( 1403*a466cc55SCy Schubert "%(structname)s->%(name)s_data[i]" 1404*a466cc55SCy Schubert % self.GetTranslation({"structname": structname}) 1405*a466cc55SCy Schubert ) 14062b15cb3dSCy Schubert 1407*a466cc55SCy Schubert code = ["if (%(structname)s->%(name)s_set == 1) {"] 14082b15cb3dSCy Schubert 14092b15cb3dSCy Schubert if codearrayfree: 14102b15cb3dSCy Schubert code += [ 1411*a466cc55SCy Schubert " int i;", 1412*a466cc55SCy Schubert " for (i = 0; i < %(structname)s->%(name)s_length; ++i) {", 1413*a466cc55SCy Schubert ] 14142b15cb3dSCy Schubert 14152b15cb3dSCy Schubert code = TranslateList(code, translate) 14162b15cb3dSCy Schubert 14172b15cb3dSCy Schubert if codearrayfree: 1418*a466cc55SCy Schubert code += [" " + x for x in codearrayfree] 1419*a466cc55SCy Schubert code += [" }"] 14202b15cb3dSCy Schubert 1421*a466cc55SCy Schubert code += TranslateList( 1422*a466cc55SCy Schubert [ 1423*a466cc55SCy Schubert " free(%(structname)s->%(name)s_data);", 1424*a466cc55SCy Schubert " %(structname)s->%(name)s_data = NULL;", 1425*a466cc55SCy Schubert " %(structname)s->%(name)s_set = 0;", 1426*a466cc55SCy Schubert " %(structname)s->%(name)s_length = 0;", 1427*a466cc55SCy Schubert " %(structname)s->%(name)s_num_allocated = 0;", 1428*a466cc55SCy Schubert "}", 1429*a466cc55SCy Schubert ], 1430*a466cc55SCy Schubert translate, 1431*a466cc55SCy Schubert ) 14322b15cb3dSCy Schubert 14332b15cb3dSCy Schubert return code 14342b15cb3dSCy Schubert 14352b15cb3dSCy Schubert def CodeInitialize(self, name): 1436*a466cc55SCy Schubert code = [ 1437*a466cc55SCy Schubert "%s->%s_data = NULL;" % (name, self._name), 1438*a466cc55SCy Schubert "%s->%s_length = 0;" % (name, self._name), 1439*a466cc55SCy Schubert "%s->%s_num_allocated = 0;" % (name, self._name), 1440*a466cc55SCy Schubert ] 14412b15cb3dSCy Schubert return code 14422b15cb3dSCy Schubert 14432b15cb3dSCy Schubert def CodeFree(self, structname): 1444*a466cc55SCy Schubert code = self.CodeClear(structname) 14452b15cb3dSCy Schubert 1446*a466cc55SCy Schubert code += TranslateList( 1447*a466cc55SCy Schubert ["free(%(structname)s->%(name)s_data);"], 1448*a466cc55SCy Schubert self.GetTranslation({"structname": structname}), 1449*a466cc55SCy Schubert ) 14502b15cb3dSCy Schubert 14512b15cb3dSCy Schubert return code 14522b15cb3dSCy Schubert 14532b15cb3dSCy Schubert def Declaration(self): 1454*a466cc55SCy Schubert dcl = [ 1455*a466cc55SCy Schubert "%s *%s_data;" % (self._ctype, self._name), 1456*a466cc55SCy Schubert "int %s_length;" % self._name, 1457*a466cc55SCy Schubert "int %s_num_allocated;" % self._name, 1458*a466cc55SCy Schubert ] 14592b15cb3dSCy Schubert 14602b15cb3dSCy Schubert return dcl 14612b15cb3dSCy Schubert 14622b15cb3dSCy Schubert 1463*a466cc55SCy Schubertdef NormalizeLine(line): 1464*a466cc55SCy Schubert 1465*a466cc55SCy Schubert line = CPPCOMMENT_RE.sub("", line) 14662b15cb3dSCy Schubert line = line.strip() 1467*a466cc55SCy Schubert line = WHITESPACE_RE.sub(" ", line) 14682b15cb3dSCy Schubert 14692b15cb3dSCy Schubert return line 14702b15cb3dSCy Schubert 1471*a466cc55SCy Schubert 1472*a466cc55SCy SchubertENTRY_NAME_RE = re.compile(r"(?P<name>[^\[\]]+)(\[(?P<fixed_length>.*)\])?") 1473*a466cc55SCy SchubertENTRY_TAG_NUMBER_RE = re.compile(r"(0x)?\d+", re.I) 1474*a466cc55SCy Schubert 1475*a466cc55SCy Schubert 14762b15cb3dSCy Schubertdef ProcessOneEntry(factory, newstruct, entry): 1477*a466cc55SCy Schubert optional = False 1478*a466cc55SCy Schubert array = False 1479*a466cc55SCy Schubert entry_type = "" 1480*a466cc55SCy Schubert name = "" 1481*a466cc55SCy Schubert tag = "" 14822b15cb3dSCy Schubert tag_set = None 1483*a466cc55SCy Schubert separator = "" 1484*a466cc55SCy Schubert fixed_length = "" 14852b15cb3dSCy Schubert 1486*a466cc55SCy Schubert for token in entry.split(" "): 14872b15cb3dSCy Schubert if not entry_type: 1488*a466cc55SCy Schubert if not optional and token == "optional": 1489*a466cc55SCy Schubert optional = True 14902b15cb3dSCy Schubert continue 14912b15cb3dSCy Schubert 1492*a466cc55SCy Schubert if not array and token == "array": 1493*a466cc55SCy Schubert array = True 14942b15cb3dSCy Schubert continue 14952b15cb3dSCy Schubert 14962b15cb3dSCy Schubert if not entry_type: 14972b15cb3dSCy Schubert entry_type = token 14982b15cb3dSCy Schubert continue 14992b15cb3dSCy Schubert 15002b15cb3dSCy Schubert if not name: 1501*a466cc55SCy Schubert res = ENTRY_NAME_RE.match(token) 15022b15cb3dSCy Schubert if not res: 15032b15cb3dSCy Schubert raise RpcGenError( 1504*a466cc55SCy Schubert r"""Cannot parse name: "%s" around line %d""" % (entry, LINE_COUNT) 1505*a466cc55SCy Schubert ) 1506*a466cc55SCy Schubert name = res.group("name") 1507*a466cc55SCy Schubert fixed_length = res.group("fixed_length") 15082b15cb3dSCy Schubert continue 15092b15cb3dSCy Schubert 15102b15cb3dSCy Schubert if not separator: 15112b15cb3dSCy Schubert separator = token 1512*a466cc55SCy Schubert if separator != "=": 1513*a466cc55SCy Schubert raise RpcGenError( 1514*a466cc55SCy Schubert r'''Expected "=" after name "%s" got "%s"''' % (name, token) 1515*a466cc55SCy Schubert ) 15162b15cb3dSCy Schubert continue 15172b15cb3dSCy Schubert 15182b15cb3dSCy Schubert if not tag_set: 15192b15cb3dSCy Schubert tag_set = 1 1520*a466cc55SCy Schubert if not ENTRY_TAG_NUMBER_RE.match(token): 1521*a466cc55SCy Schubert raise RpcGenError(r'''Expected tag number: "%s"''' % (entry)) 15222b15cb3dSCy Schubert tag = int(token, 0) 15232b15cb3dSCy Schubert continue 15242b15cb3dSCy Schubert 1525*a466cc55SCy Schubert raise RpcGenError(r'''Cannot parse "%s"''' % (entry)) 15262b15cb3dSCy Schubert 15272b15cb3dSCy Schubert if not tag_set: 1528*a466cc55SCy Schubert raise RpcGenError(r'''Need tag number: "%s"''' % (entry)) 15292b15cb3dSCy Schubert 15302b15cb3dSCy Schubert # Create the right entry 1531*a466cc55SCy Schubert if entry_type == "bytes": 15322b15cb3dSCy Schubert if fixed_length: 15332b15cb3dSCy Schubert newentry = factory.EntryBytes(entry_type, name, tag, fixed_length) 15342b15cb3dSCy Schubert else: 15352b15cb3dSCy Schubert newentry = factory.EntryVarBytes(entry_type, name, tag) 1536*a466cc55SCy Schubert elif entry_type == "int" and not fixed_length: 15372b15cb3dSCy Schubert newentry = factory.EntryInt(entry_type, name, tag) 1538*a466cc55SCy Schubert elif entry_type == "int64" and not fixed_length: 15392b15cb3dSCy Schubert newentry = factory.EntryInt(entry_type, name, tag, bits=64) 1540*a466cc55SCy Schubert elif entry_type == "string" and not fixed_length: 15412b15cb3dSCy Schubert newentry = factory.EntryString(entry_type, name, tag) 15422b15cb3dSCy Schubert else: 1543*a466cc55SCy Schubert res = STRUCT_REF_RE.match(entry_type) 15442b15cb3dSCy Schubert if res: 15452b15cb3dSCy Schubert # References another struct defined in our file 1546*a466cc55SCy Schubert newentry = factory.EntryStruct(entry_type, name, tag, res.group("name")) 15472b15cb3dSCy Schubert else: 15482b15cb3dSCy Schubert raise RpcGenError('Bad type: "%s" in "%s"' % (entry_type, entry)) 15492b15cb3dSCy Schubert 15502b15cb3dSCy Schubert structs = [] 15512b15cb3dSCy Schubert 15522b15cb3dSCy Schubert if optional: 15532b15cb3dSCy Schubert newentry.MakeOptional() 15542b15cb3dSCy Schubert if array: 15552b15cb3dSCy Schubert newentry.MakeArray() 15562b15cb3dSCy Schubert 15572b15cb3dSCy Schubert newentry.SetStruct(newstruct) 1558*a466cc55SCy Schubert newentry.SetLineCount(LINE_COUNT) 15592b15cb3dSCy Schubert newentry.Verify() 15602b15cb3dSCy Schubert 15612b15cb3dSCy Schubert if array: 15622b15cb3dSCy Schubert # We need to encapsulate this entry into a struct 15632b15cb3dSCy Schubert newentry = factory.EntryArray(newentry) 15642b15cb3dSCy Schubert newentry.SetStruct(newstruct) 1565*a466cc55SCy Schubert newentry.SetLineCount(LINE_COUNT) 15662b15cb3dSCy Schubert newentry.MakeArray() 15672b15cb3dSCy Schubert 15682b15cb3dSCy Schubert newstruct.AddEntry(newentry) 15692b15cb3dSCy Schubert 15702b15cb3dSCy Schubert return structs 15712b15cb3dSCy Schubert 1572*a466cc55SCy Schubert 15732b15cb3dSCy Schubertdef ProcessStruct(factory, data): 1574*a466cc55SCy Schubert tokens = data.split(" ") 15752b15cb3dSCy Schubert 15762b15cb3dSCy Schubert # First three tokens are: 'struct' 'name' '{' 15772b15cb3dSCy Schubert newstruct = factory.Struct(tokens[1]) 15782b15cb3dSCy Schubert 1579*a466cc55SCy Schubert inside = " ".join(tokens[3:-1]) 15802b15cb3dSCy Schubert 1581*a466cc55SCy Schubert tokens = inside.split(";") 15822b15cb3dSCy Schubert 15832b15cb3dSCy Schubert structs = [] 15842b15cb3dSCy Schubert 15852b15cb3dSCy Schubert for entry in tokens: 15862b15cb3dSCy Schubert entry = NormalizeLine(entry) 15872b15cb3dSCy Schubert if not entry: 15882b15cb3dSCy Schubert continue 15892b15cb3dSCy Schubert 15902b15cb3dSCy Schubert # It's possible that new structs get defined in here 15912b15cb3dSCy Schubert structs.extend(ProcessOneEntry(factory, newstruct, entry)) 15922b15cb3dSCy Schubert 15932b15cb3dSCy Schubert structs.append(newstruct) 15942b15cb3dSCy Schubert return structs 15952b15cb3dSCy Schubert 15962b15cb3dSCy Schubert 1597*a466cc55SCy SchubertC_COMMENT_START = "/*" 1598*a466cc55SCy SchubertC_COMMENT_END = "*/" 15992b15cb3dSCy Schubert 1600*a466cc55SCy SchubertC_COMMENT_START_RE = re.compile(re.escape(C_COMMENT_START)) 1601*a466cc55SCy SchubertC_COMMENT_END_RE = re.compile(re.escape(C_COMMENT_END)) 16022b15cb3dSCy Schubert 1603*a466cc55SCy SchubertC_COMMENT_START_SUB_RE = re.compile(r"%s.*$" % (re.escape(C_COMMENT_START))) 1604*a466cc55SCy SchubertC_COMMENT_END_SUB_RE = re.compile(r"%s.*$" % (re.escape(C_COMMENT_END))) 1605*a466cc55SCy Schubert 1606*a466cc55SCy SchubertC_MULTILINE_COMMENT_SUB_RE = re.compile( 1607*a466cc55SCy Schubert r"%s.*?%s" % (re.escape(C_COMMENT_START), re.escape(C_COMMENT_END)) 1608*a466cc55SCy Schubert) 1609*a466cc55SCy SchubertCPP_CONDITIONAL_BLOCK_RE = re.compile(r"#(if( |def)|endif)") 1610*a466cc55SCy SchubertINCLUDE_RE = re.compile(r'#include (".+"|<.+>)') 1611*a466cc55SCy Schubert 1612*a466cc55SCy Schubert 1613*a466cc55SCy Schubertdef GetNextStruct(filep): 1614*a466cc55SCy Schubert global CPP_DIRECT 1615*a466cc55SCy Schubert global LINE_COUNT 1616*a466cc55SCy Schubert 1617*a466cc55SCy Schubert got_struct = False 1618*a466cc55SCy Schubert have_c_comment = False 1619*a466cc55SCy Schubert 1620*a466cc55SCy Schubert data = "" 1621*a466cc55SCy Schubert 1622*a466cc55SCy Schubert while True: 1623*a466cc55SCy Schubert line = filep.readline() 16242b15cb3dSCy Schubert if not line: 16252b15cb3dSCy Schubert break 16262b15cb3dSCy Schubert 1627*a466cc55SCy Schubert LINE_COUNT += 1 16282b15cb3dSCy Schubert line = line[:-1] 16292b15cb3dSCy Schubert 1630*a466cc55SCy Schubert if not have_c_comment and C_COMMENT_START_RE.search(line): 1631*a466cc55SCy Schubert if C_MULTILINE_COMMENT_SUB_RE.search(line): 1632*a466cc55SCy Schubert line = C_MULTILINE_COMMENT_SUB_RE.sub("", line) 16332b15cb3dSCy Schubert else: 1634*a466cc55SCy Schubert line = C_COMMENT_START_SUB_RE.sub("", line) 1635*a466cc55SCy Schubert have_c_comment = True 16362b15cb3dSCy Schubert 16372b15cb3dSCy Schubert if have_c_comment: 1638*a466cc55SCy Schubert if not C_COMMENT_END_RE.search(line): 16392b15cb3dSCy Schubert continue 1640*a466cc55SCy Schubert have_c_comment = False 1641*a466cc55SCy Schubert line = C_COMMENT_END_SUB_RE.sub("", line) 16422b15cb3dSCy Schubert 16432b15cb3dSCy Schubert line = NormalizeLine(line) 16442b15cb3dSCy Schubert 16452b15cb3dSCy Schubert if not line: 16462b15cb3dSCy Schubert continue 16472b15cb3dSCy Schubert 16482b15cb3dSCy Schubert if not got_struct: 1649*a466cc55SCy Schubert if INCLUDE_RE.match(line): 1650*a466cc55SCy Schubert CPP_DIRECT.append(line) 1651*a466cc55SCy Schubert elif CPP_CONDITIONAL_BLOCK_RE.match(line): 1652*a466cc55SCy Schubert CPP_DIRECT.append(line) 1653*a466cc55SCy Schubert elif PREPROCESSOR_DEF_RE.match(line): 1654*a466cc55SCy Schubert HEADER_DIRECT.append(line) 1655*a466cc55SCy Schubert elif not STRUCT_DEF_RE.match(line): 1656*a466cc55SCy Schubert raise RpcGenError("Missing struct on line %d: %s" % (LINE_COUNT, line)) 16572b15cb3dSCy Schubert else: 1658*a466cc55SCy Schubert got_struct = True 16592b15cb3dSCy Schubert data += line 16602b15cb3dSCy Schubert continue 16612b15cb3dSCy Schubert 16622b15cb3dSCy Schubert # We are inside the struct 1663*a466cc55SCy Schubert tokens = line.split("}") 16642b15cb3dSCy Schubert if len(tokens) == 1: 1665*a466cc55SCy Schubert data += " " + line 16662b15cb3dSCy Schubert continue 16672b15cb3dSCy Schubert 1668*a466cc55SCy Schubert if tokens[1]: 1669*a466cc55SCy Schubert raise RpcGenError("Trailing garbage after struct on line %d" % LINE_COUNT) 16702b15cb3dSCy Schubert 16712b15cb3dSCy Schubert # We found the end of the struct 1672*a466cc55SCy Schubert data += " %s}" % tokens[0] 16732b15cb3dSCy Schubert break 16742b15cb3dSCy Schubert 16752b15cb3dSCy Schubert # Remove any comments, that might be in there 1676*a466cc55SCy Schubert data = re.sub(r"/\*.*\*/", "", data) 16772b15cb3dSCy Schubert 16782b15cb3dSCy Schubert return data 16792b15cb3dSCy Schubert 16802b15cb3dSCy Schubert 1681*a466cc55SCy Schubertdef Parse(factory, filep): 16822b15cb3dSCy Schubert """ 16832b15cb3dSCy Schubert Parses the input file and returns C code and corresponding header file. 16842b15cb3dSCy Schubert """ 16852b15cb3dSCy Schubert 16862b15cb3dSCy Schubert entities = [] 16872b15cb3dSCy Schubert 16882b15cb3dSCy Schubert while 1: 16892b15cb3dSCy Schubert # Just gets the whole struct nicely formatted 1690*a466cc55SCy Schubert data = GetNextStruct(filep) 16912b15cb3dSCy Schubert 16922b15cb3dSCy Schubert if not data: 16932b15cb3dSCy Schubert break 16942b15cb3dSCy Schubert 16952b15cb3dSCy Schubert entities.extend(ProcessStruct(factory, data)) 16962b15cb3dSCy Schubert 16972b15cb3dSCy Schubert return entities 16982b15cb3dSCy Schubert 1699*a466cc55SCy Schubert 1700*a466cc55SCy Schubertclass CCodeGenerator(object): 17012b15cb3dSCy Schubert def __init__(self): 17022b15cb3dSCy Schubert pass 17032b15cb3dSCy Schubert 1704*a466cc55SCy Schubert @staticmethod 1705*a466cc55SCy Schubert def GuardName(name): 17062b15cb3dSCy Schubert # Use the complete provided path to the input file, with all 17072b15cb3dSCy Schubert # non-identifier characters replaced with underscores, to 17082b15cb3dSCy Schubert # reduce the chance of a collision between guard macros. 1709*a466cc55SCy Schubert return "EVENT_RPCOUT_%s_" % (NONIDENT_RE.sub("_", name).upper()) 17102b15cb3dSCy Schubert 17112b15cb3dSCy Schubert def HeaderPreamble(self, name): 17122b15cb3dSCy Schubert guard = self.GuardName(name) 1713*a466cc55SCy Schubert pre = """ 1714*a466cc55SCy Schubert/* 1715*a466cc55SCy Schubert * Automatically generated from %s 1716*a466cc55SCy Schubert */ 17172b15cb3dSCy Schubert 1718*a466cc55SCy Schubert#ifndef %s 1719*a466cc55SCy Schubert#define %s 17202b15cb3dSCy Schubert 1721*a466cc55SCy Schubert""" % ( 1722*a466cc55SCy Schubert name, 1723*a466cc55SCy Schubert guard, 1724*a466cc55SCy Schubert guard, 17252b15cb3dSCy Schubert ) 17262b15cb3dSCy Schubert 1727*a466cc55SCy Schubert if HEADER_DIRECT: 1728*a466cc55SCy Schubert for statement in HEADER_DIRECT: 1729*a466cc55SCy Schubert pre += "%s\n" % statement 1730*a466cc55SCy Schubert pre += "\n" 1731*a466cc55SCy Schubert 1732*a466cc55SCy Schubert pre += """ 1733*a466cc55SCy Schubert#include <event2/util.h> /* for ev_uint*_t */ 1734*a466cc55SCy Schubert#include <event2/rpc.h> 1735*a466cc55SCy Schubert""" 1736*a466cc55SCy Schubert 17372b15cb3dSCy Schubert return pre 17382b15cb3dSCy Schubert 17392b15cb3dSCy Schubert def HeaderPostamble(self, name): 17402b15cb3dSCy Schubert guard = self.GuardName(name) 1741*a466cc55SCy Schubert return "#endif /* %s */" % (guard) 17422b15cb3dSCy Schubert 1743*a466cc55SCy Schubert @staticmethod 1744*a466cc55SCy Schubert def BodyPreamble(name, header_file): 17452b15cb3dSCy Schubert global _NAME 17462b15cb3dSCy Schubert global _VERSION 17472b15cb3dSCy Schubert 1748*a466cc55SCy Schubert slash = header_file.rfind("/") 17492b15cb3dSCy Schubert if slash != -1: 17502b15cb3dSCy Schubert header_file = header_file[slash + 1 :] 17512b15cb3dSCy Schubert 1752*a466cc55SCy Schubert pre = """ 1753*a466cc55SCy Schubert/* 1754*a466cc55SCy Schubert * Automatically generated from %(name)s 1755*a466cc55SCy Schubert * by %(script_name)s/%(script_version)s. DO NOT EDIT THIS FILE. 1756*a466cc55SCy Schubert */ 17572b15cb3dSCy Schubert 1758*a466cc55SCy Schubert#include <stdlib.h> 1759*a466cc55SCy Schubert#include <string.h> 1760*a466cc55SCy Schubert#include <assert.h> 1761*a466cc55SCy Schubert#include <event2/event-config.h> 1762*a466cc55SCy Schubert#include <event2/event.h> 1763*a466cc55SCy Schubert#include <event2/buffer.h> 1764*a466cc55SCy Schubert#include <event2/tag.h> 1765*a466cc55SCy Schubert 1766*a466cc55SCy Schubert#if defined(EVENT__HAVE___func__) 1767*a466cc55SCy Schubert# ifndef __func__ 1768*a466cc55SCy Schubert# define __func__ __func__ 1769*a466cc55SCy Schubert# endif 1770*a466cc55SCy Schubert#elif defined(EVENT__HAVE___FUNCTION__) 1771*a466cc55SCy Schubert# define __func__ __FUNCTION__ 1772*a466cc55SCy Schubert#else 1773*a466cc55SCy Schubert# define __func__ __FILE__ 1774*a466cc55SCy Schubert#endif 1775*a466cc55SCy Schubert 1776*a466cc55SCy Schubert""" % { 1777*a466cc55SCy Schubert "name": name, 1778*a466cc55SCy Schubert "script_name": _NAME, 1779*a466cc55SCy Schubert "script_version": _VERSION, 1780*a466cc55SCy Schubert } 1781*a466cc55SCy Schubert 1782*a466cc55SCy Schubert for statement in CPP_DIRECT: 1783*a466cc55SCy Schubert pre += "%s\n" % statement 17842b15cb3dSCy Schubert 17852b15cb3dSCy Schubert pre += '\n#include "%s"\n\n' % header_file 17862b15cb3dSCy Schubert 1787*a466cc55SCy Schubert pre += "void event_warn(const char *fmt, ...);\n" 1788*a466cc55SCy Schubert pre += "void event_warnx(const char *fmt, ...);\n\n" 17892b15cb3dSCy Schubert 17902b15cb3dSCy Schubert return pre 17912b15cb3dSCy Schubert 1792*a466cc55SCy Schubert @staticmethod 1793*a466cc55SCy Schubert def HeaderFilename(filename): 1794*a466cc55SCy Schubert return ".".join(filename.split(".")[:-1]) + ".h" 17952b15cb3dSCy Schubert 1796*a466cc55SCy Schubert @staticmethod 1797*a466cc55SCy Schubert def CodeFilename(filename): 1798*a466cc55SCy Schubert return ".".join(filename.split(".")[:-1]) + ".gen.c" 17992b15cb3dSCy Schubert 1800*a466cc55SCy Schubert @staticmethod 1801*a466cc55SCy Schubert def Struct(name): 18022b15cb3dSCy Schubert return StructCCode(name) 18032b15cb3dSCy Schubert 1804*a466cc55SCy Schubert @staticmethod 1805*a466cc55SCy Schubert def EntryBytes(entry_type, name, tag, fixed_length): 18062b15cb3dSCy Schubert return EntryBytes(entry_type, name, tag, fixed_length) 18072b15cb3dSCy Schubert 1808*a466cc55SCy Schubert @staticmethod 1809*a466cc55SCy Schubert def EntryVarBytes(entry_type, name, tag): 18102b15cb3dSCy Schubert return EntryVarBytes(entry_type, name, tag) 18112b15cb3dSCy Schubert 1812*a466cc55SCy Schubert @staticmethod 1813*a466cc55SCy Schubert def EntryInt(entry_type, name, tag, bits=32): 18142b15cb3dSCy Schubert return EntryInt(entry_type, name, tag, bits) 18152b15cb3dSCy Schubert 1816*a466cc55SCy Schubert @staticmethod 1817*a466cc55SCy Schubert def EntryString(entry_type, name, tag): 18182b15cb3dSCy Schubert return EntryString(entry_type, name, tag) 18192b15cb3dSCy Schubert 1820*a466cc55SCy Schubert @staticmethod 1821*a466cc55SCy Schubert def EntryStruct(entry_type, name, tag, struct_name): 18222b15cb3dSCy Schubert return EntryStruct(entry_type, name, tag, struct_name) 18232b15cb3dSCy Schubert 1824*a466cc55SCy Schubert @staticmethod 1825*a466cc55SCy Schubert def EntryArray(entry): 18262b15cb3dSCy Schubert return EntryArray(entry) 18272b15cb3dSCy Schubert 18282b15cb3dSCy Schubert 1829*a466cc55SCy Schubertclass CommandLine(object): 1830*a466cc55SCy Schubert def __init__(self, argv=None): 18312b15cb3dSCy Schubert """Initialize a command-line to launch event_rpcgen, as if 18322b15cb3dSCy Schubert from a command-line with CommandLine(sys.argv). If you're 18332b15cb3dSCy Schubert calling this directly, remember to provide a dummy value 18342b15cb3dSCy Schubert for sys.argv[0] 18352b15cb3dSCy Schubert """ 1836*a466cc55SCy Schubert global QUIETLY 1837*a466cc55SCy Schubert 18382b15cb3dSCy Schubert self.filename = None 18392b15cb3dSCy Schubert self.header_file = None 18402b15cb3dSCy Schubert self.impl_file = None 18412b15cb3dSCy Schubert self.factory = CCodeGenerator() 18422b15cb3dSCy Schubert 1843*a466cc55SCy Schubert parser = argparse.ArgumentParser( 1844*a466cc55SCy Schubert usage="%(prog)s [options] rpc-file [[h-file] c-file]" 1845*a466cc55SCy Schubert ) 1846*a466cc55SCy Schubert parser.add_argument("--quiet", action="store_true", default=False) 1847*a466cc55SCy Schubert parser.add_argument("rpc_file", type=argparse.FileType("r")) 18482b15cb3dSCy Schubert 1849*a466cc55SCy Schubert args, extra_args = parser.parse_known_args(args=argv) 18502b15cb3dSCy Schubert 1851*a466cc55SCy Schubert QUIETLY = args.quiet 18522b15cb3dSCy Schubert 1853*a466cc55SCy Schubert if extra_args: 1854*a466cc55SCy Schubert if len(extra_args) == 1: 1855*a466cc55SCy Schubert self.impl_file = extra_args[0].replace("\\", "/") 1856*a466cc55SCy Schubert elif len(extra_args) == 2: 1857*a466cc55SCy Schubert self.header_file = extra_args[0].replace("\\", "/") 1858*a466cc55SCy Schubert self.impl_file = extra_args[1].replace("\\", "/") 1859*a466cc55SCy Schubert else: 1860*a466cc55SCy Schubert parser.error("Spurious arguments provided") 1861*a466cc55SCy Schubert 1862*a466cc55SCy Schubert self.rpc_file = args.rpc_file 18632b15cb3dSCy Schubert 18642b15cb3dSCy Schubert if not self.impl_file: 1865*a466cc55SCy Schubert self.impl_file = self.factory.CodeFilename(self.rpc_file.name) 18662b15cb3dSCy Schubert 18672b15cb3dSCy Schubert if not self.header_file: 18682b15cb3dSCy Schubert self.header_file = self.factory.HeaderFilename(self.impl_file) 18692b15cb3dSCy Schubert 1870*a466cc55SCy Schubert if not self.impl_file.endswith(".c"): 1871*a466cc55SCy Schubert parser.error("can only generate C implementation files") 1872*a466cc55SCy Schubert if not self.header_file.endswith(".h"): 1873*a466cc55SCy Schubert parser.error("can only generate C header files") 18742b15cb3dSCy Schubert 18752b15cb3dSCy Schubert def run(self): 1876*a466cc55SCy Schubert filename = self.rpc_file.name 18772b15cb3dSCy Schubert header_file = self.header_file 18782b15cb3dSCy Schubert impl_file = self.impl_file 18792b15cb3dSCy Schubert factory = self.factory 18802b15cb3dSCy Schubert 1881*a466cc55SCy Schubert declare('Reading "%s"' % filename) 18822b15cb3dSCy Schubert 1883*a466cc55SCy Schubert with self.rpc_file: 1884*a466cc55SCy Schubert entities = Parse(factory, self.rpc_file) 18852b15cb3dSCy Schubert 18862b15cb3dSCy Schubert declare('... creating "%s"' % header_file) 1887*a466cc55SCy Schubert with open(header_file, "w") as header_fp: 1888*a466cc55SCy Schubert header_fp.write(factory.HeaderPreamble(filename)) 18892b15cb3dSCy Schubert 18902b15cb3dSCy Schubert # Create forward declarations: allows other structs to reference 18912b15cb3dSCy Schubert # each other 18922b15cb3dSCy Schubert for entry in entities: 18932b15cb3dSCy Schubert entry.PrintForwardDeclaration(header_fp) 1894*a466cc55SCy Schubert header_fp.write("\n") 18952b15cb3dSCy Schubert 18962b15cb3dSCy Schubert for entry in entities: 18972b15cb3dSCy Schubert entry.PrintTags(header_fp) 18982b15cb3dSCy Schubert entry.PrintDeclaration(header_fp) 1899*a466cc55SCy Schubert header_fp.write(factory.HeaderPostamble(filename)) 19002b15cb3dSCy Schubert 19012b15cb3dSCy Schubert declare('... creating "%s"' % impl_file) 1902*a466cc55SCy Schubert with open(impl_file, "w") as impl_fp: 1903*a466cc55SCy Schubert impl_fp.write(factory.BodyPreamble(filename, header_file)) 19042b15cb3dSCy Schubert for entry in entities: 19052b15cb3dSCy Schubert entry.PrintCode(impl_fp) 19062b15cb3dSCy Schubert 1907*a466cc55SCy Schubert 1908*a466cc55SCy Schubertdef main(argv=None): 19092b15cb3dSCy Schubert try: 1910*a466cc55SCy Schubert CommandLine(argv=argv).run() 1911*a466cc55SCy Schubert return 0 1912*a466cc55SCy Schubert except RpcGenError as e: 1913*a466cc55SCy Schubert sys.stderr.write(e) 1914*a466cc55SCy Schubert except EnvironmentError as e: 19152b15cb3dSCy Schubert if e.filename and e.strerror: 1916*a466cc55SCy Schubert sys.stderr.write("%s: %s" % (e.filename, e.strerror)) 19172b15cb3dSCy Schubert elif e.strerror: 1918*a466cc55SCy Schubert sys.stderr.write(e.strerror) 19192b15cb3dSCy Schubert else: 19202b15cb3dSCy Schubert raise 1921*a466cc55SCy Schubert return 1 1922*a466cc55SCy Schubert 1923*a466cc55SCy Schubert 1924*a466cc55SCy Schubertif __name__ == "__main__": 1925*a466cc55SCy Schubert sys.exit(main(argv=sys.argv[1:])) 1926