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